Update to bsnes v016r42 release.

Ok, one semi-large change if anyone wants to test.

             byuu.cinnamonpirate.com/files/bsnes_v016_wip42.zip

 This is built for maximum speed. No debugger, PGO enabled, favor
speed, no c++ EH (so no ZIP/JMA), and a new addition: links against
msvcrt instead of libcmt.

 By using msvcrt and some evil linker hacks I was finally able to
build the SDL port again on Windows. So now I just need to focus on
cleaning that up so the next release will build on Linux out of the
box. Anyway, I tried it on the non-SDL port for the hell of it, and
noticed not only a 20% drop in EXE size, but a ~10-11% speedup as
well. Only problem is it requires msvcr80.dll, and I have no idea how
common that file is. So, that's what this wip is for. Does this
version work for you, and if it does, does it run faster? A direct FPS
comparison between v0.016 and v0.016.42 would be helpful if you're not
sure.
This commit is contained in:
byuu 2006-08-04 01:27:04 +00:00
parent 6010bffe5d
commit a55d640459
66 changed files with 1044 additions and 1358 deletions

189
bsnes.cfg Normal file
View File

@ -0,0 +1,189 @@
# Default path to look for ROM files in ("" = use default directory)
# (default = "")
fs.rom_path = ""
# Default path for all save RAM and cheat files ("" = use current directory)
# (default = "")
fs.save_path = ""
# Extension to be used for all save RAM files
# (default = "srm")
fs.save_ext = "srm"
# Use precalculated TV-style gamma ramp
# (default = true)
snes.colorfilter.gamma_ramp = true
# Convert color to sepia tone
# (default = false)
snes.colorfilter.sepia = false
# Convert color to grayscale tone
# (default = false)
snes.colorfilter.grayscale = false
# Invert output image colors
# (default = false)
snes.colorfilter.invert = false
#
# (default = 0)
snes.colorfilter.contrast = 0
#
# (default = 0)
snes.colorfilter.brightness = 0
#
# (default = 80)
snes.colorfilter.gamma = 80
# Merge fields in NTSC video filter
# Set to true if using filter at any refresh rate other than 60hz
#
# (default = true)
snes.ntsc_merge_fields = true
# Mutes SNES audio output when enabled
# (default = false)
snes.mute = true
# Regulate speed to 60hz (NTSC) / 50hz (PAL)
# (default = true)
system.regulate_speed = false
# Slowest speed setting (in hz)
# (default = 16000)
system.speed_slowest = 16000
# Slow speed setting
# (default = 24000)
system.speed_slow = 24000
# Normal speed setting
# (default = 32000)
system.speed_normal = 32000
# Fast speed setting
# (default = 48000)
system.speed_fast = 48000
# Fastest speed setting
# (default = 64000)
system.speed_fastest = 64000
# Video renderer
# "dd" (DirectDraw7 -- faster, less features)
# "d3d" (Direct3D9 -- slower, more features)
# (default = "d3d")
video.renderer = "d3d"
#
# (default = 2)
video.profile = 0
# Video profile 0-7 configuration
# Please use bsnes GUI configuration editor to modify video profile settings
# Format: software_filter;hardware_filter;video_standard;multiplier-1;correct_aspect_ratio;
# enable_scanlines;manual_render_size;render_width;render_height;
# resolution_width;resolution_height;refresh_rate;triple_buffering
# (default = "0;0;0;0;false;false;false;256;224;0;0;0;false")
video.profile_0 = "0;0;0;0;false;false;false;256;239;0;0;0;false"
#
# (default = "0;0;0;1;false;false;false;512;448;0;0;0;false")
video.profile_1 = "0;0;0;1;false;false;false;512;448;0;0;0;false"
#
# (default = "0;1;0;1;true;false;false;597;448;0;0;0;false")
video.profile_2 = "0;1;0;1;true;false;false;597;448;0;0;0;false"
#
# (default = "0;1;0;2;true;false;false;896;672;0;0;0;false")
video.profile_3 = "0;1;0;2;true;false;false;896;672;0;0;0;false"
#
# (default = "0;1;0;3;true;false;false;1195;896;0;0;0;false")
video.profile_4 = "0;1;0;3;true;false;false;1195;896;0;0;0;false"
#
# (default = "0;0;0;0;false;false;false;256;224;0;0;0;false")
video.profile_5 = "0;0;0;0;false;false;false;256;224;0;0;0;false"
#
# (default = "0;0;0;0;false;false;false;256;224;0;0;0;false")
video.profile_6 = "0;0;0;0;false;false;false;256;224;0;0;0;false"
#
# (default = "0;0;0;0;false;false;false;256;224;0;0;0;false")
video.profile_7 = "0;0;0;0;false;false;false;256;224;0;0;0;false"
# Use Video RAM instead of System RAM
# (default = true)
video.use_vram = true
# Use triple buffering
# (default = false)
video.triple_buffering = false
# Progressive scanline intensity
# Value is percentage of intensity from 0 to 100
# (default = 30)
video.pscanline_intensity = 30
# Interlace scanline intensity
# (default = 50)
video.iscanline_intensity = 50
# Axis resistance for all analog joypads
# Affects responsiveness of analog stick movement by specifying what percentage
# in any given direction the axis must be pressed to trigger a button press.
# In other words, this determines how hard you have to press the analog stick to
# simulate pressing e.g. left or right on a digital joypad.
# Value is a percentage, from 0 (axis will trigger with virtually any axis movement)
# up to 100 (axis must be pressed fully to given corner).
# Value affects all four directions of the axis equally.
# Note: Values below 10 or above 90 are not recommended and may not work at all.
# (default = 75)
input.axis_resistance = 75
# Allow up+down and left+right key combinations for joypad 1 (not recommended)
# (default = false)
input.joypad1.allow_invalid_input = false
# Joypad 1 button map
# Format: Up; Down; Left; Right; A; B; X; Y; L; R; Select; Start
# (default = "up | joypad0.up; down | joypad0.down; left | joypad0.left; right | joypad0.right; x | joypad0.button3; z | joypad0.button2; s | joypad0.button1; a | joypad0.button0; d | joypad0.button6; c | joypad0.button7; rshift | joypad0.button4; enter | joypad0.button5")
input.joypad1.map = "up | joypad0.up; down | joypad0.down; left | joypad0.left; right | joypad0.right; x | joypad0.button3; z | joypad0.button2; s | joypad0.button1; a | joypad0.button0; d | joypad0.button6; c | joypad0.button7; rshift | joypad0.button4; enter | joypad0.button5"
# Allow up+down and left+right key combinations for joypad 2 (not recommended)
# (default = false)
input.joypad2.allow_invalid_input = false
# Joypad 2 button map
# Format: Up; Down; Left; Right; A; B; X; Y; L; R; Select; Start
# (default = "t | joypad1.up; g | joypad1.down; f | joypad1.left; h | joypad1.right; k | joypad1.button3; j | joypad1.button2; i | joypad1.button1; u | joypad1.button0; o | joypad1.button6; l | joypad1.button7; lbracket | joypad1.button4; rbracket | joypad1.button5")
input.joypad2.map = "t | joypad1.up; g | joypad1.down; f | joypad1.left; h | joypad1.right; k | joypad1.button3; j | joypad1.button2; i | joypad1.button1; u | joypad1.button0; o | joypad1.button6; l | joypad1.button7; lbracket | joypad1.button4; rbracket | joypad1.button5"
# Number of lines buffered for debugger console
# (default = 100)
debugger.console_lines = 100
# Image format for screenshots
# Valid formats: "bmp", "png", "jpg"
# (default = "png")
misc.image_format = "png"
# Window style for main emulation window
# (default = "titlebar|frame|minimize|dragmove")
misc.window_style = "titlebar|frame|minimize|dragmove"
# Show framerate
# (default = true)
misc.show_fps = true
# Alpha level (opacity) of configuration window
# Value must be between 64 (25% opaque, 75% transparent) and 255 (100% opaque)
# (default = 255)
misc.config_window_alpha_level = 255

BIN
bsnes.exe

Binary file not shown.

BIN
bsnes_pgo.exe Normal file

Binary file not shown.

View File

@ -1,4 +1,4 @@
#define BSNES_VERSION "0.016.38"
#define BSNES_VERSION "0.016.42"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#define MEMCORE bMemBus
@ -20,7 +20,7 @@
//#define JMA_SUPPORT
//debugging extensions (~10% speed hit)
#define DEBUGGER
//#define DEBUGGER
//snes core polymorphism
//(allow mem/cpu/apu/ppu overriding, ~10% speed hit)

View File

@ -45,7 +45,7 @@ SNES::VideoColorAdjust SNES::contrast(&config_file, "snes.colorfilter.contrast",
SNES::VideoColorAdjust SNES::brightness(&config_file, "snes.colorfilter.brightness",
"", 0, Setting::DEC);
SNES::VideoColorAdjust SNES::gamma(&config_file, "snes.colorfilter.gamma",
"", 100, Setting::DEC);
"", 80, Setting::DEC);
void SNES::VideoColorAdjust::set(uint32 _data) {
Setting::set(_data);

View File

@ -233,9 +233,6 @@ void sCPU::hdma_init() {
void sCPU::dma_power() {
for(int i = 0; i < 8; i++) {
channel[i].dma_enabled = false;
channel[i].hdma_enabled = false;
channel[i].dmap = 0xff;
channel[i].direction = 1;
channel[i].hdma_indirect = true;
@ -260,6 +257,9 @@ void sCPU::dma_power() {
void sCPU::dma_reset() {
for(int i = 0; i < 8; i++) {
channel[i].dma_enabled = false;
channel[i].hdma_enabled = false;
channel[i].hdma_completed = false;
channel[i].hdma_do_transfer = false;
}

View File

@ -51,8 +51,7 @@ uint8 sCPU::mmio_r4016() {
uint8 r = regs.mdr & 0xfc;
r |= status.joypad1_bits & 1;
if(status.joypad_strobe_latch == 0) {
status.joypad1_bits >>= 1;
status.joypad1_bits |= ~0xffff;
status.joypad1_bits = asr<1>(status.joypad1_bits);
}
return r;
@ -66,8 +65,7 @@ uint8 sCPU::mmio_r4017() {
uint8 r = (regs.mdr & 0xe0) | 0x1c;
r |= status.joypad2_bits & 1;
if(status.joypad_strobe_latch == 0) {
status.joypad2_bits >>= 1;
status.joypad2_bits |= ~0xffff;
status.joypad2_bits = asr<1>(status.joypad2_bits);
}
return r;

View File

@ -1,5 +1,5 @@
/*
libbase : version 0.08a ~byuu (07/14/06)
libbase : version 0.08b ~byuu (07/30/06)
*/
#ifndef __LIBBASE
@ -100,18 +100,47 @@ enum { b = 1 << (bits - 1), m = (1 << (bits - 1)) - 1 };
return (x > m) ? m : (x < -b) ? -b : x;
}
//requires compiler SAR (shift arithmetic right) support
template<int bits> inline signed sclip(const signed x) {
enum { s = sizeof(x) * 8 - bits };
return (x << s) >> s;
enum { b = 1 << (bits - 1), m = (1 << (bits - 1)) - 1 };
return (x & b) ? (x | ~m) : (x & m);
}
//use this if compiler uses SLR (shift logical right)
//requires compiler arithmetic shift right support
//c++ standard does not define whether >> is arithmetic or logical
//template<int bits> inline signed sclip(const signed x) {
//enum { b = 1 << (bits - 1), m = (1 << (bits - 1)) - 1 };
// return (x & b) ? (x | ~m) : (x & m);
//enum { s = sizeof(x) * 8 - bits };
// return (x << s) >> s;
//}
template<int bits, typename T> inline T rol(const T x) {
enum { s = (sizeof(T) << 3) - bits };
return (x << bits) | (x >> s);
}
template<int bits, typename T> inline T ror(const T x) {
enum { s = (sizeof(T) << 3) - bits };
return (x >> bits) | (x << s);
}
template<int bits, typename T> inline T asl(const T x) {
return (x << bits);
}
template<int bits, typename T> inline T asr(const T x) {
enum { h = 1 << ((sizeof(T) << 3) - 1) };
enum { m = ~((1 << ((sizeof(T) << 3) - bits)) - 1) };
return (x >> bits) | ((0 - !!(x & h)) & m);
}
template<int bits, typename T> inline T lsl(const T x) {
return (x << bits);
}
template<int bits, typename T> inline T lsr(const T x) {
enum { m = ((1 << ((sizeof(T) << 3) - bits)) - 1) };
return (x >> bits) & m;
}
template<unsigned bits, typename base = uint> class uint_t {
private:
base data;

View File

@ -1,5 +1,5 @@
/*
libco_win32 : version 0.04 ~byuu (05/11/06)
libco_win32 : version 0.06 ~byuu (05/21/06)
win32-x86 implementation of libco
*/
@ -7,7 +7,7 @@
#define _WIN32_WINNT 0x0400
#include <windows.h>
#include "libco.h"
#include "libco_win32.h"
namespace libco_win32 {
bool co_enabled = false;
@ -20,16 +20,16 @@ namespace libco_win32 {
}
};
extern "C" void co_init() {
void co_init() {
if(libco_win32::co_enabled == true)return;
libco_win32::co_enabled = true;
ConvertThreadToFiber(0);
}
extern "C" void co_term() {
void co_term() {
/*****
//ConverFiberToThread() only exists in WinXP+
//ConverFiberToThread() only exists on WinXP+
if(libco_win32::co_enabled == false)return;
libco_win32::co_enabled = false;
@ -38,31 +38,31 @@ extern "C" void co_term() {
*****/
}
extern "C" thread_t co_active() {
thread_t co_active() {
if(libco_win32::co_enabled == false)co_init();
return GetCurrentFiber();
}
extern "C" thread_t co_create(thread_p coentry, unsigned int heapsize) {
thread_t co_create(thread_p coentry, unsigned int heapsize) {
if(libco_win32::co_enabled == false)co_init();
return CreateFiber(heapsize, libco_win32::coentry_proc, (void*)coentry);
}
extern "C" void co_delete(thread_t cothread) {
void co_delete(thread_t cothread) {
DeleteFiber(cothread);
}
extern "C" void co_jump(thread_t cothread) {
void co_jump(thread_t cothread) {
SwitchToFiber(cothread);
}
extern "C" void co_call(thread_t cothread) {
void co_call(thread_t cothread) {
libco_win32::co_stack[libco_win32::co_stackptr++] = co_active();
co_jump(cothread);
}
extern "C" void co_return() {
void co_return() {
co_jump(libco_win32::co_stack[--libco_win32::co_stackptr]);
}

15
src/lib/libco_win32.h Normal file
View File

@ -0,0 +1,15 @@
/*
libco_win32 : version 0.06 ~byuu (05/21/2006)
*/
typedef void (*thread_t);
typedef void (*thread_p)();
void co_init();
void co_term();
thread_t co_active();
thread_t co_create(thread_p coentry, unsigned int heapsize);
void co_delete(thread_t cothread);
void co_jump(thread_t cothread);
void co_call(thread_t cothread);
void co_return();

View File

@ -1,13 +1,17 @@
/*
libkeymap : version 0.01 ~byuu (07/14/06)
libkeymap : version 0.02 ~byuu (07/30/06)
*/
#ifndef __LIBKEYMAP
#define __LIBKEYMAP
class keymap {
private:
char tmp[32];
public:
uint null;
uint esc;
uint f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12;
uint print_screen, scroll_lock, pause;
@ -30,8 +34,14 @@ uint tab, enter, space;
uint lctrl, rctrl, lalt, ralt, lshift, rshift;
uint lwin, rwin, menu;
struct {
uint up, down, left, right;
uint button[128];
} joypad[16];
uint find(const char *key) {
#define match(n) if(!strcmp(#n, key))return n;
match(null)
match(esc)
match(f1) match(f2) match(f3) match(f4) match(f5) match(f6)
match(f7) match(f8) match(f9) match(f10) match(f11) match(f12)
@ -62,10 +72,32 @@ uint lwin, rwin, menu;
match(ralt) match(lshift) match(rshift)
match(lwin) match(rwin) match(menu)
#undef match
if(!memcmp(key, "joypad", 6)) {
const char *p = key + 6;
int joy, bn, n;
sscanf(p, "%d%n", &joy, &n);
p += n;
if(*p == '.') {
p++;
if(!strcmp(p, "up")) { return joypad[joy].up; }
if(!strcmp(p, "down")) { return joypad[joy].down; }
if(!strcmp(p, "left")) { return joypad[joy].left; }
if(!strcmp(p, "right")) { return joypad[joy].right; }
if(!memcmp(p, "button", 6)) {
p += 6;
sscanf(p, "%d", &bn);
return joypad[joy].button[bn];
}
}
}
return 0;
}
const char *find(uint key) {
#define match(n) if(n == key)return #n;
match(null)
match(esc)
match(f1) match(f2) match(f3) match(f4) match(f5) match(f6)
match(f7) match(f8) match(f9) match(f10) match(f11) match(f12)
@ -96,9 +128,22 @@ uint lwin, rwin, menu;
match(ralt) match(lshift) match(rshift)
match(lwin) match(rwin) match(menu)
#undef match
for(int joy = 0; joy < 16; joy++) {
if(joypad[joy].up == key) { sprintf(tmp, "joypad%d.up", joy); return tmp; }
if(joypad[joy].down == key) { sprintf(tmp, "joypad%d.down", joy); return tmp; }
if(joypad[joy].left == key) { sprintf(tmp, "joypad%d.left", joy); return tmp; }
if(joypad[joy].right == key) { sprintf(tmp, "joypad%d.right", joy); return tmp; }
for(int bn = 0; bn < 128; bn++) {
if(joypad[joy].button[bn] == key) { sprintf(tmp, "joypad%d.button%d", joy, bn); return tmp; }
}
}
return "null";
}
keymap() {
null = 0;
esc = 0;
f1 = f2 = f3 = f4 = f5 = f6 = 0;
f7 = f8 = f9 = f10 = f11 = f12 = 0;
@ -122,6 +167,14 @@ uint lwin, rwin, menu;
tab = enter = space = 0;
lctrl = rctrl = lalt = ralt = lshift = rshift = 0;
lwin = rwin = menu = 0;
for(int joy = 0; joy < 16; joy++) {
joypad[joy].up = 0;
joypad[joy].down = 0;
joypad[joy].left = 0;
joypad[joy].right = 0;
memset(joypad[joy].button, 0, sizeof(joypad[joy].button));
}
}
};

View File

@ -45,7 +45,7 @@ void bMemBus::load_cart() {
cart_map_system();
uint region = read(0xffd9) & 0x7f;
cartridge.info.region = (region == 0 || region == 1 || region == 13) ? Cartridge::NTSC : Cartridge::PAL;
cartridge.info.region = (region <= 1 || region >= 13) ? Cartridge::NTSC : Cartridge::PAL;
if(cartridge.info.region == Cartridge::NTSC) {
snes->set_region(SNES::NTSC);
} else {

View File

@ -18,7 +18,7 @@ void bPPU::scanline() {
if(line.y == 1) {
//mosaic reset
for(int32 bg = BG1; bg <= BG4; bg++) {
for(int bg = BG1; bg <= BG4; bg++) {
regs.bg_y[bg] = 1;
}
@ -32,7 +32,7 @@ void bPPU::scanline() {
regs.oam_firstsprite = (regs.oam_addr >> 2) & 127;
}
} else {
for(int32 bg = BG1; bg <= BG4; bg++) {
for(int bg = BG1; bg <= BG4; bg++) {
if(!regs.mosaic_enabled[bg] || !regs.mosaic_countdown) {
regs.bg_y[bg] = line.y;
}
@ -88,25 +88,6 @@ void bPPU::power() {
region = snes->region();
reset();
}
void bPPU::reset() {
PPU::reset();
frame();
memset(sprite_list, 0, sizeof(sprite_list));
//open bus support
regs.ppu1_mdr = 0xff;
regs.ppu2_mdr = 0xff;
//bg line counters
regs.bg_y[0] = 0;
regs.bg_y[1] = 0;
regs.bg_y[2] = 0;
regs.bg_y[3] = 0;
//$2100
regs.display_disabled = 0;
regs.display_brightness = 0;
@ -135,12 +116,12 @@ void bPPU::reset() {
regs.hires = false;
//$2106
regs.mosaic_size = 0;
regs.mosaic_enabled[BG1] = false;
regs.mosaic_enabled[BG2] = false;
regs.mosaic_enabled[BG3] = false;
regs.mosaic_enabled[BG4] = false;
regs.mosaic_countdown = 0;
regs.mosaic_size = 0;
regs.mosaic_enabled[BG1] = false;
regs.mosaic_enabled[BG2] = false;
regs.mosaic_enabled[BG3] = false;
regs.mosaic_enabled[BG4] = false;
regs.mosaic_countdown = 0;
//$2107-$210a
regs.bg_scaddr[BG1] = 0x0000;
@ -159,7 +140,7 @@ void bPPU::reset() {
regs.bg_tdaddr[BG4] = 0x0000;
//$210d-$2114
regs.bg_ofslatch = 0x00;
regs.bg_ofslatch = 0x00;
regs.m7_hofs = regs.m7_vofs = 0x0000;
regs.bg_hofs[BG1] = regs.bg_vofs[BG1] = 0x0000;
regs.bg_hofs[BG2] = regs.bg_vofs[BG2] = 0x0000;
@ -304,7 +285,26 @@ void bPPU::reset() {
regs.time_over = false;
regs.range_over = false;
line.width = 256; //needed for clear_window_cache()
reset();
}
void bPPU::reset() {
PPU::reset();
frame();
memset(sprite_list, 0, sizeof(sprite_list));
//open bus support
regs.ppu1_mdr = 0xff;
regs.ppu2_mdr = 0xff;
//bg line counters
regs.bg_y[0] = 0;
regs.bg_y[1] = 0;
regs.bg_y[2] = 0;
regs.bg_y[3] = 0;
line.width = 256;
clear_tiledata_cache();
}
@ -376,21 +376,21 @@ bPPU::bPPU() {
init_tiledata_cache();
for(int32 l = 0; l < 16; l++) {
for(int l = 0; l < 16; l++) {
mosaic_table[l] = (uint16*)malloc(4096 * 2);
for(int32 i = 0; i < 4096; i++) {
for(int i = 0; i < 4096; i++) {
mosaic_table[l][i] = (i / (l + 1)) * (l + 1);
}
}
light_table = (uint16*)malloc(16 * 32768 * 2);
uint16 *ptr = (uint16*)light_table;
for(int32 l = 0; l < 16; l++) {
int32 r, g, b;
for(int l = 0; l < 16; l++) {
int r, g, b;
#if 0
double y, cb, cr;
double kr = 0.2126, kb = 0.0722, kg = (1.0 - kr - kb);
for(int32 i = 0; i < 32768; i++) {
for(int i = 0; i < 32768; i++) {
if(l == 0) { *ptr++ = 0; continue; }
if(l == 15) { *ptr++ = i; continue; }
@ -398,27 +398,27 @@ uint16 *ptr = (uint16*)light_table;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
y = double(r) * kr + double(g) * kg + double(b) * kb;
cb = (double(b) - y) / (2.0 - 2.0 * kb);
cr = (double(r) - y) / (2.0 - 2.0 * kr);
y = (double)r * kr + (double)g * kg + (double)b * kb;
cb = ((double)b - y) / (2.0 - 2.0 * kb);
cr = ((double)r - y) / (2.0 - 2.0 * kr);
y *= double(l) / 15.0;
cb *= double(l) / 15.0;
cr *= double(l) / 15.0;
y *= (double)l / 15.0;
cb *= (double)l / 15.0;
cr *= (double)l / 15.0;
r = y + cr * (2.0 - 2.0 * kr);
b = y + cb * (2.0 - 2.0 * kb);
g = (y - b * kb - r * kr) / kg;
r = (r > 31) ? 31 : ((r < 0) ? 0 : r);
g = (g > 31) ? 31 : ((g < 0) ? 0 : g);
b = (b > 31) ? 31 : ((b < 0) ? 0 : b);
r = minmax<0, 31>(r);
g = minmax<0, 31>(g);
b = minmax<0, 31>(b);
*ptr++ = (r) | (g << 5) | (b << 10);
}
#else
double m = double(l) / 15.0;
for(int32 i = 0; i < 32768; i++) {
double m = (double)l / 15.0;
for(int i = 0; i < 32768; i++) {
if(l == 0) { *ptr++ = 0; continue; }
if(l == 15) { *ptr++ = i; continue; }
@ -426,9 +426,9 @@ uint16 *ptr = (uint16*)light_table;
g = (i >> 5) & 31;
b = (i >> 10) & 31;
r = (int32)(double(r) * m);
g = (int32)(double(g) * m);
b = (int32)(double(b) * m);
r = minmax<0, 31>((int)((double)r * m));
g = minmax<0, 31>((int)((double)g * m));
b = minmax<0, 31>((int)((double)b * m));
*ptr++ = (r) | (g << 5) | (b << 10);
}

View File

@ -1,120 +0,0 @@
CC = cc
CXX = c++
CFLAGS = -O3 -fomit-frame-pointer -ffast-math
CXXFLAGS = $(CFLAGS) -fno-rtti
OBJS = sdlmain.o \
libstring.o libconfig.o libbpf.o \
reader.o cart.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 \
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
all: $(OBJS)
$(CXX) $(CXXFLAGS) $(OBJS) `sdl11-config --cflags --libs` -o bsnes_sdl
clean:
rm *.o
####################
### sdl-specific ###
####################
sdlmain.o: *.cpp *.h
$(CXX) $(CXXFLAGS) -c sdlmain.cpp `sdl11-config --cflags`
#################
### libraries ###
#################
libstring.o: ../lib/*.cpp ../lib/*.h
$(CXX) $(CXXFLAGS) -c ../lib/libstring.cpp
libconfig.o: ../lib/*.cpp ../lib/*.h
$(CXX) $(CXXFLAGS) -c ../lib/libconfig.cpp
libbpf.o: ../lib/*.cpp ../lib/*.h
$(CXX) $(CXXFLAGS) -c ../lib/libbpf.cpp
##############
### memory ###
##############
memory.o: ../memory/memory.cpp ../memory/memory.h
$(CXX) $(CXXFLAGS) -c ../memory/memory.cpp
bmemory.o: ../memory/bmemory/*
$(CXX) $(CXXFLAGS) -c ../memory/bmemory/bmemory.cpp
###########
### cpu ###
###########
cpu.o: ../cpu/*.cpp ../cpu/*.h
$(CXX) $(CXXFLAGS) -c ../cpu/cpu.cpp
bcpu.o: ../cpu/bcpu/*
$(CXX) $(CXXFLAGS) -c ../cpu/bcpu/bcpu.cpp
###########
### apu ###
###########
apu.o: ../apu/*
$(CXX) $(CXXFLAGS) -c ../apu/apu.cpp
bapu.o: ../apu/bapu/*
$(CXX) $(CXXFLAGS) -c ../apu/bapu/bapu.cpp
###########
### dsp ###
###########
bdsp.o: ../dsp/bdsp/*
$(CXX) $(CXXFLAGS) -c ../dsp/bdsp/bdsp.cpp
###########
### ppu ###
###########
ppu.o: ../ppu/*.cpp ../ppu/*.h
$(CXX) $(CXXFLAGS) -c ../ppu/ppu.cpp
bppu.o: ../ppu/bppu/*
$(CXX) $(CXXFLAGS) -c ../ppu/bppu/bppu.cpp
#################
### utilities ###
#################
reader.o: ../reader/*.cpp ../reader/*.h
$(CXX) $(CXXFLAGS) -c ../reader/reader.cpp
cart.o: ../cart/*.cpp ../cart/*.h
$(CXX) $(CXXFLAGS) -c ../cart/cart.cpp
############
### snes ###
############
snes.o: ../snes/*.cpp ../snes/*.h
$(CXX) $(CXXFLAGS) -c ../snes/snes.cpp
#####################
### special chips ###
#####################
srtc.o: ../chip/srtc/*.cpp ../chip/srtc/*.h
$(CXX) $(CXXFLAGS) -c ../chip/srtc/srtc.cpp
sdd1.o: ../chip/sdd1/*.cpp ../chip/sdd1/*.h
$(CXX) $(CXXFLAGS) -c ../chip/sdd1/sdd1.cpp
c4.o: ../chip/c4/*.cpp ../chip/c4/*.h
$(CXX) $(CXXFLAGS) -c ../chip/c4/c4.cpp
############
### zlib ###
############
adler32.o: ../reader/zlib/*.c ../reader/zlib/*.h
$(CC) $(CFLAGS) -c ../reader/zlib/*.c
###########
### jma ###
###########
jma.o: ../reader/jma/*.cpp ../reader/jma/*.h
$(CXX) $(CXXFLAGS) -c ../reader/jma/*.cpp

View File

@ -1,119 +0,0 @@
CC = cl
CFLAGS = /nologo /O2 /EHsc
OBJS = sdlmain.obj \
libstring.obj libconfig.obj libbpf.obj \
reader.obj cart.obj \
memory.obj bmemory.obj \
cpu.obj bcpu.obj \
apu.obj bapu.obj \
bdsp.obj \
ppu.obj bppu.obj \
snes.obj \
srtc.obj sdd1.obj c4.obj
# adler32.obj compress.obj crc32.obj deflate.obj gzio.obj inffast.obj \
# inflate.obj inftrees.obj ioapi.obj trees.obj unzip.obj zip.obj zutil.obj \
# jma.obj jcrc32.obj lzmadec.obj 7zlzma.obj iiostrm.obj inbyte.obj lzma.obj winout.obj
LIBS = kernel32.lib user32.lib gdi32.lib sdlmain.lib sdl.lib
all: $(OBJS)
$(CC) /Febsnes_sdl.exe $(CFLAGS) $(OBJS) $(LIBS)
clean:
del *.obj
####################
### sdl-specific ###
####################
sdlmain.obj: *.cpp *.h
$(CC) $(CFLAGS) /c sdlmain.cpp
#################
### libraries ###
#################
libstring.obj: ../lib/*.cpp ../lib/*.h
$(CC) $(CFLAGS) /c ../lib/libstring.cpp
libconfig.obj: ../lib/*.cpp ../lib/*.h
$(CC) $(CFLAGS) /c ../lib/libconfig.cpp
libbpf.obj: ../lib/*.cpp ../lib/*.h
$(CC) $(CFLAGS) /c ../lib/libbpf.cpp
##############
### memory ###
##############
memory.obj: ../memory/memory.cpp ../memory/memory.h
$(CC) $(CFLAGS) /c ../memory/memory.cpp
bmemory.obj: ../memory/bmemory/*
$(CC) $(CFLAGS) /c ../memory/bmemory/bmemory.cpp
###########
### cpu ###
###########
cpu.obj: ../cpu/*.cpp ../cpu/*.h
$(CC) $(CFLAGS) /c ../cpu/cpu.cpp
bcpu.obj: ../cpu/bcpu/*
$(CC) $(CFLAGS) /c ../cpu/bcpu/bcpu.cpp
###########
### apu ###
###########
apu.obj: ../apu/*
$(CC) $(CFLAGS) /c ../apu/apu.cpp
bapu.obj: ../apu/bapu/*
$(CC) $(CFLAGS) /c ../apu/bapu/bapu.cpp
###########
### dsp ###
###########
bdsp.obj: ../dsp/bdsp/*
$(CC) $(CFLAGS) /c ../dsp/bdsp/bdsp.cpp
###########
### ppu ###
###########
ppu.obj: ../ppu/*.cpp ../ppu/*.h
$(CC) $(CFLAGS) /c ../ppu/ppu.cpp
bppu.obj: ../ppu/bppu/*
$(CC) $(CFLAGS) /c ../ppu/bppu/bppu.cpp
#################
### utilities ###
#################
reader.obj: ../reader/*.cpp ../reader/*.h
$(CC) $(CFLAGS) /c ../reader/reader.cpp
cart.obj: ../cart/*.cpp ../cart/*.h
$(CC) $(CFLAGS) /c ../cart/cart.cpp
############
### snes ###
############
snes.obj: ../snes/*.cpp ../snes/*.h
$(CC) $(CFLAGS) /c ../snes/snes.cpp
#####################
### special chips ###
#####################
srtc.obj: ../chip/srtc/*.cpp ../chip/srtc/*.h
$(CC) $(CFLAGS) /c ../chip/srtc/srtc.cpp
sdd1.obj: ../chip/sdd1/*.cpp ../chip/sdd1/*.h
$(CC) $(CFLAGS) /c ../chip/sdd1/sdd1.cpp
c4.obj: ../chip/c4/*.cpp ../chip/c4/*.h
$(CC) $(CFLAGS) /c ../chip/c4/c4.cpp
############
### zlib ###
############
adler32.obj: ../reader/zlib/*.c ../reader/zlib/*.h
$(CC) $(CFLAGS) /c ../reader/zlib/*.c
###########
### jma ###
###########
jma.obj: ../reader/jma/*.cpp ../reader/jma/*.h
$(CC) $(CFLAGS) /c ../reader/jma/*.cpp

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

@ -1,2 +0,0 @@
@nmake /NOLOGO /f Makefile.win32
@pause

View File

@ -1,3 +0,0 @@
@nmake /NOLOGO /f Makefile.win32 clean
@del output.wav
@del bsnes_sdl.exe

View File

@ -1,32 +0,0 @@
namespace config {
struct Video {
static Setting fullscreen;
static Setting display_width, display_height;
static Setting output_width, output_height;
} video;
Setting Video::fullscreen(&config_file, "video.fullscreen", "Enable fullscreen mode at startup", false, Setting::TRUE_FALSE);
Setting Video::display_width (&config_file, "video.display_width", "Window / Fullscreen width", 320, Setting::DEC);
Setting Video::display_height(&config_file, "video.display_height", "Window / Fullscreen height", 240, Setting::DEC);
Setting Video::output_width (&config_file, "video.output_width", "SNES video output width", 256, Setting::DEC);
Setting Video::output_height (&config_file, "video.output_height", "SNES video output height", 223, Setting::DEC);
struct Input {
struct Joypad {
static Setting up, down, left, right, a, b, x, y, l, r, select, start;
} joypad1;
} input;
Setting Input::Joypad::up (&config_file, "input.joypad1.up", "Joypad1 up", SDLK_UP, Setting::HEX);
Setting Input::Joypad::down (&config_file, "input.joypad1.down", "Joypad1 down", SDLK_DOWN, Setting::HEX);
Setting Input::Joypad::left (&config_file, "input.joypad1.left", "Joypad1 left", SDLK_LEFT, Setting::HEX);
Setting Input::Joypad::right (&config_file, "input.joypad1.right", "Joypad1 right", SDLK_RIGHT, Setting::HEX);
Setting Input::Joypad::a (&config_file, "input.joypad1.a", "Joypad1 A", SDLK_x, Setting::HEX);
Setting Input::Joypad::b (&config_file, "input.joypad1.b", "Joypad1 B", SDLK_z, Setting::HEX);
Setting Input::Joypad::x (&config_file, "input.joypad1.x", "Joypad1 X", SDLK_s, Setting::HEX);
Setting Input::Joypad::y (&config_file, "input.joypad1.y", "Joypad1 Y", SDLK_a, Setting::HEX);
Setting Input::Joypad::l (&config_file, "input.joypad1.l", "Joypad1 L", SDLK_d, Setting::HEX);
Setting Input::Joypad::r (&config_file, "input.joypad1.r", "Joypad1 R", SDLK_c, Setting::HEX);
Setting Input::Joypad::select(&config_file, "input.joypad1.select", "Joypad1 select", SDLK_RSHIFT, Setting::HEX);
Setting Input::Joypad::start (&config_file, "input.joypad1.start", "Joypad1 start", SDLK_RETURN, Setting::HEX);
};

View File

@ -1,17 +0,0 @@
void render() {
SNES::video_info vi;
snes->get_video_info(&vi);
screen_info.rs.x = 0;
screen_info.rs.y = (vi.height == 224) ? 1 : 2;
screen_info.rs.w = vi.width;
screen_info.rs.h = (vi.height == 224) ? 223 : 446;
//documentation says not to use this, but it's rather ridiculous that a graphics
//library wouldn't support simple image scaling... so let's use it anyway and see
//what happens...
//SDL_SoftStretch(backbuffer, &screen_info.rs, screen, &screen_info.rd);
SDL_BlitSurface(backbuffer, &screen_info.rs, screen, &screen_info.rd);
SDL_UpdateRect(screen, screen_info.rd.x, screen_info.rd.y, screen_info.rd.w, screen_info.rd.h);
}

View File

@ -1,12 +0,0 @@
#ifdef _WIN32_
#include <windows.h>
#include <SDL.h>
#else
#include "SDL.h"
#endif
SDL_Surface *screen, *backbuffer;
struct {
SDL_Rect rs, rd;
} screen_info;

View File

@ -1 +0,0 @@
bsnes_sdl c:\root\bsnes_testrom\zelda_us.smc

View File

@ -25,7 +25,7 @@ public:
*/
virtual void run(uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height, uint16 *scanline_widths = 0) = 0;
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height, uint16 *scanline_widths = 0) = 0;
virtual ~VideoFilter() {}
};

View File

@ -1,7 +1,7 @@
void DirectVideoFilter::run(
uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height,
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height,
uint16 *scanline_widths
) {
pitch >>= 1;

View File

@ -2,5 +2,5 @@ class DirectVideoFilter : public VideoFilter {
public:
void run(uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height, uint16 *scanline_widths = 0);
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height, uint16 *scanline_widths = 0);
};

View File

@ -64,7 +64,7 @@ static uint16 blend10(uint32 c1, uint32 c2, uint32 c3) {
void HQ2xVideoFilter::run(
uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height,
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height,
uint16 *scanline_widths
) {
pitch >>= 1;

View File

@ -4,7 +4,7 @@ uint32 yuvtable[32768];
uint32 diff_offset, diff_mask;
void run(uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height, uint16 *scanline_widths = 0);
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height, uint16 *scanline_widths = 0);
void lores_progressive(uint32 *colortbl, uint16 *data, uint32 height, uint32 pitch,
uint16 *output, uint32 output_pitch);

View File

@ -40,7 +40,7 @@ snes_ntsc_setup_t setup = defaults;
void NtscVideoFilter::run(
uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height,
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height,
uint16 *scanline_widths)
{
if(!ntsc)return;

View File

@ -16,7 +16,7 @@ public:
// where 0 < i < height
void run(uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height,
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height,
uint16 *scanline_widths = 0);
NtscVideoFilter();

View File

@ -1,7 +1,7 @@
void Scale2xVideoFilter::run(
uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height,
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height,
uint16 *scanline_widths
) {
pitch >>= 1;

View File

@ -2,7 +2,7 @@ class Scale2xVideoFilter : public VideoFilter {
public:
void run(uint32 *colortbl, uint16 *data, uint32 width, uint32 height, uint32 pitch,
uint16 *output, uint32 max_width, uint32 max_height, uint32 output_pitch,
uint32 req_width, uint32 req_height, uint32 &result_width, uint32 &result_height, uint16 *scanline_widths = 0);
uint32 req_width, uint32 req_height, uint &result_width, uint &result_height, uint16 *scanline_widths = 0);
void lores_progressive(uint32 *colortbl, uint16 *data, uint32 height, uint32 pitch,
uint16 *output, uint32 output_pitch);

View File

@ -1,8 +1,9 @@
void SNES::set_video_format(uint32 filter, uint32 pixel_format) {
void SNES::set_video_format(uint filter, uint video_standard, uint pixel_format) {
//only make changes at the start of a new frame
video_format.filter = filter;
video_format.pixel_format = pixel_format;
video_format.modified = true;
video_format.filter = filter;
video_format.video_standard = video_standard;
video_format.pixel_format = pixel_format;
video_format.modified = true;
}
/*****
@ -23,26 +24,42 @@ void SNES::update_video_format() {
case VIDEOFILTER_SCALE2X: video_filter = new Scale2xVideoFilter(); break;
}
video.pixel_format = video_format.pixel_format;
video.video_standard = video_format.video_standard;
video.pixel_format = video_format.pixel_format;
update_color_lookup_table();
}
void SNES::get_video_info(video_info *info) {
info->filter = video.filter;
info->pixel_format = video.pixel_format;
info->width = video.width;
info->height = video.height;
info->filter = video.filter;
info->video_standard = video.video_standard;
info->pixel_format = video.pixel_format;
info->width = video.width;
info->height = video.height;
}
void SNES::video_update() {
if(r_ppu->renderer_enabled()) {
update_video_format();
video.ppu_data = (uint16*)r_ppu->output + (int(r_cpu->overscan()) << 13) + 1024;
video.ppu_data = (uint16*)r_ppu->output;
// video_normalize();
video.raster_width = (video.frame_hires == false) ? 256 : 512;
video.raster_height = (video.frame_interlace == false) ? 224 : 448;
switch(video.video_standard) {
default:
case VIDEOSTANDARD_NTSC:
video.raster_width = 256;
video.raster_height = 224;
video.ppu_data += (int(r_cpu->overscan()) << 13) + 1024;
break;
case VIDEOSTANDARD_PAL:
video.raster_width = 256;
video.raster_height = 239;
video.ppu_data += 1024;
break;
}
if(video.frame_hires) { video.raster_width <<= 1; }
if(video.frame_interlace) { video.raster_height <<= 1; }
video.data = (uint16*)video_lock(video.pitch);
if(video.data) {
@ -64,7 +81,7 @@ void SNES::video_update() {
void SNES::video_scanline() {
int y = r_cpu->vcounter();
int o = int(r_cpu->overscan()) << 3;
int o = (video.video_standard == VIDEOSTANDARD_NTSC) ? (int(r_cpu->overscan()) << 3) : 0;
if(y <= (0 + o) || y >= (225 + o))return;
y -= o;
@ -86,6 +103,6 @@ void SNES::video_init() {
video.raster_data = (uint16*)malloc(512 * 480 * sizeof(uint16));
memset(video.raster_data, 0, 512 * 480 * sizeof(uint16));
video_filter = 0;
set_video_format(VIDEOFILTER_DIRECT, PIXELFORMAT_RGB565);
set_video_format(VIDEOFILTER_DIRECT, VIDEOSTANDARD_NTSC, PIXELFORMAT_RGB565);
update_video_format();
}

View File

@ -1,3 +1,8 @@
enum {
VIDEOSTANDARD_NTSC,
VIDEOSTANDARD_PAL,
};
enum {
PIXELFORMAT_RGB444,
PIXELFORMAT_RGB555,
@ -17,23 +22,23 @@ uint32 color_lookup_table[32768];
struct {
uint16 *data, *raster_data, *ppu_data;
uint32 raster_width, raster_height;
uint32 width, height;
uint32 filter, pixel_format;
uint32 pitch;
uint raster_width, raster_height;
uint width, height;
uint filter, video_standard, pixel_format;
uint pitch;
bool frame_hires, frame_interlace;
} video;
struct {
bool modified;
uint32 filter, pixel_format;
bool modified;
uint filter, video_standard, pixel_format;
} video_format;
uint16 pline_width[240], iline_width[480];
struct video_info {
uint32 filter, pixel_format, width, height;
uint filter, video_standard, pixel_format, width, height;
};
void contrast_adjust(int32 &input);
@ -42,10 +47,10 @@ struct video_info {
//public functions
void update_color_lookup_table();
virtual void set_video_format(uint32 filter, uint32 pixel_format);
virtual void set_video_format(uint filter, uint video_standard, uint pixel_format);
virtual void get_video_info(video_info *info);
virtual void video_run() = 0;
virtual uint16 *video_lock(uint32 &pitch) = 0;
virtual uint16 *video_lock(uint &pitch) = 0;
virtual void video_unlock() = 0;
//private functions

View File

@ -4,7 +4,7 @@ CXX = cl
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
CFLAGS = /nologo /O2 /MD /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK =
@ -18,7 +18,7 @@ CXX = cl
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
CFLAGS = /nologo /O2 /MD /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK = /link /LTCG
@ -32,7 +32,7 @@ CXX = cl
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
CFLAGS = /nologo /O2 /MD /GL /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
@ -46,7 +46,7 @@ CXX = cl
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
CFLAGS = /nologo /O2 /MD /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
@ -54,6 +54,20 @@ LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \
d3d9.lib d3dx9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
endif
ifeq ($(PLATFORM),win-visualc-sdl)
CC = cl
CXX = cl
AS = nasm
RM = del
OBJ = obj
CFLAGS = /nologo /O2 /MD /DPLATFORM_SDL /DCOMPILER_VISUALC /DPROCESSOR_X86
COMPILE = $(CC) $(CFLAGS) /c
ASSEMBLE = $(AS) -f win32
LINK =
LIBS = kernel32.lib user32.lib gdi32.lib winmm.lib comdlg32.lib comctl32.lib \
sdlmain.lib sdl.lib
endif
OBJS = main.$(OBJ) \
libco.$(OBJ) libstring.$(OBJ) libconfig.$(OBJ) \
reader.$(OBJ) cart.$(OBJ) cheat.$(OBJ) \
@ -71,6 +85,7 @@ OBJS = main.$(OBJ) \
all: $(OBJS)
rc /r /fobsnes.res bsnes.rc
$(CC) /Febsnes.exe $(CFLAGS) $(OBJS) bsnes.res $(LIBS) $(LINK)
mt -nologo -manifest bsnes.exe.manifest -outputresource:bsnes.exe;1
clean:
$(RM) *.$(OBJ)
@ -79,6 +94,7 @@ clean:
$(RM) *.pgc
$(RM) *.ilk
$(RM) *.pdb
$(RM) *.manifest
#########################
### platform-specific ###
@ -91,6 +107,7 @@ main.$(OBJ): *.cpp *.h video/* audio/* input/* ../config/* win/* win/settings/*
#################
libco.$(OBJ): ../lib/*
$(ASSEMBLE) -o libco.$(OBJ) ../lib/libco_x86.asm
# $(COMPILE) /Folibco.obj ../lib/libco_win32.cpp
libstring.$(OBJ): ../lib/*.cpp ../lib/*.h
$(COMPILE) ../lib/libstring.cpp

View File

@ -7,5 +7,5 @@ uint frequency;
virtual void init() = 0;
virtual void term() = 0;
Audio() { frequency = 32000; }
Audio() : frequency(32000) {}
} *uiAudio;

View File

@ -107,9 +107,9 @@ Setting Input::Joypad1::start (0, "input.joypad1.start", "", 0, Setting::HEX);
Setting Input::Joypad1::map(&config_file, "input.joypad1.map", "Joypad 1 button map\n"
"Format: Up; Down; Left; Right; A; B; X; Y; L; R; Select; Start",
"up | joy0.up; down | joy0.down; left | joy0.left; right | joy0.right; "
"x | joy0.button4; z | joy0.button3; s | joy0.button1; a | joy0.button0; "
"d | joy0.button6; c | joy0.button7; rshift | joy0.button2; enter | joy0.button5");
"up | joypad0.up; " "down | joypad0.down; " "left | joypad0.left; " "right | joypad0.right; "
"x | joypad0.button3; " "z | joypad0.button2; " "s | joypad0.button1; " "a | joypad0.button0; "
"d | joypad0.button6; " "c | joypad0.button7; " "rshift | joypad0.button4; " "enter | joypad0.button5");
//
@ -131,8 +131,8 @@ Setting Input::Joypad2::start (0, "input.joypad2.start", "", 0, Setting::HEX);
Setting Input::Joypad2::map(&config_file, "input.joypad2.map", "Joypad 2 button map\n"
"Format: Up; Down; Left; Right; A; B; X; Y; L; R; Select; Start",
"t | joy1.up; g | joy1.down; f | joy1.left; h | joy1.right; "
"k | joy1.button4; j | joy1.button3; i | joy1.button1; u | joy1.button0; "
"o | joy1.button6; l | joy1.button7; lbracket | joy1.button2; rbracket | joy1.button5");
"t | joypad1.up; " "g | joypad1.down; " "f | joypad1.left; " "h | joypad1.right; "
"k | joypad1.button3; " "j | joypad1.button2; " "i | joypad1.button1; " "u | joypad1.button0; "
"o | joypad1.button6; " "l | joypad1.button7; " "lbracket | joypad1.button4; " "rbracket | joypad1.button5");
};

View File

@ -1,16 +1,24 @@
void InputDI::poll(uint8 device) {
if(wMain.hwnd != GetForegroundWindow()) {
clear_input();
return;
}
Input::poll(device);
}
void InputDI::poll() {
HRESULT hr;
DIJOYSTATE2 js;
memset(keystate, 0, 256);
memset(keystate, 0, sizeof(keystate));
if(di_key) {
hr = di_key->GetDeviceState(256, keystate);
if(FAILED(hr)) {
di_key->Acquire();
di_key->GetDeviceState(256, keystate);
hr = di_key->GetDeviceState(256, keystate);
}
}
memset(joystate, 0, INPUT_JOYMAX * 256);
for(int i = 0; i < di_joy_count; i++) {
if(!di_joy[i])continue;
@ -23,178 +31,30 @@ DIJOYSTATE2 js;
}
di_joy[i]->GetDeviceState(sizeof(DIJOYSTATE2), &js);
uint32 index = i * 256; //joypad index
memcpy(joystate + index, js.rgbButtons, 128);
//map d-pad axes to joystate[index + {128 - 131}]
int32 resistance = config::input.axis_resistance;
uint index = 0x100 + i * 128; //joypad index
memcpy(keystate + index, js.rgbButtons, 124);
//map d-pad axes to keystate[index + {124 - 127}]
int resistance = config::input.axis_resistance;
if(resistance < 1)resistance = 1;
if(resistance > 99)resistance = 99;
resistance = int32(double(resistance) * 32768.0 / 100.0);
int32 resistance_lo = 0x7fff - resistance;
int32 resistance_hi = 0x8000 + resistance;
joystate[index + 128] = (js.lY <= resistance_lo) ? 0x80 : 0x00;
joystate[index + 129] = (js.lY >= resistance_hi) ? 0x80 : 0x00;
joystate[index + 130] = (js.lX <= resistance_lo) ? 0x80 : 0x00;
joystate[index + 131] = (js.lX >= resistance_hi) ? 0x80 : 0x00;
int resistance_lo = 0x7fff - resistance;
int resistance_hi = 0x8000 + resistance;
keystate[index + 124] = (js.lY <= resistance_lo) ? 0x80 : 0x00;
keystate[index + 125] = (js.lY >= resistance_hi) ? 0x80 : 0x00;
keystate[index + 126] = (js.lX <= resistance_lo) ? 0x80 : 0x00;
keystate[index + 127] = (js.lX >= resistance_hi) ? 0x80 : 0x00;
//map analog POV (analog directional pad) as well
uint32 pov = js.rgdwPOV[0];
joystate[index + 128] |= (pov == 0 || pov == 31500 || pov == 4500) ? 0x80 : 0x00;
joystate[index + 129] |= (pov == 18000 || pov == 13500 || pov == 22500) ? 0x80 : 0x00;
joystate[index + 130] |= (pov == 27000 || pov == 22500 || pov == 31500) ? 0x80 : 0x00;
joystate[index + 131] |= (pov == 9000 || pov == 4500 || pov == 13500) ? 0x80 : 0x00;
uint pov = js.rgdwPOV[0];
keystate[index + 124] |= (pov == 0 || pov == 31500 || pov == 4500) ? 0x80 : 0x00;
keystate[index + 125] |= (pov == 18000 || pov == 13500 || pov == 22500) ? 0x80 : 0x00;
keystate[index + 126] |= (pov == 27000 || pov == 22500 || pov == 31500) ? 0x80 : 0x00;
keystate[index + 127] |= (pov == 9000 || pov == 4500 || pov == 13500) ? 0x80 : 0x00;
}
}
bool InputDI::button_down(uint32 r) {
if((r & JOYMASK) != JOY_NONE) {
uint8 joynum = (r >> 16) & 0xff;
joynum %= INPUT_JOYMAX;
if(joystate[(joynum * 256) + ((r >> 8) & 0xff)] & 0x80) {
return true;
}
}
if((r & KEYMASK) != KEY_NONE) {
//keypad value defined
if(keystate[r & 0xff] & 0x80) {
return true;
}
}
return false;
}
void InputDI::poll(uint8 type) {
poll();
HWND fw = GetForegroundWindow();
#define poll_key(__key) \
__key = (fw == wMain.hwnd) ? button_down(uint32(config::input.__key)) : 0
switch(type) {
case SNES::DEV_JOYPAD1:
poll_key(joypad1.up);
poll_key(joypad1.down);
poll_key(joypad1.left);
poll_key(joypad1.right);
poll_key(joypad1.a);
poll_key(joypad1.b);
poll_key(joypad1.x);
poll_key(joypad1.y);
poll_key(joypad1.l);
poll_key(joypad1.r);
poll_key(joypad1.select);
poll_key(joypad1.start);
break;
case SNES::DEV_JOYPAD2:
poll_key(joypad2.up);
poll_key(joypad2.down);
poll_key(joypad2.left);
poll_key(joypad2.right);
poll_key(joypad2.a);
poll_key(joypad2.b);
poll_key(joypad2.x);
poll_key(joypad2.y);
poll_key(joypad2.l);
poll_key(joypad2.r);
poll_key(joypad2.select);
poll_key(joypad2.start);
break;
}
#undef poll_key
}
bool InputDI::get_status(uint8 device, uint8 button) {
switch(device) {
case SNES::DEV_JOYPAD1:
switch(button) {
case SNES::JOYPAD_UP: return joypad1.up;
case SNES::JOYPAD_DOWN: return joypad1.down;
case SNES::JOYPAD_LEFT: return joypad1.left;
case SNES::JOYPAD_RIGHT: return joypad1.right;
case SNES::JOYPAD_A: return joypad1.a;
case SNES::JOYPAD_B: return joypad1.b;
case SNES::JOYPAD_X: return joypad1.x;
case SNES::JOYPAD_Y: return joypad1.y;
case SNES::JOYPAD_L: return joypad1.l;
case SNES::JOYPAD_R: return joypad1.r;
case SNES::JOYPAD_SELECT: return joypad1.select;
case SNES::JOYPAD_START: return joypad1.start;
}
break;
case SNES::DEV_JOYPAD2:
switch(button) {
case SNES::JOYPAD_UP: return joypad2.up;
case SNES::JOYPAD_DOWN: return joypad2.down;
case SNES::JOYPAD_LEFT: return joypad2.left;
case SNES::JOYPAD_RIGHT: return joypad2.right;
case SNES::JOYPAD_A: return joypad2.a;
case SNES::JOYPAD_B: return joypad2.b;
case SNES::JOYPAD_X: return joypad2.x;
case SNES::JOYPAD_Y: return joypad2.y;
case SNES::JOYPAD_L: return joypad2.l;
case SNES::JOYPAD_R: return joypad2.r;
case SNES::JOYPAD_SELECT: return joypad2.select;
case SNES::JOYPAD_START: return joypad2.start;
}
break;
}
return false;
}
void InputDI::set_status(uint8 device, uint8 button, bool status) {
switch(device) {
case SNES::DEV_JOYPAD1:
switch(button) {
case SNES::JOYPAD_UP: joypad1.up = status; break;
case SNES::JOYPAD_DOWN: joypad1.down = status; break;
case SNES::JOYPAD_LEFT: joypad1.left = status; break;
case SNES::JOYPAD_RIGHT: joypad1.right = status; break;
case SNES::JOYPAD_A: joypad1.a = status; break;
case SNES::JOYPAD_B: joypad1.b = status; break;
case SNES::JOYPAD_X: joypad1.x = status; break;
case SNES::JOYPAD_Y: joypad1.y = status; break;
case SNES::JOYPAD_L: joypad1.l = status; break;
case SNES::JOYPAD_R: joypad1.r = status; break;
case SNES::JOYPAD_SELECT: joypad1.select = status; break;
case SNES::JOYPAD_START: joypad1.start = status; break;
} break;
case SNES::DEV_JOYPAD2:
switch(button) {
case SNES::JOYPAD_UP: joypad2.up = status; break;
case SNES::JOYPAD_DOWN: joypad2.down = status; break;
case SNES::JOYPAD_LEFT: joypad2.left = status; break;
case SNES::JOYPAD_RIGHT: joypad2.right = status; break;
case SNES::JOYPAD_A: joypad2.a = status; break;
case SNES::JOYPAD_B: joypad2.b = status; break;
case SNES::JOYPAD_X: joypad2.x = status; break;
case SNES::JOYPAD_Y: joypad2.y = status; break;
case SNES::JOYPAD_L: joypad2.l = status; break;
case SNES::JOYPAD_R: joypad2.r = status; break;
case SNES::JOYPAD_SELECT: joypad2.select = status; break;
case SNES::JOYPAD_START: joypad2.start = status; break;
} break;
}
}
void InputDI::clear_input() {
joypad1.up = joypad2.up =
joypad1.down = joypad2.down =
joypad1.left = joypad2.left =
joypad1.right = joypad2.right =
joypad1.a = joypad2.a =
joypad1.b = joypad2.b =
joypad1.x = joypad2.x =
joypad1.y = joypad2.y =
joypad1.l = joypad2.l =
joypad1.r = joypad2.r =
joypad1.select = joypad2.select =
joypad1.start = joypad2.start = false;
}
BOOL CALLBACK DI_EnumJoypadsCallback(const DIDEVICEINSTANCE *instance, void *context) {
return static_cast<InputDI*>(uiInput)->enum_joypads(instance);
}

View File

@ -7,23 +7,13 @@ LPDIRECTINPUT8 di;
LPDIRECTINPUTDEVICE8 di_key, di_joy[INPUT_JOYMAX];
uint32 di_joy_count;
struct joypad {
bool up, down, left, right;
bool a, b, x, y, l, r;
bool select, start;
} joypad1, joypad2;
void poll();
bool button_down(uint32 r);
void poll(uint8 type);
bool get_status(uint8 device, uint8 button);
void set_status(uint8 device, uint8 button, bool status);
void clear_input();
bool enum_joypads(const DIDEVICEINSTANCE *instance);
void poll(uint8 device);
void init();
void term();
bool enum_joypads(const DIDEVICEINSTANCE *instance);
InputDI() {
di = 0;
di_key = 0;

View File

@ -1,117 +1,127 @@
keymap.esc = 0x01;
key.esc = 0x01;
keymap.f1 = 0x3b;
keymap.f2 = 0x3c;
keymap.f3 = 0x3d;
keymap.f4 = 0x3e;
keymap.f5 = 0x3f;
keymap.f6 = 0x40;
keymap.f7 = 0x41;
keymap.f8 = 0x42;
keymap.f9 = 0x43;
keymap.f10 = 0x44;
keymap.f11 = 0x57;
keymap.f12 = 0x58;
key.f1 = 0x3b;
key.f2 = 0x3c;
key.f3 = 0x3d;
key.f4 = 0x3e;
key.f5 = 0x3f;
key.f6 = 0x40;
key.f7 = 0x41;
key.f8 = 0x42;
key.f9 = 0x43;
key.f10 = 0x44;
key.f11 = 0x57;
key.f12 = 0x58;
keymap.print_screen = 0xb7;
keymap.scroll_lock = 0x46;
keymap.pause = 0xc5;
key.print_screen = 0xb7;
key.scroll_lock = 0x46;
key.pause = 0xc5;
keymap.tilde = 0x29;
key.tilde = 0x29;
keymap.num_0 = 0x0b;
keymap.num_1 = 0x02;
keymap.num_2 = 0x03;
keymap.num_3 = 0x04;
keymap.num_4 = 0x05;
keymap.num_5 = 0x06;
keymap.num_6 = 0x07;
keymap.num_7 = 0x08;
keymap.num_8 = 0x09;
keymap.num_9 = 0x0a;
key.num_0 = 0x0b;
key.num_1 = 0x02;
key.num_2 = 0x03;
key.num_3 = 0x04;
key.num_4 = 0x05;
key.num_5 = 0x06;
key.num_6 = 0x07;
key.num_7 = 0x08;
key.num_8 = 0x09;
key.num_9 = 0x0a;
keymap.minus = 0x0c;
keymap.plus = 0x0d;
keymap.backspace = 0x0e;
key.minus = 0x0c;
key.plus = 0x0d;
key.backspace = 0x0e;
keymap.ins = 0xd2;
keymap.del = 0xd3;
keymap.home = 0xc7;
keymap.end = 0xcf;
keymap.page_up = 0xc9;
keymap.page_down = 0xd1;
key.ins = 0xd2;
key.del = 0xd3;
key.home = 0xc7;
key.end = 0xcf;
key.page_up = 0xc9;
key.page_down = 0xd1;
keymap.a = 0x1e;
keymap.b = 0x30;
keymap.c = 0x2e;
keymap.d = 0x20;
keymap.e = 0x12;
keymap.f = 0x21;
keymap.g = 0x22;
keymap.h = 0x23;
keymap.i = 0x17;
keymap.j = 0x24;
keymap.k = 0x25;
keymap.l = 0x26;
keymap.m = 0x32;
keymap.n = 0x31;
keymap.o = 0x18;
keymap.p = 0x19;
keymap.q = 0x10;
keymap.r = 0x13;
keymap.s = 0x1f;
keymap.t = 0x14;
keymap.u = 0x16;
keymap.v = 0x2f;
keymap.w = 0x11;
keymap.x = 0x2d;
keymap.y = 0x15;
keymap.z = 0x2c;
key.a = 0x1e;
key.b = 0x30;
key.c = 0x2e;
key.d = 0x20;
key.e = 0x12;
key.f = 0x21;
key.g = 0x22;
key.h = 0x23;
key.i = 0x17;
key.j = 0x24;
key.k = 0x25;
key.l = 0x26;
key.m = 0x32;
key.n = 0x31;
key.o = 0x18;
key.p = 0x19;
key.q = 0x10;
key.r = 0x13;
key.s = 0x1f;
key.t = 0x14;
key.u = 0x16;
key.v = 0x2f;
key.w = 0x11;
key.x = 0x2d;
key.y = 0x15;
key.z = 0x2c;
keymap.lbracket = 0x1a;
keymap.rbracket = 0x1b;
keymap.pipe = 0x2b;
keymap.colon = 0x27;
keymap.quote = 0x28;
keymap.comma = 0x33;
keymap.period = 0x34;
keymap.question = 0x35;
key.lbracket = 0x1a;
key.rbracket = 0x1b;
key.pipe = 0x2b;
key.colon = 0x27;
key.quote = 0x28;
key.comma = 0x33;
key.period = 0x34;
key.question = 0x35;
keymap.numpad_0 = 0x52;
keymap.numpad_1 = 0x4f;
keymap.numpad_2 = 0x50;
keymap.numpad_3 = 0x51;
keymap.numpad_4 = 0x4b;
keymap.numpad_5 = 0x4c;
keymap.numpad_6 = 0x4d;
keymap.numpad_7 = 0x47;
keymap.numpad_8 = 0x48;
keymap.numpad_9 = 0x49;
keymap.numpad_plus = 0x4e;
keymap.numpad_minus = 0x4a;
keymap.numpad_mul = 0x37;
keymap.numpad_div = 0xb5;
keymap.numpad_enter = 0x9c;
keymap.numpad_point = 0x53;
key.numpad_0 = 0x52;
key.numpad_1 = 0x4f;
key.numpad_2 = 0x50;
key.numpad_3 = 0x51;
key.numpad_4 = 0x4b;
key.numpad_5 = 0x4c;
key.numpad_6 = 0x4d;
key.numpad_7 = 0x47;
key.numpad_8 = 0x48;
key.numpad_9 = 0x49;
key.numpad_plus = 0x4e;
key.numpad_minus = 0x4a;
key.numpad_mul = 0x37;
key.numpad_div = 0xb5;
key.numpad_enter = 0x9c;
key.numpad_point = 0x53;
keymap.numlock = 0x45;
keymap.capslock = 0x3a;
key.numlock = 0x45;
key.capslock = 0x3a;
keymap.up = 0xc8;
keymap.down = 0xd0;
keymap.left = 0xcb;
keymap.right = 0xcd;
key.up = 0xc8;
key.down = 0xd0;
key.left = 0xcb;
key.right = 0xcd;
keymap.tab = 0x0f;
keymap.enter = 0x1c;
keymap.space = 0x39;
keymap.lctrl = 0x1d;
keymap.rctrl = 0x9d;
keymap.lalt = 0x38;
keymap.ralt = 0xb8;
keymap.lshift = 0x2a;
keymap.rshift = 0x36;
key.tab = 0x0f;
key.enter = 0x1c;
key.space = 0x39;
key.lctrl = 0x1d;
key.rctrl = 0x9d;
key.lalt = 0x38;
key.ralt = 0xb8;
key.lshift = 0x2a;
key.rshift = 0x36;
keymap.lwin = 0xdb;
keymap.rwin = 0xdc;
keymap.menu = 0xdd;
key.lwin = 0xdb;
key.rwin = 0xdc;
key.menu = 0xdd;
for(int joy = 0; joy < 16; joy++) {
key.joypad[joy].up = 0x100 + (joy * 128) + 124;
key.joypad[joy].down = 0x100 + (joy * 128) + 125;
key.joypad[joy].left = 0x100 + (joy * 128) + 126;
key.joypad[joy].right = 0x100 + (joy * 128) + 127;
for(int bn = 0; bn <= 123; bn++) {
key.joypad[joy].button[bn] = 0x100 + (joy * 128) + bn;
}
}

View File

@ -1,208 +1,140 @@
void Input::ui_poll_input(Window *focus, bool require_window_focus) {
if(require_window_focus == true) {
if(GetFocus() != focus->hwnd)return;
}
void Input::poll(uint8 device) {
poll();
EventInfo info;
info.window = focus;
info.window_id = focus->id;
info.control = 0;
#define poll_key(__key) \
__key = bool(keystate[(uint(config::input.__key) >> 0) & 4095]) | \
bool(keystate[(uint(config::input.__key) >> 16) & 4095])
for(int i = 0; i < 256; i++) {
if(!old_keystate[i] && keystate[i]) {
info.event_id = EVENT_INPUTKEYDOWN;
info.control_id = KEYFLAG | i;
focus->Event(info);
} else if(old_keystate[i] && !keystate[i]) {
info.event_id = EVENT_INPUTKEYUP;
info.control_id = KEYFLAG | i;
focus->Event(info);
}
switch(device) {
case SNES::DEV_JOYPAD1:
poll_key(joypad1.up);
poll_key(joypad1.down);
poll_key(joypad1.left);
poll_key(joypad1.right);
poll_key(joypad1.a);
poll_key(joypad1.b);
poll_key(joypad1.x);
poll_key(joypad1.y);
poll_key(joypad1.l);
poll_key(joypad1.r);
poll_key(joypad1.select);
poll_key(joypad1.start);
break;
case SNES::DEV_JOYPAD2:
poll_key(joypad2.up);
poll_key(joypad2.down);
poll_key(joypad2.left);
poll_key(joypad2.right);
poll_key(joypad2.a);
poll_key(joypad2.b);
poll_key(joypad2.x);
poll_key(joypad2.y);
poll_key(joypad2.l);
poll_key(joypad2.r);
poll_key(joypad2.select);
poll_key(joypad2.start);
break;
}
for(int j = 0; j < INPUT_JOYMAX; j++) {
for(int i = 0; i < 256; i++) {
if(!old_joystate[j * 256 + i] && joystate[j * 256 + i]) {
info.event_id = EVENT_INPUTKEYDOWN;
info.control_id = JOYFLAG | (j << 8) | i;
focus->Event(info);
} else if(old_joystate[j * 256 + i] && !joystate[j * 256 + i]) {
info.event_id = EVENT_INPUTKEYUP;
info.control_id = JOYFLAG | (j << 8) | i;
focus->Event(info);
}
#undef poll_key
}
bool Input::get_status(uint8 device, uint8 button) {
switch(device) {
case SNES::DEV_JOYPAD1:
switch(button) {
case SNES::JOYPAD_UP: return joypad1.up;
case SNES::JOYPAD_DOWN: return joypad1.down;
case SNES::JOYPAD_LEFT: return joypad1.left;
case SNES::JOYPAD_RIGHT: return joypad1.right;
case SNES::JOYPAD_A: return joypad1.a;
case SNES::JOYPAD_B: return joypad1.b;
case SNES::JOYPAD_X: return joypad1.x;
case SNES::JOYPAD_Y: return joypad1.y;
case SNES::JOYPAD_L: return joypad1.l;
case SNES::JOYPAD_R: return joypad1.r;
case SNES::JOYPAD_SELECT: return joypad1.select;
case SNES::JOYPAD_START: return joypad1.start;
}
}
memcpy(old_keystate, keystate, 256);
memcpy(old_joystate, joystate, INPUT_JOYMAX * 256);
}
void Input::ui_clear_input() {
memset(keystate, 0, 256);
memset(joystate, 0, INPUT_JOYMAX * 256);
memset(old_keystate, 0, 256);
memset(old_joystate, 0, INPUT_JOYMAX * 256);
}
//this does not poll actual key state, it relies on
//current keystate buffer to be up-to-date.
//it is intended to be used inside
//Input::EVENT_INPUTKEY* messages only.
//calling Input::ui_poll_input() first will allow
//this function to be used anywhere.
bool Input::keydown(uint id) {
if(id < 256) {
return (keystate[id] != 0);
break;
case SNES::DEV_JOYPAD2:
switch(button) {
case SNES::JOYPAD_UP: return joypad2.up;
case SNES::JOYPAD_DOWN: return joypad2.down;
case SNES::JOYPAD_LEFT: return joypad2.left;
case SNES::JOYPAD_RIGHT: return joypad2.right;
case SNES::JOYPAD_A: return joypad2.a;
case SNES::JOYPAD_B: return joypad2.b;
case SNES::JOYPAD_X: return joypad2.x;
case SNES::JOYPAD_Y: return joypad2.y;
case SNES::JOYPAD_L: return joypad2.l;
case SNES::JOYPAD_R: return joypad2.r;
case SNES::JOYPAD_SELECT: return joypad2.select;
case SNES::JOYPAD_START: return joypad2.start;
}
break;
}
return false;
}
//turn string into keymap value, eg
//"esc" returns keymap.esc
uint Input::stringtokeymap(const char *str) {
uint r = JOYKEY_NONE;
string t, part;
strcpy(t, str);
replace(t, ".", "|");
split(part, "|", t);
#define cmp(__n) if(strmatch(#__n, part[0]) == true)r = (r & ~KEYMASK) | keymap.__n;
cmp(esc)
cmp(f1) cmp(f2) cmp(f3) cmp(f4) cmp(f5) cmp(f6)
cmp(f7) cmp(f8) cmp(f9) cmp(f10) cmp(f11) cmp(f12)
cmp(print_screen) cmp(scroll_lock) cmp(pause)
cmp(tilde)
cmp(num_0) cmp(num_1) cmp(num_2) cmp(num_3) cmp(num_4)
cmp(num_5) cmp(num_6) cmp(num_7) cmp(num_8) cmp(num_9)
cmp(minus) cmp(plus) cmp(backspace)
cmp(ins) cmp(del) cmp(home) cmp(end) cmp(page_up) cmp(page_down)
cmp(a) cmp(b) cmp(c) cmp(d) cmp(e) cmp(f) cmp(g) cmp(h) cmp(i)
cmp(j) cmp(k) cmp(l) cmp(m) cmp(n) cmp(o) cmp(p) cmp(q) cmp(r)
cmp(s) cmp(t) cmp(u) cmp(v) cmp(w) cmp(x) cmp(y) cmp(z)
cmp(lbracket) cmp(rbracket) cmp(pipe)
cmp(colon) cmp(quote)
cmp(comma) cmp(period) cmp(question)
cmp(numpad_0) cmp(numpad_1) cmp(numpad_2) cmp(numpad_3) cmp(numpad_4)
cmp(numpad_5) cmp(numpad_6) cmp(numpad_7) cmp(numpad_8) cmp(numpad_9)
cmp(numpad_plus) cmp(numpad_minus) cmp(numpad_mul) cmp(numpad_div)
cmp(numpad_enter) cmp(numpad_point)
cmp(numlock) cmp(capslock)
cmp(up) cmp(down) cmp(left) cmp(right)
cmp(tab) cmp(enter) cmp(space)
cmp(lctrl) cmp(rctrl)
cmp(lalt) cmp(ralt)
cmp(lshift) cmp(rshift)
cmp(lwin) cmp(rwin) cmp(menu)
#undef cmp
if(count(part) < 3)return r;
strcpy(t, part[1]);
replace(t, "joy", "");
uint controller = strdec(t), button;
strcpy(t, part[2]);
if(strmatch(t, "up")) {
button = 0x80;
} else if(strmatch(t, "down")) {
button = 0x81;
} else if(strmatch(t, "left")) {
button = 0x82;
} else if(strmatch(t, "right")) {
button = 0x83;
} else {
replace(t, "button", "");
button = strdec(t);
void Input::set_status(uint8 device, uint8 button, bool status) {
switch(device) {
case SNES::DEV_JOYPAD1:
switch(button) {
case SNES::JOYPAD_UP: joypad1.up = status; break;
case SNES::JOYPAD_DOWN: joypad1.down = status; break;
case SNES::JOYPAD_LEFT: joypad1.left = status; break;
case SNES::JOYPAD_RIGHT: joypad1.right = status; break;
case SNES::JOYPAD_A: joypad1.a = status; break;
case SNES::JOYPAD_B: joypad1.b = status; break;
case SNES::JOYPAD_X: joypad1.x = status; break;
case SNES::JOYPAD_Y: joypad1.y = status; break;
case SNES::JOYPAD_L: joypad1.l = status; break;
case SNES::JOYPAD_R: joypad1.r = status; break;
case SNES::JOYPAD_SELECT: joypad1.select = status; break;
case SNES::JOYPAD_START: joypad1.start = status; break;
} break;
case SNES::DEV_JOYPAD2:
switch(button) {
case SNES::JOYPAD_UP: joypad2.up = status; break;
case SNES::JOYPAD_DOWN: joypad2.down = status; break;
case SNES::JOYPAD_LEFT: joypad2.left = status; break;
case SNES::JOYPAD_RIGHT: joypad2.right = status; break;
case SNES::JOYPAD_A: joypad2.a = status; break;
case SNES::JOYPAD_B: joypad2.b = status; break;
case SNES::JOYPAD_X: joypad2.x = status; break;
case SNES::JOYPAD_Y: joypad2.y = status; break;
case SNES::JOYPAD_L: joypad2.l = status; break;
case SNES::JOYPAD_R: joypad2.r = status; break;
case SNES::JOYPAD_SELECT: joypad2.select = status; break;
case SNES::JOYPAD_START: joypad2.start = status; break;
} break;
}
r = (r & ~JOYMASK) | (controller << 16) | (button << 8);
return r;
}
//turn keymap value into string,
//eg 0x01 returns "esc"
const char *Input::keymaptostring(uint key) {
static char result[128];
strcpy(result, "keynone");
uint r = key & KEYMASK;
#define cmp(__n) if(r == keymap.__n)strcpy(result, #__n);
cmp(esc)
cmp(f1) cmp(f2) cmp(f3) cmp(f4) cmp(f5) cmp(f6)
cmp(f7) cmp(f8) cmp(f9) cmp(f10) cmp(f11) cmp(f12)
cmp(print_screen) cmp(scroll_lock) cmp(pause)
cmp(tilde)
cmp(num_0) cmp(num_1) cmp(num_2) cmp(num_3) cmp(num_4)
cmp(num_5) cmp(num_6) cmp(num_7) cmp(num_8) cmp(num_9)
cmp(minus) cmp(plus) cmp(backspace)
cmp(ins) cmp(del) cmp(home) cmp(end) cmp(page_up) cmp(page_down)
cmp(a) cmp(b) cmp(c) cmp(d) cmp(e) cmp(f) cmp(g) cmp(h) cmp(i)
cmp(j) cmp(k) cmp(l) cmp(m) cmp(n) cmp(o) cmp(p) cmp(q) cmp(r)
cmp(s) cmp(t) cmp(u) cmp(v) cmp(w) cmp(x) cmp(y) cmp(z)
cmp(lbracket) cmp(rbracket) cmp(pipe)
cmp(colon) cmp(quote)
cmp(comma) cmp(period) cmp(question)
cmp(numpad_0) cmp(numpad_1) cmp(numpad_2) cmp(numpad_3) cmp(numpad_4)
cmp(numpad_5) cmp(numpad_6) cmp(numpad_7) cmp(numpad_8) cmp(numpad_9)
cmp(numpad_plus) cmp(numpad_minus) cmp(numpad_mul) cmp(numpad_div)
cmp(numpad_enter) cmp(numpad_point)
cmp(numlock) cmp(capslock)
cmp(up) cmp(down) cmp(left) cmp(right)
cmp(tab) cmp(enter) cmp(space)
cmp(lctrl) cmp(rctrl)
cmp(lalt) cmp(ralt)
cmp(lshift) cmp(rshift)
cmp(lwin) cmp(rwin) cmp(menu)
#undef cmp
if((key & JOYMASK) != JOY_NONE) {
strcat(result, " | joy");
r = (key >> 16) & 0xff;
char tmp[16];
sprintf(tmp, "%d", r);
strcat(result, tmp);
strcat(result, ".");
r = (key >> 8) & 0xff;
if(r == 0x80) {
strcat(result, "up");
} else if(r == 0x81) {
strcat(result, "down");
} else if(r == 0x82) {
strcat(result, "left");
} else if(r == 0x83) {
strcat(result, "right");
} else {
sprintf(tmp, "button%d", r);
strcat(result, tmp);
}
}
return result;
void Input::clear_input() {
joypad1.up = joypad2.up =
joypad1.down = joypad2.down =
joypad1.left = joypad2.left =
joypad1.right = joypad2.right =
joypad1.a = joypad2.a =
joypad1.b = joypad2.b =
joypad1.x = joypad2.x =
joypad1.y = joypad2.y =
joypad1.l = joypad2.l =
joypad1.r = joypad2.r =
joypad1.select = joypad2.select =
joypad1.start = joypad2.start = false;
}
uint Input::get_keymap(uint device, uint button) {
//this does not poll actual key state, it relies on
//current keystate buffer to be up-to-date.
bool Input::keydown(uint16 key) {
return (keystate[key] != 0);
}
uint Input::get_key(uint device, uint button) {
switch(device) {
case SNES::DEV_JOYPAD1:
switch(button) {
@ -235,44 +167,53 @@ uint Input::get_keymap(uint device, uint button) {
case SNES::JOYPAD_START: return config::input.joypad2.start;
} break;
}
return JOYKEY_NONE;
return 0;
}
void Input::set_keymap(uint device, uint button, uint keymap) {
void Input::set_key(uint device, uint button, uint key) {
switch(device) {
case SNES::DEV_JOYPAD1:
switch(button) {
case SNES::JOYPAD_UP: config::input.joypad1.up = keymap; break;
case SNES::JOYPAD_DOWN: config::input.joypad1.down = keymap; break;
case SNES::JOYPAD_LEFT: config::input.joypad1.left = keymap; break;
case SNES::JOYPAD_RIGHT: config::input.joypad1.right = keymap; break;
case SNES::JOYPAD_A: config::input.joypad1.a = keymap; break;
case SNES::JOYPAD_B: config::input.joypad1.b = keymap; break;
case SNES::JOYPAD_X: config::input.joypad1.x = keymap; break;
case SNES::JOYPAD_Y: config::input.joypad1.y = keymap; break;
case SNES::JOYPAD_L: config::input.joypad1.l = keymap; break;
case SNES::JOYPAD_R: config::input.joypad1.r = keymap; break;
case SNES::JOYPAD_SELECT: config::input.joypad1.select = keymap; break;
case SNES::JOYPAD_START: config::input.joypad1.start = keymap; break;
case SNES::JOYPAD_UP: config::input.joypad1.up = key; break;
case SNES::JOYPAD_DOWN: config::input.joypad1.down = key; break;
case SNES::JOYPAD_LEFT: config::input.joypad1.left = key; break;
case SNES::JOYPAD_RIGHT: config::input.joypad1.right = key; break;
case SNES::JOYPAD_A: config::input.joypad1.a = key; break;
case SNES::JOYPAD_B: config::input.joypad1.b = key; break;
case SNES::JOYPAD_X: config::input.joypad1.x = key; break;
case SNES::JOYPAD_Y: config::input.joypad1.y = key; break;
case SNES::JOYPAD_L: config::input.joypad1.l = key; break;
case SNES::JOYPAD_R: config::input.joypad1.r = key; break;
case SNES::JOYPAD_SELECT: config::input.joypad1.select = key; break;
case SNES::JOYPAD_START: config::input.joypad1.start = key; break;
} break;
case SNES::DEV_JOYPAD2:
switch(button) {
case SNES::JOYPAD_UP: config::input.joypad2.up = keymap; break;
case SNES::JOYPAD_DOWN: config::input.joypad2.down = keymap; break;
case SNES::JOYPAD_LEFT: config::input.joypad2.left = keymap; break;
case SNES::JOYPAD_RIGHT: config::input.joypad2.right = keymap; break;
case SNES::JOYPAD_A: config::input.joypad2.a = keymap; break;
case SNES::JOYPAD_B: config::input.joypad2.b = keymap; break;
case SNES::JOYPAD_X: config::input.joypad2.x = keymap; break;
case SNES::JOYPAD_Y: config::input.joypad2.y = keymap; break;
case SNES::JOYPAD_L: config::input.joypad2.l = keymap; break;
case SNES::JOYPAD_R: config::input.joypad2.r = keymap; break;
case SNES::JOYPAD_SELECT: config::input.joypad2.select = keymap; break;
case SNES::JOYPAD_START: config::input.joypad2.start = keymap; break;
case SNES::JOYPAD_UP: config::input.joypad2.up = key; break;
case SNES::JOYPAD_DOWN: config::input.joypad2.down = key; break;
case SNES::JOYPAD_LEFT: config::input.joypad2.left = key; break;
case SNES::JOYPAD_RIGHT: config::input.joypad2.right = key; break;
case SNES::JOYPAD_A: config::input.joypad2.a = key; break;
case SNES::JOYPAD_B: config::input.joypad2.b = key; break;
case SNES::JOYPAD_X: config::input.joypad2.x = key; break;
case SNES::JOYPAD_Y: config::input.joypad2.y = key; break;
case SNES::JOYPAD_L: config::input.joypad2.l = key; break;
case SNES::JOYPAD_R: config::input.joypad2.r = key; break;
case SNES::JOYPAD_SELECT: config::input.joypad2.select = key; break;
case SNES::JOYPAD_START: config::input.joypad2.start = key; break;
} break;
}
}
uint Input::decode(substring &str) {
string p;
split(p, "|", str);
uint r = key.find(strptr(p[0])) & 4095;
if(count(p) >= 2) { r |= (key.find(strptr(p[1])) & 4095) << 16; }
return r;
}
void Input::init() {
string t, part;
strcpy(t, config::input.joypad1.map.sget());
@ -280,72 +221,82 @@ string t, part;
replace(t, "\t", "");
strlower(t);
split(part, ";", t);
config::input.joypad1.up = stringtokeymap(strptr(part[ 0]));
config::input.joypad1.down = stringtokeymap(strptr(part[ 1]));
config::input.joypad1.left = stringtokeymap(strptr(part[ 2]));
config::input.joypad1.right = stringtokeymap(strptr(part[ 3]));
config::input.joypad1.a = stringtokeymap(strptr(part[ 4]));
config::input.joypad1.b = stringtokeymap(strptr(part[ 5]));
config::input.joypad1.x = stringtokeymap(strptr(part[ 6]));
config::input.joypad1.y = stringtokeymap(strptr(part[ 7]));
config::input.joypad1.l = stringtokeymap(strptr(part[ 8]));
config::input.joypad1.r = stringtokeymap(strptr(part[ 9]));
config::input.joypad1.select = stringtokeymap(strptr(part[10]));
config::input.joypad1.start = stringtokeymap(strptr(part[11]));
config::input.joypad1.up = decode(part[ 0]);
config::input.joypad1.down = decode(part[ 1]);
config::input.joypad1.left = decode(part[ 2]);
config::input.joypad1.right = decode(part[ 3]);
config::input.joypad1.a = decode(part[ 4]);
config::input.joypad1.b = decode(part[ 5]);
config::input.joypad1.x = decode(part[ 6]);
config::input.joypad1.y = decode(part[ 7]);
config::input.joypad1.l = decode(part[ 8]);
config::input.joypad1.r = decode(part[ 9]);
config::input.joypad1.select = decode(part[10]);
config::input.joypad1.start = decode(part[11]);
strcpy(t, config::input.joypad2.map.sget());
replace(t, " ", "");
replace(t, "\t", "");
strlower(t);
split(part, ";", t);
config::input.joypad2.up = stringtokeymap(strptr(part[ 0]));
config::input.joypad2.down = stringtokeymap(strptr(part[ 1]));
config::input.joypad2.left = stringtokeymap(strptr(part[ 2]));
config::input.joypad2.right = stringtokeymap(strptr(part[ 3]));
config::input.joypad2.a = stringtokeymap(strptr(part[ 4]));
config::input.joypad2.b = stringtokeymap(strptr(part[ 5]));
config::input.joypad2.x = stringtokeymap(strptr(part[ 6]));
config::input.joypad2.y = stringtokeymap(strptr(part[ 7]));
config::input.joypad2.l = stringtokeymap(strptr(part[ 8]));
config::input.joypad2.r = stringtokeymap(strptr(part[ 9]));
config::input.joypad2.select = stringtokeymap(strptr(part[10]));
config::input.joypad2.start = stringtokeymap(strptr(part[11]));
config::input.joypad2.up = decode(part[ 0]);
config::input.joypad2.down = decode(part[ 1]);
config::input.joypad2.left = decode(part[ 2]);
config::input.joypad2.right = decode(part[ 3]);
config::input.joypad2.a = decode(part[ 4]);
config::input.joypad2.b = decode(part[ 5]);
config::input.joypad2.x = decode(part[ 6]);
config::input.joypad2.y = decode(part[ 7]);
config::input.joypad2.l = decode(part[ 8]);
config::input.joypad2.r = decode(part[ 9]);
config::input.joypad2.select = decode(part[10]);
config::input.joypad2.start = decode(part[11]);
}
const char *Input::encode(uint k) {
strcpy(tmp, key.find(k & 4095));
if(k >> 16) {
strcat(tmp, " | ");
strcat(tmp, key.find((k >> 16) & 4095));
}
return tmp;
}
void Input::term() {
string result;
char t[256];
strcpy(result, "");
strcat(result, keymaptostring(config::input.joypad1.up)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.down)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.left)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.right)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.a)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.b)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.x)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.y)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.l)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.r)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.select)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad1.start));
strcat(result, encode((uint)config::input.joypad1.up)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.down)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.left)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.right)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.a)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.b)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.x)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.y)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.l)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.r)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.select)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad1.start));
config::input.joypad1.map.sset(strptr(result));
strcpy(result, "");
strcat(result, keymaptostring(config::input.joypad2.up)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.down)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.left)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.right)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.a)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.b)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.x)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.y)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.l)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.r)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.select)); strcat(result, "; ");
strcat(result, keymaptostring(config::input.joypad2.start));
strcat(result, encode((uint)config::input.joypad2.up)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.down)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.left)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.right)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.a)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.b)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.x)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.y)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.l)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.r)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.select)); strcat(result, "; ");
strcat(result, encode((uint)config::input.joypad2.start));
config::input.joypad2.map.sset(strptr(result));
}
Input::Input() {
ui_clear_input();
memset(keystate, 0, sizeof(keystate));
clear_input();
}

View File

@ -1,83 +1,37 @@
#define INPUT_JOYMAX 8
#include "../../lib/libkeymap.h"
#define INPUT_JOYMAX 16
class Input {
private:
char tmp[256];
public:
enum {
EVENT_INPUTKEYDOWN = EVENT_USER + 0,
EVENT_INPUTKEYUP = EVENT_USER + 1,
};
struct joypad {
bool up, down, left, right;
bool a, b, x, y, l, r;
bool select, start;
} joypad1, joypad2;
//this must be initialized by init()
struct Keymap {
uint esc;
uint f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12;
uint print_screen, scroll_lock, pause;
uint tilde;
uint num_0, num_1, num_2, num_3, num_4;
uint num_5, num_6, num_7, num_8, num_9;
uint minus, plus, backspace;
uint ins, del, home, end, page_up, page_down;
uint a, b, c, d, e, f, g, h, i, j, k, l, m;
uint n, o, p, q, r, s, t, u, v, w, x, y, z;
uint lbracket, rbracket, pipe;
uint colon, quote;
uint comma, period, question;
uint numpad_0, numpad_1, numpad_2, numpad_3, numpad_4;
uint numpad_5, numpad_6, numpad_7, numpad_8, numpad_9;
uint numpad_plus, numpad_minus, numpad_mul, numpad_div;
uint numpad_enter, numpad_point;
uint numlock, capslock;
uint up, down, left, right;
uint tab, enter, space;
uint lctrl, rctrl;
uint lalt, ralt;
uint lshift, rshift;
uint lwin, rwin, menu;
} keymap;
uint8 keystate[256], joystate[INPUT_JOYMAX * 256];
uint8 old_keystate[256], old_joystate[INPUT_JOYMAX * 256];
enum {
//bit 31: clear = keypress, set = joypress
KEYFLAG = 0x00000000,
JOYFLAG = 0x80000000,
JOYMASK = 0xffff00,
KEYMASK = 0x0000ff,
JOYKEYMASK = 0xffffff,
JOY_NONE = 0xffff00,
KEY_NONE = 0x0000ff,
JOYKEY_NONE = 0xffffff,
};
keymap key; //this must be initialized by init()
bool8 keystate[4096];
virtual void poll() = 0;
virtual void ui_poll_input(Window *focus, bool require_window_focus = true);
virtual void ui_clear_input();
virtual void poll(uint8 type) = 0;
virtual bool get_status(uint8 device, uint8 button) = 0;
virtual void set_status(uint8 device, uint8 button, bool status) = 0;
virtual void clear_input() = 0;
virtual void poll(uint8 device);
virtual void init();
virtual void term();
//helper functions
bool keydown(uint id);
uint stringtokeymap(const char *str);
const char *keymaptostring(uint key);
uint get_keymap(uint device, uint button);
void set_keymap(uint device, uint button, uint keymap);
bool get_status(uint8 device, uint8 button);
void set_status(uint8 device, uint8 button, bool status);
void clear_input();
bool keydown(uint16 key);
uint get_key(uint device, uint button);
void set_key(uint device, uint button, uint key);
uint decode(substring&);
const char *encode(uint);
Input();
} *uiInput;

View File

@ -1,6 +1,7 @@
#define INTERFACE_MAIN
#include "../base.h"
#include "main.h"
#include "config.cpp"
void init_snes();
@ -10,31 +11,25 @@ void term_snes();
* OS abstraction layer
*****/
//#include "video/video.h"
//#include "audio/audio.h"
//#include "input/input.h"
#include "video/video.h"
#include "audio/audio.h"
#include "input/input.h"
//#include "video/video.cpp"
//#include "input/input.cpp"
/*****
* emulation abstraction layer
*****/
#include "bsnes.h"
#include "video/video.cpp"
#include "input/input.cpp"
/*****
* platform abstraction layer
*****/
#ifdef PLATFORM_WIN
#if defined(PLATFORM_WIN)
#include "win/main.cpp"
#elif defined(PLATFORM_SDL)
#include "sdl/main.cpp"
#else
#error "unsupported platform"
#endif
#include "bsnes.cpp"
/*****
* platform independent code
*****/

0
src/ui/main.h Normal file
View File

View File

@ -15,14 +15,8 @@ void bSNES::video_run() {
if(r_ppu->status.frames_updated) {
char s[512], t[512];
r_ppu->status.frames_updated = false;
// if((bool)config::gui.show_fps == true) {
sprintf(s, "%s : %d fps", BSNES_TITLE, r_ppu->status.frames_executed);
// if(w_main->frameskip != 0) {
// sprintf(t, " (%d frames)", r_ppu->status.frames_rendered);
// strcat(s, t);
// }
SDL_WM_SetCaption(s, 0);
// }
sprintf(s, "%s : %d fps", BSNES_TITLE, r_ppu->status.frames_executed);
SDL_WM_SetCaption(s, 0);
}
render();
@ -30,7 +24,7 @@ void bSNES::video_run() {
void bSNES::sound_run(uint32 data) {}
uint16 *bSNES::video_lock(uint32 &pitch) {
uint16 *bSNES::video_lock(uint &pitch) {
if(SDL_MUSTLOCK(screen)) {
SDL_LockSurface(screen);
}

View File

@ -17,7 +17,7 @@ enum { STOP = 0, RUN };
void video_run();
void sound_run(uint32 data);
uint16 *video_lock(uint32 &data);
uint16 *video_lock(uint &data);
void video_unlock();
void set_status(uint32 new_status);
@ -29,6 +29,4 @@ enum { STOP = 0, RUN };
void notify(uint32 message, uint32 param1 = 0, uint32 param2 = 0);
bSNES();
};
bSNES *bsnes;
} *bsnes;

View File

@ -1,12 +1,4 @@
#define INTERFACE_MAIN
#include "../base.h"
#include "sdlmain.h"
#include "config.cpp"
#ifdef _WIN32_
HWND hwnd;
#endif
#include "main.h"
#include "bsnes.h"
#include "render.cpp"
@ -18,7 +10,7 @@ va_list args;
va_start(args, s);
vsprintf(str, s, args);
va_end(args);
#ifdef _WIN32_
#ifdef _WIN32
MessageBox(0, str, "bsnes", MB_OK);
#else
fprintf(stdout, "%s\r\n", str);
@ -34,42 +26,12 @@ va_list args;
fprintf(stdout, "%s\r\n", str);
}
void init_snes() {
#ifdef POLYMORPHISM
deref(mem) = new bMemBus();
deref(cpu) = new bCPU();
deref(apu) = new bAPU();
deref(dsp) = new bDSP();
deref(ppu) = new bPPU();
#endif
snes = new bSNES();
bsnes = static_cast<bSNES*>(snes);
snes->init();
//TODO: add sound support and remove this,
//this is used with linux/bsd and mkfifo to
//play audio in real-time while sound output
//isn't available.
snes->log_audio_enable("output.wav");
}
void term_snes() {
snes->term();
#ifdef POLYMORPHISM
SafeDelete(deref(mem));
SafeDelete(deref(cpu));
SafeDelete(deref(apu));
SafeDelete(deref(dsp));
SafeDelete(deref(ppu));
#endif
SafeDelete(snes);
}
void center_window() {
#ifdef _WIN32_
#ifdef _WIN32
HWND hwnd;
RECT rc;
int x, y;
hwnd = FindWindow(0, BSNES_TITLE);
GetWindowRect(hwnd, &rc);
x = (GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) >> 1;
y = (GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) >> 1;
@ -77,29 +39,13 @@ int x, y;
#endif
}
void set_window_info() {
//SDL won't draw anything if you blit an image that's larger than
//the display mode/window, even if you use the SoftStretch blit and
//clip the source + dest rectangles properly...
if((int)config::video.display_width < (int)config::video.output_width) {
config::video.display_width = config::video.output_width;
}
if((int)config::video.display_height < (int)config::video.output_height) {
config::video.display_height = config::video.output_height;
}
screen_info.rd.x = ((int)config::video.display_width - (int)config::video.output_width ) >> 1;
screen_info.rd.y = ((int)config::video.display_height - (int)config::video.output_height) >> 1;
screen_info.rd.w = config::video.output_width;
screen_info.rd.h = config::video.output_height;
}
#ifdef _WIN32_
#ifdef _WIN32
int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) {
int argc = __argc;
char **argv = __argv;
SDL_SetModuleHandle(GetModuleHandle(0));
#else
int main(int argc, char *argv[]) {
int SDL_main(int argc, char *argv[]) {
#endif
SDL_Event event;
@ -120,17 +66,20 @@ SDL_Event event;
SDL_Init(SDL_INIT_VIDEO);
atexit(SDL_Quit);
set_window_info();
screen = SDL_SetVideoMode(config::video.display_width, config::video.display_height, 16,
screen_rect.x = 0;
screen_rect.y = 0;
screen_rect.w = 256;
screen_rect.h = 224;
screen = SDL_SetVideoMode(screen_rect.w, screen_rect.h, 16,
SDL_HWSURFACE | ((config::video.fullscreen) ? SDL_FULLSCREEN : 0));
if(!screen) { alert("Failed to initialize SDL"); goto _end; }
backbuffer = SDL_CreateRGBSurface(SDL_HWSURFACE, 512, 448, 16, 0xf800, 0x07e0, 0x001f, 0x0000);
if(!backbuffer) { alert("Failed to initialize SDL"); goto _end; }
SDL_WM_SetCaption(BSNES_TITLE, 0);
#ifdef _WIN32_
hwnd = FindWindow(0, BSNES_TITLE);
#endif
center_window();
snes->power();

8
src/ui/sdl/main.h Normal file
View File

@ -0,0 +1,8 @@
#ifdef _WIN32
#include <windows.h>
#endif
#include "SDL.h"
SDL_Surface *screen, *backbuffer;
SDL_Rect screen_rect;

18
src/ui/sdl/render.cpp Normal file
View File

@ -0,0 +1,18 @@
void render() {
SNES::video_info vi;
snes->get_video_info(&vi);
SDL_Rect rect;
rect.x = 0;
rect.y = (vi.height == 224) ? 1 : 2;
rect.w = vi.width;
rect.h = (vi.height == 224) ? 223 : 446;
//documentation says not to use this, but it's rather ridiculous that a graphics
//library wouldn't support simple image scaling... so let's use it anyway and see
//what happens...
SDL_SoftStretch(backbuffer, &rect, screen, &screen_rect);
//SDL_BlitSurface(backbuffer, &rect, screen, &screen_rect);
SDL_UpdateRect(screen, screen_rect.x, screen_rect.y, screen_rect.w, screen_rect.h);
}

View File

@ -5,7 +5,6 @@ HRESULT hr;
term();
update_video_settings();
update_window();
lpd3d = Direct3DCreate9(D3D_SDK_VERSION);
if(!lpd3d) {
@ -117,7 +116,6 @@ HRESULT hr;
static_cast<D3DPOOL>(flags.v_pool), &vertex_buffer, NULL);
clear_video();
update_window();
return true;
}
@ -170,7 +168,7 @@ D3DLOCKED_RECT d3dlr;
}
}
uint16 *VideoD3D::lock(uint32 &pitch) {
uint16 *VideoD3D::lock(uint &pitch) {
if(caps.stretchrect == false) {
texture->GetLevelDesc(0, &d3dsd);
texture->GetSurfaceLevel(0, &surface);

View File

@ -36,9 +36,12 @@ struct {
void set_vertex(uint32 px, uint32 py, uint32 pw, uint32 ph,
uint32 tw, uint32 th, uint32 x, uint32 y, uint32 w, uint32 h);
uint16 *lock(uint32 &pitch);
uint16 *lock(uint &pitch);
void unlock();
uint screen_width() { return GetScreenWidth(); }
uint screen_height() { return GetScreenHeight(); }
void pause_enable();
void pause_disable();

View File

@ -2,7 +2,6 @@ bool VideoDD::update_video_profile() {
term();
update_video_settings();
update_window();
DirectDrawCreate(0, &lpdd, 0);
lpdd->QueryInterface(IID_IDirectDraw7, (void**)&lpdd7);
@ -23,7 +22,6 @@ bool VideoDD::update_video_profile() {
create_render_target();
clear_video();
update_window();
return true;
}
@ -85,7 +83,7 @@ DDBLTFX fx;
surface->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx);
}
uint16 *VideoDD::lock(uint32 &pitch) {
uint16 *VideoDD::lock(uint &pitch) {
if(surface->Lock(0, &ddsd, DDLOCK_WAIT, 0) != DD_OK)return 0;
pitch = ddsd.lPitch;
return (uint16*)ddsd.lpSurface;

View File

@ -11,9 +11,12 @@ DDSURFACEDESC2 ddsd;
DDSCAPS2 ddscaps;
public:
uint16 *lock(uint32 &pitch);
uint16 *lock(uint &pitch);
void unlock();
uint screen_width() { return GetScreenWidth(); }
uint screen_height() { return GetScreenHeight(); }
bool update_video_profile();
void init();
void term();

View File

@ -73,20 +73,20 @@ uint profile = uint(config::video.profile);
load_video_settings(profile);
VideoSettings *v = &video_settings[profile];
snes->set_video_format(v->software_filter, SNES::PIXELFORMAT_RGB565);
snes->set_video_format(v->software_filter, v->video_standard, SNES::PIXELFORMAT_RGB565);
if(v->manual_render_size == true) {
settings.render_width = v->render_width;
settings.render_height = v->render_height;
} else {
settings.render_width = 256;
settings.render_height = (v->video_standard == 0) ? 224 : 239;
settings.render_height = (v->video_standard == SNES::VIDEOSTANDARD_NTSC) ? 224 : 239;
settings.render_width *= (v->multiplier + 1);
settings.render_height *= (v->multiplier + 1);
if(v->correct_aspect_ratio == true) {
settings.render_width = uint( double(settings.render_height) / 3.0 * 4.0 );
settings.render_width = (uint)( (double)settings.render_height / 3.0 * 4.0 );
}
}
@ -94,9 +94,9 @@ VideoSettings *v = &video_settings[profile];
settings.triple_buffering = v->triple_buffering;
settings.enable_scanlines = v->enable_scanlines;
if(bool(config::video.fullscreen) == true) {
settings.resolution_width = (v->resolution_width) ? v->resolution_width : GetScreenWidth();
settings.resolution_height = (v->resolution_height) ? v->resolution_height : GetScreenHeight();
if((bool)config::video.fullscreen == true) {
settings.resolution_width = (v->resolution_width) ? v->resolution_width : screen_width();
settings.resolution_height = (v->resolution_height) ? v->resolution_height : screen_height();
settings.refresh_rate = v->refresh_rate;
} else {
settings.resolution_width = settings.render_width;
@ -104,28 +104,19 @@ VideoSettings *v = &video_settings[profile];
settings.refresh_rate = 0;
}
settings.internal_height_normal = 224;
settings.internal_height_overscan = (v->video_standard == 0) ? 224 : 239;
settings.rx = (settings.resolution_width - settings.render_width) >> 1;
settings.ry = (settings.resolution_height - settings.render_height) >> 1;
settings.rw = (settings.render_width);
settings.rh = (settings.render_height);
}
void Video::update_window() {
string t;
if(bool(config::video.fullscreen) == true) {
strcpy(t, "topmost|popup");
if(wMain.Visible())strcat(t, "|visible");
wMain.HideMenu();
HideCursor();
if(settings.render_width <= settings.resolution_width) {
settings.rx = (settings.resolution_width - settings.render_width) >> 1;
settings.rw = settings.render_width;
} else {
strcpy(t, config::misc.window_style.sget());
if(wMain.Visible())strcat(t, "|visible");
wMain.ShowMenu();
ShowCursor();
settings.rx = 0;
settings.rw = settings.resolution_width;
}
if(settings.render_height <= settings.resolution_height) {
settings.ry = (settings.resolution_height - settings.render_height) >> 1;
settings.rh = settings.render_height;
} else {
settings.ry = 0;
settings.rh = settings.resolution_height;
}
wMain.SetStyle(strptr(t));
wMain.Resize(settings.resolution_width, settings.resolution_height, true);
}

View File

@ -38,21 +38,21 @@ struct {
uint resolution_height;
uint refresh_rate;
uint internal_height_normal;
uint internal_height_overscan;
uint rx, ry, rw, rh;
} settings;
void update_video_settings();
void update_window();
virtual uint16 *lock(uint32 &pitch) = 0;
virtual uint16 *lock(uint &pitch) = 0;
virtual void unlock() = 0;
virtual uint screen_width() = 0;
virtual uint screen_height() = 0;
virtual bool update_video_profile() = 0;
virtual void clear_video() = 0;
virtual void pause_enable() {}
virtual void pause_disable() {}
virtual void clear_video() = 0;
virtual bool update_video_profile() = 0;
virtual void update_hardware_filter() {}
virtual void update_scanlines() {}

View File

@ -84,7 +84,7 @@ void bSNES::sound_run(uint32 data) {
*** video functions ***
***********************/
uint16 *bSNES::video_lock(uint32 &pitch) {
uint16 *bSNES::video_lock(uint &pitch) {
return uiVideo->lock(pitch);
}

View File

@ -15,7 +15,7 @@ uint32 state;
void sound_run(uint32 data);
//video functions
uint16 *video_lock(uint32 &pitch);
uint16 *video_lock(uint &pitch);
void video_unlock();
//input functions
@ -26,6 +26,4 @@ uint32 state;
void notify(uint32 message, uint32 param1 = 0, uint32 param2 = 0);
bSNES() { state = RUN; }
};
bSNES *bsnes;
} *bsnes;

View File

@ -27,6 +27,23 @@ void set_video_profile(uint profile) {
if(profile > 7)profile = 0;
config::video.profile = profile;
uiVideo->update_video_settings();
string t;
if(bool(config::video.fullscreen) == true) {
strcpy(t, "topmost|popup");
if(wMain.Visible())strcat(t, "|visible");
wMain.HideMenu();
HideCursor();
} else {
strcpy(t, config::misc.window_style.sget());
if(wMain.Visible())strcat(t, "|visible");
wMain.ShowMenu();
ShowCursor();
}
wMain.SetStyle(strptr(t));
wMain.Resize(uiVideo->settings.resolution_width, uiVideo->settings.resolution_height, true);
uiVideo->update_video_profile();
wMain.CheckMenuItem(MENU_SETTINGS_VIDEOPROFILE_0, profile == 0);

View File

@ -3,15 +3,12 @@
#include "config.cpp"
#include "bsnes.h"
#include "event.h"
#include "ui.h"
#include "../video/video.h"
#include "../audio/audio.h"
#include "../input/input.h"
#include "../video/video.cpp"
#include "../input/input.cpp"
#include "bsnes.cpp"
#include "../video/d3d.h"
#include "../video/ddraw.h"

View File

@ -1,7 +1,6 @@
void CALLBACK wInputConfigInputTimerProc(HWND hwnd, UINT msg, UINT event, DWORD time) {
if(!uiInput)return;
uiInput->ui_poll_input(&wInputConfig, false);
ui_poll_input(&wInputConfig, false);
}
bool InputConfigWindow::Event(EventInfo &info) {
@ -13,13 +12,13 @@ bool InputConfigWindow::Event(EventInfo &info) {
HDC hdcsrc = CreateCompatibleDC(hdc);
HBITMAP hbm = LoadBitmap(GetModuleHandle(0), MAKEINTRESOURCE(102));
SelectObject(hdcsrc, hbm);
BitBlt(hdc, 285, 139, 190, 100, hdcsrc, 0, 0, SRCCOPY);
BitBlt(hdc, 285, 169, 190, 100, hdcsrc, 0, 0, SRCCOPY);
DeleteDC(hdcsrc);
DeleteObject(hbm);
EndPaint(hwnd, &ps);
} break;
case Input::EVENT_INPUTKEYDOWN: {
case EVENT_INPUTKEYDOWN: {
if(button_update.active == true) {
button_update.id = info.control_id;
ButtonUpdateEnd();
@ -42,19 +41,32 @@ bool InputConfigWindow::Event(EventInfo &info) {
case EVENT_DOUBLECLICKED: {
if(info.control == &ButtonList) {
int sel = ButtonList.GetSelection();
if(sel != -1)ButtonUpdateBegin(sel);
if(sel != -1) {
button_update.primary = true;
ButtonUpdateBegin(sel);
}
}
} break;
case EVENT_CLICKED: {
if(info.control == &ButtonUpdate) {
if(info.control == &ButtonUpdatePrimary ||
info.control == &ButtonUpdateSecondary) {
int sel = ButtonList.GetSelection();
if(sel != -1)ButtonUpdateBegin(sel);
if(sel != -1) {
button_update.primary = (info.control == &ButtonUpdatePrimary);
ButtonUpdateBegin(sel);
}
} else if(info.control == &ButtonClear) {
int sel = ButtonList.GetSelection();
if(sel != -1) {
button_update.primary = true;
ButtonUpdateBegin(sel);
button_update.id = uiInput->keymap.esc;
button_update.id = uiInput->key.esc;
ButtonUpdateEnd();
button_update.primary = false;
ButtonUpdateBegin(sel);
button_update.id = uiInput->key.esc;
ButtonUpdateEnd();
}
} else if(info.control == &AllowBadInput) {
@ -100,9 +112,12 @@ uint device = Selected.GetSelection();
char t[512], tmp[512];
string str, part;
#define add(__label, __bn) \
strcpy(tmp, uiInput->keymaptostring(uiInput->get_keymap(device, SNES::JOYPAD_##__bn))); \
strcpy(tmp, uiInput->key.find((uiInput->get_key(device, SNES::JOYPAD_##__bn) >> 0) & 4095)); \
strcat(tmp, " | "); \
strcat(tmp, uiInput->key.find((uiInput->get_key(device, SNES::JOYPAD_##__bn) >> 16) & 4095)); \
split(part, " | ", tmp); \
replace(part[0], "keynone", "<none>"); \
replace(part[0], "null", "<none>"); \
replace(part[1], "null", "<none>"); \
if(count(part) < 2)strcpy(part[1], "<none>"); \
sprintf(t, #__label "|%s|%s", strptr(part[0]), strptr(part[1])); \
ButtonList.AddItem(t);
@ -137,35 +152,19 @@ void InputConfigWindow::ButtonUpdateEnd() {
button_update.active = false;
KillTimer(hwnd, 0);
uint old_id, id = button_update.id;
if(id == uiInput->keymap.esc) {
//escape key was pressed, clear key + joy mapping
id = Input::JOYKEY_NONE;
uint id = button_update.id;
if(id == uiInput->key.esc) { id = 0; }
uint old_id = uiInput->get_key(button_update.controller, button_update.button);
if(button_update.primary == true) {
id &= 0xffff;
id |= old_id & ~0xffff;
} else {
old_id = uiInput->get_keymap(button_update.controller, button_update.button);
if(id & Input::JOYFLAG) {
//joypad key was pressed
//format for EVENT_INPUTKEY(DOWN|UP) is (joypad<<8)|button,
//format for config file is (joypad<<16)|(button<<8)|key.
//the idea is to allow config file to have both key and joypad
//mapping for a single SNES button, so id must be converted to
//config file format.
id <<= 8;
id &= Input::JOYMASK;
id |= old_id & Input::KEYMASK;
} else {
//keyboard key was pressed
id &= Input::KEYMASK;
id |= old_id & Input::JOYMASK;
}
id &= Input::JOYKEYMASK;
id <<= 16;
id |= old_id & 0xffff;
}
uiInput->set_keymap(button_update.controller, button_update.button, id);
uiInput->set_key(button_update.controller, button_update.button, id);
Message.SetText("Button updated. Select another button to update.");
int sel = ButtonList.GetSelection();
@ -215,10 +214,11 @@ int x = 15, y = 30;
ButtonList.Create(this, "visible|edge", x, y, 265, 195);
ButtonList.AddColumn(Listview::LEFT, 61, "Button");
ButtonList.AddColumn(Listview::LEFT, 100, "Key Mapping");
ButtonList.AddColumn(Listview::LEFT, 100, "Joypad Mapping");
ButtonUpdate.Create(this, "visible", x + 270, y, 92, 25, "Update");
ButtonClear.Create(this, "visible", x + 270 + 98, y, 92, 25, "Clear");
ButtonList.AddColumn(Listview::LEFT, 100, "Primary");
ButtonList.AddColumn(Listview::LEFT, 100, "Secondary");
ButtonUpdatePrimary.Create(this, "visible", x + 270, y, 92, 25, "Set Primary");
ButtonUpdateSecondary.Create(this, "visible", x + 270 + 98, y, 92, 25, "Set Secondary");
ButtonClear.Create(this, "visible", x + 270, y + 30, 190, 25, "Clear Primary + Secondary");
y += 200;
AllowBadInput.Create(this, "visible", x, y, 460, 15,

View File

@ -8,11 +8,13 @@ Combobox Selected;
Label Separator;
Label Message;
Listview ButtonList;
Button ButtonUpdate;
Button ButtonUpdatePrimary;
Button ButtonUpdateSecondary;
Button ButtonClear;
Checkbox AllowBadInput;
struct {
bool primary;
bool active;
uint controller;
uint button;

View File

@ -62,8 +62,8 @@ char t[64 + 1];
save_video_settings(profile);
//update current video mode if necessary
if(profile == uint(config::video.profile)) {
uiVideo->update_video_profile();
if(profile == (uint)config::video.profile) {
event::set_video_profile(config::video.profile);
}
}
@ -97,8 +97,8 @@ int x = 15, y = 30;
y += 25;
VideoStandardLabel.Create(this, "visible", x, y + 3, 85, 15, "Video standard:");
VideoStandard.Create(this, "visible|disabled", x + 85, y, 140, 200,
"NTSC|PAL|PAL (centered)");
VideoStandard.Create(this, "visible", x + 85, y, 140, 200,
"NTSC|PAL");
MultiplierLabel.Create(this, "visible", x + 235, y + 3, 85, 15, "Multiplier:");
Multiplier.Create(this, "visible", x + 320, y, 140, 200,

View File

@ -1,3 +1,4 @@
#include "ui_input.cpp"
#include "ui_main.cpp"
#include "ui_about.cpp"
#include "settings/settings.cpp"

View File

@ -1,5 +1,10 @@
#define KeyDown(__key) ((GetAsyncKeyState(__key) & 0x8000) ? 1 : 0)
enum {
EVENT_INPUTKEYDOWN = EVENT_USER + 0,
EVENT_INPUTKEYUP = EVENT_USER + 1,
};
namespace global {
Font vwf, fwf, font_about, font_header, font_list;
};

View File

@ -5,7 +5,7 @@ const char AboutWindow::about_text[4096] = ""
"\r\n\r\n\r\n\r\n\r\n"
"Contributors:\r\n"
" anomie, blargg, DMV27, GIGO, kode54, Nach,\r\n"
" Overload, Richard Bannister, TRAC\r\n";
" Overload, Richard Bannister, TRAC, zones\r\n";
bool AboutWindow::Event(EventInfo &info) {
switch(info.event_id) {

29
src/ui/win/ui_input.cpp Normal file
View File

@ -0,0 +1,29 @@
bool8 old_keystate[4096];
void ui_poll_input(Window *focus, bool require_window_focus = true) {
if(require_window_focus == true) {
if(GetFocus() != focus->hwnd)return;
}
uiInput->poll();
bool8 *keystate = uiInput->keystate;
EventInfo info;
info.window = focus;
info.window_id = focus->id;
info.control = 0;
for(int i = 0; i < 4096; i++) {
if(!old_keystate[i] && keystate[i]) {
info.event_id = EVENT_INPUTKEYDOWN;
info.control_id = i;
focus->Event(info);
} else if(old_keystate[i] && !keystate[i]) {
info.event_id = EVENT_INPUTKEYUP;
info.control_id = i;
focus->Event(info);
}
}
memcpy(old_keystate, keystate, sizeof(keystate));
}

View File

@ -1,7 +1,5 @@
void CALLBACK wMainInputTimerProc(HWND hwnd, UINT msg, UINT event, DWORD time) {
if(!uiInput)return;
uiInput->ui_poll_input(&wMain);
if(uiInput) { ui_poll_input(&wMain); }
}
void MainWindow::SetFrameskip(uint fs) {
@ -42,11 +40,11 @@ void MainWindow::SetRegulationSpeed(uint speed) {
bool MainWindow::Event(EventInfo &info) {
switch(info.event_id) {
case Input::EVENT_INPUTKEYDOWN: {
Input::Keymap *keymap = &uiInput->keymap;
uint key = info.control_id;
bool ctrl = uiInput->keydown(keymap->lctrl) || uiInput->keydown(keymap->rctrl);
if(key == keymap->esc) {
case EVENT_INPUTKEYDOWN: {
keymap *key = &uiInput->key;
uint id = info.control_id;
bool ctrl = uiInput->keydown(key->lctrl) || uiInput->keydown(key->rctrl);
if(id == key->esc) {
if(bool(config::video.fullscreen) == false) {
ShowMenu(!MenuVisible());
Center();
@ -54,37 +52,37 @@ bool MainWindow::Event(EventInfo &info) {
config::video.fullscreen = false;
event::set_video_profile(config::video.profile);
}
} else if(key == keymap->f11) {
} else if(id == key->f11) {
event::toggle_fullscreen();
} else if(key == keymap->f12) {
} else if(id == key->f12) {
if(bsnes->get_state() == bSNES::RUN) {
bsnes->set_state(bSNES::STOP);
} else if(bsnes->get_state() == bSNES::STOP) {
bsnes->set_state(bSNES::RUN);
}
} else if(key == keymap->num_1 && ctrl) {
} else if(id == key->num_1 && ctrl) {
event::set_video_profile(0);
} else if(key == keymap->num_2 && ctrl) {
} else if(id == key->num_2 && ctrl) {
event::set_video_profile(1);
} else if(key == keymap->num_3 && ctrl) {
} else if(id == key->num_3 && ctrl) {
event::set_video_profile(2);
} else if(key == keymap->num_4 && ctrl) {
} else if(id == key->num_4 && ctrl) {
event::set_video_profile(3);
} else if(key == keymap->num_5 && ctrl) {
} else if(id == key->num_5 && ctrl) {
event::set_video_profile(4);
} else if(key == keymap->num_6 && ctrl) {
} else if(id == key->num_6 && ctrl) {
event::set_video_profile(5);
} else if(key == keymap->num_7 && ctrl) {
} else if(id == key->num_7 && ctrl) {
event::set_video_profile(6);
} else if(key == keymap->num_8 && ctrl) {
} else if(id == key->num_8 && ctrl) {
event::set_video_profile(7);
} else if((key == keymap->minus && !ctrl) || key == keymap->numpad_minus) {
} else if((id == key->minus && !ctrl) || id == key->numpad_minus) {
if(frameskip > 0)SetFrameskip(frameskip - 1);
} else if((key == keymap->plus && !ctrl) || key == keymap->numpad_plus) {
} else if((id == key->plus && !ctrl) || id == key->numpad_plus) {
if(frameskip < 9)SetFrameskip(frameskip + 1);
} else if(key == keymap->minus && ctrl) {
} else if(id == key->minus && ctrl) {
if(regulation_speed > 0)SetRegulationSpeed(regulation_speed - 1);
} else if(key == keymap->plus && ctrl) {
} else if(id == key->plus && ctrl) {
if(regulation_speed < 4)SetRegulationSpeed(regulation_speed + 1);
}
} break;