mirror of
https://github.com/ares-emulator/ares.git
synced 2026-11-09 01:09:46 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9ca01fe20 | ||
|
|
becf122aaa | ||
|
|
1e130d7872 | ||
|
|
c57c733d7d | ||
|
|
e41aa25887 | ||
|
|
435f7d4371 |
No files matched your search
+2
-2
@@ -53,11 +53,11 @@ information in the header. The lack of such a header indicates said file falls
|
||||
under the bsnes license.
|
||||
|
||||
HQ2x Filter, author: MaxST, license: LGPL
|
||||
JMA, author: NSRT Team, license: GPL *
|
||||
JMA, author: NSRT Team, license: GPL (*)
|
||||
libco, author: byuu, license: public domain
|
||||
libui, author: byuu, license: public domain
|
||||
NTSC Filter, author: blargg, license: LGPL
|
||||
S-DD1, author: Andreas Naive, license: public domain
|
||||
zlib, license: zlib license
|
||||
|
||||
* bsnes has received an exemption from the copyright holder to use this work.
|
||||
(*) bsnes has received an exemption from the copyright holder to use this work.
|
||||
+15
-9
@@ -1,8 +1,8 @@
|
||||
bsnes
|
||||
Version 0.021
|
||||
Version 0.023
|
||||
Author: byuu
|
||||
|
||||
|
||||
--------
|
||||
General:
|
||||
--------
|
||||
bsnes is a Super Nintendo / Super Famicom emulator that began on
|
||||
@@ -13,16 +13,22 @@ http://byuu.org/
|
||||
|
||||
Please see license.txt for important licensing information.
|
||||
|
||||
--------------
|
||||
Shortcut Keys:
|
||||
--------------
|
||||
Esc - Toggle menubar visibility
|
||||
F11 - Toggle fullscreen
|
||||
|
||||
------------------
|
||||
Known Limitations:
|
||||
------------------
|
||||
S-CPU
|
||||
- Invalid DMA / HDMA transfers (eg WRAM<>WRAM) not fully emulated
|
||||
- Invalid DMA / HDMA transfers not fully emulated
|
||||
- Multiply / Divide register delays not implemented
|
||||
|
||||
S-PPU
|
||||
- Uses scanline-based renderer. This is very inaccurate, but very few games
|
||||
rely on mid-scanline writes to function correctly
|
||||
- Uses scanline-based renderer. This is very inaccurate, but few (if any)
|
||||
games rely on mid-scanline writes to function correctly
|
||||
- Does not support FirstSprite+Y priority
|
||||
- OAM / CGRAM accesses during active display not supported correctly
|
||||
- RTO flags are not calculated on frames that are skipped when frameskipping
|
||||
@@ -31,10 +37,10 @@ S-PPU
|
||||
Turning frameskipping off will allow RTO flag calculation on every frame
|
||||
|
||||
Hardware Bugs
|
||||
- CPUr1 HDMA crashing bug not emulated
|
||||
- CPU<>APU communication bus conflicts not emulated
|
||||
|
||||
- S-CPU.r1 HDMA crashing bug not emulated
|
||||
- S-CPU<>S-SMP communication bus conflicts not emulated
|
||||
|
||||
---------------------
|
||||
Unsupported Hardware:
|
||||
---------------------
|
||||
SA-1
|
||||
@@ -79,7 +85,7 @@ Flash cartridge used by BS-X, as well as some standalone games by Asciisoft
|
||||
Super Gameboy
|
||||
Cartridge passthrough used for playing Gameboy games
|
||||
|
||||
|
||||
------------------------
|
||||
Unsupported Controllers:
|
||||
------------------------
|
||||
Mouse
|
||||
|
||||
+41
-4
@@ -38,7 +38,7 @@ CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
@@ -49,7 +49,7 @@ CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGINSTRUMENT
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
@@ -61,12 +61,34 @@ CC = cl
|
||||
CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib
|
||||
LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
LINK = /link /PGD:bsnes.pgd /LTCG:PGOPTIMIZE
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-mingw-lui)
|
||||
OS = win
|
||||
CC = mingw32-gcc
|
||||
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM),win-mingw4-lui)
|
||||
OS = win
|
||||
CC = mingw32-gcc-sjlj
|
||||
CFLAGS = -mwindows -O3 -fomit-frame-pointer -DPLATFORM_WIN -DCOMPILER_GCC -DPROCESSOR_X86 -DUI_LUI
|
||||
AS = nasm
|
||||
ASFLAGS = -f win32 -DWIN32
|
||||
LIBS = -ld3d9 -lddraw -ldsound -ldinput8 -ldxguid -luuid -lkernel32 -luser32 -lgdi32 -lshell32 -lwinmm -lcomdlg32 -lcomctl32
|
||||
LIBCO = libco_x86
|
||||
LIBUI = libui_win
|
||||
endif
|
||||
|
||||
#####################################
|
||||
### compiler / assembler switches ###
|
||||
#####################################
|
||||
@@ -79,6 +101,22 @@ CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),mingw32-gcc)
|
||||
OUT = -obsnes
|
||||
CPP = mingw32-g++
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),mingw32-gcc-sjlj)
|
||||
OUT = -obsnes
|
||||
CPP = mingw32-g++-sjlj
|
||||
OBJ = o
|
||||
CARGS = -c $< -o $@
|
||||
DEFINE = -D
|
||||
endif
|
||||
|
||||
ifeq ($(CC),cl)
|
||||
OUT = /Febsnes
|
||||
CPP = cl
|
||||
@@ -106,7 +144,6 @@ endif
|
||||
ifeq ($(OS),win)
|
||||
OUT := $(OUT).exe
|
||||
RM = del
|
||||
LIBS += kernel32.lib user32.lib gdi32.lib shell32.lib winmm.lib comdlg32.lib comctl32.lib
|
||||
endif
|
||||
|
||||
####################################
|
||||
|
||||
+5
-4
@@ -1,4 +1,4 @@
|
||||
#define BSNES_VERSION "0.021"
|
||||
#define BSNES_VERSION "0.023"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define MEMCORE bMemBus
|
||||
@@ -31,6 +31,7 @@
|
||||
#error "unsupported processor"
|
||||
#endif
|
||||
|
||||
#include "lib/libfunctor.h"
|
||||
#include "lib/libsort.h"
|
||||
#include "lib/libarray.h"
|
||||
#include "lib/libvector.h"
|
||||
@@ -38,9 +39,9 @@
|
||||
#include "lib/libconfig.h"
|
||||
|
||||
//platform-specific global functions
|
||||
void alert(char*, ...);
|
||||
void dprintf(char*, ...);
|
||||
void dprintf(uint, char*, ...);
|
||||
void alert(const char*, ...);
|
||||
void dprintf(const char*, ...);
|
||||
void dprintf(uint, const char*, ...);
|
||||
|
||||
namespace source {
|
||||
enum {
|
||||
|
||||
@@ -89,6 +89,21 @@ IntegerSetting PPU::Hack::obj_cache(&config_file, "ppu.hack.obj_cache",
|
||||
"This is technically closer to the actual operation of the SNES,\n"
|
||||
"but can cause problems in some games if enabled",
|
||||
IntegerSetting::Boolean, false);
|
||||
IntegerSetting PPU::Hack::oam_address_invalidation(&config_file, "ppu.hack.oam_address_invalidation",
|
||||
"OAM access address changes during active display, as the S-PPU reads\n"
|
||||
"data to render the display. Thusly, the address retrieved when accessing\n"
|
||||
"OAM during active display is unpredictable. Unfortunately, the exact\n"
|
||||
"algorithm for this is completely unknown at this time. It is more hardware\n"
|
||||
"accurate to enable this setting, but one must *not* rely on the actual\n"
|
||||
"address to match hardware under emulation.",
|
||||
IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::Hack::cgram_address_invalidation(&config_file, "ppu.hack.cgram_address_invalidation",
|
||||
"CGRAM access address changes during active display (excluding hblank), as\n"
|
||||
"the S-PPU reads data to render the display. Thusly, as with OAM, the access\n"
|
||||
"address is unpredictable. Again, enabling this setting is more hardware\n"
|
||||
"accurate, but one must *not* rely on the actual address to match hardware\n"
|
||||
"under emulation.",
|
||||
IntegerSetting::Boolean, true);
|
||||
|
||||
IntegerSetting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", IntegerSetting::Boolean, true);
|
||||
IntegerSetting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", IntegerSetting::Boolean, true);
|
||||
|
||||
@@ -30,6 +30,8 @@ extern struct PPU {
|
||||
struct Hack {
|
||||
static IntegerSetting render_scanline_position;
|
||||
static IntegerSetting obj_cache;
|
||||
static IntegerSetting oam_address_invalidation;
|
||||
static IntegerSetting cgram_address_invalidation;
|
||||
} hack;
|
||||
|
||||
static IntegerSetting opt_enable;
|
||||
|
||||
+11
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
libbase : version 0.10 ~byuu (2007-06-04)
|
||||
libbase : version 0.11 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <new>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#include <shlobj.h>
|
||||
@@ -34,6 +34,10 @@
|
||||
|
||||
#define NOMINMAX
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#define va_copy(dst, src) ((dst) = (src))
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
#define getcwd _getcwd
|
||||
#define ftruncate _chsize
|
||||
#define mkdir _mkdir
|
||||
@@ -41,11 +45,10 @@
|
||||
#define rmdir _rmdir
|
||||
#define vsnprintf _vsnprintf
|
||||
|
||||
#define va_copy(dst, src) ((dst) = (src))
|
||||
static char *realpath(const char *file_name, char *resolved_name) {
|
||||
return _fullpath(resolved_name, file_name, PATH_MAX);
|
||||
}
|
||||
#elif defined(__GNUC__)
|
||||
#else
|
||||
#define mkdir(path) (mkdir)(path, 0755);
|
||||
#endif
|
||||
|
||||
@@ -90,13 +93,13 @@ typedef int64_t int64;
|
||||
//userpath(output) retrieves path to user's home folder
|
||||
//output must be at least as large as PATH_MAX
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||
static char *userpath(char *output) {
|
||||
strcpy(output, "."); //failsafe
|
||||
SHGetFolderPath(0, CSIDL_APPDATA | CSIDL_FLAG_CREATE, 0, 0, output);
|
||||
return output;
|
||||
}
|
||||
#elif defined(__GNUC__)
|
||||
#else
|
||||
static char *userpath(char *output) {
|
||||
strcpy(output, "."); //failsafe
|
||||
struct passwd *userinfo = getpwuid(getuid());
|
||||
@@ -136,14 +139,10 @@ T z = x;
|
||||
y = z;
|
||||
}
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
template<int min, int max, typename T> inline T minmax(const T x) {
|
||||
@@ -170,6 +169,8 @@ enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
|
||||
return ((x & m) ^ b) - b;
|
||||
}
|
||||
|
||||
//bit shifting functions are deprecated
|
||||
|
||||
template<int n, typename T> inline T rol(const T x) {
|
||||
enum { s = (sizeof(T) << 3) - n };
|
||||
return (x << n) | (x >> s);
|
||||
|
||||
+14
-33
@@ -1,14 +1,14 @@
|
||||
;*****
|
||||
;libco_x86 : version 0.10 ~byuu (2007-04-18)
|
||||
;libco_x86 : version 0.10 ~byuu (2007-09-08)
|
||||
;cross-platform x86 implementation of libco
|
||||
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- visual c++; windows-x86
|
||||
;- mingw; windows-x86
|
||||
;- gcc; osx86
|
||||
;- gcc; linux-x86
|
||||
;- gcc; freebsd-x86
|
||||
;- visual c++; windows; x86
|
||||
;- mingw; windows; x86
|
||||
;- gcc; mac os x; x86
|
||||
;- gcc; linux; x86
|
||||
;- gcc; freebsd; x86
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- esp, ebp, edi, esi, ebx
|
||||
@@ -28,7 +28,7 @@
|
||||
%define free _free
|
||||
|
||||
%define co_active @co_active@0
|
||||
%define co_create @co_create@12
|
||||
%define co_create @co_create@8
|
||||
%define co_delete @co_delete@4
|
||||
%define co_switch @co_switch@4
|
||||
%endif
|
||||
@@ -76,11 +76,10 @@ co_active:
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)(void *data), void *data);
|
||||
;ecx = heapsize
|
||||
;edx = coentry
|
||||
;[esp+4] = data
|
||||
;return = eax
|
||||
;extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
|
||||
;ecx = heapsize
|
||||
;edx = coentry
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
@@ -101,7 +100,7 @@ co_create:
|
||||
and ecx,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov dword[ecx-4],co_entrypoint ;entry point
|
||||
mov dword[ecx-4],edx ;entry point
|
||||
mov dword[ecx-8],0 ;ebp
|
||||
mov dword[ecx-12],0 ;esi
|
||||
mov dword[ecx-16],0 ;edi
|
||||
@@ -109,11 +108,8 @@ co_create:
|
||||
sub ecx,20
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [eax],ecx ;cothread_t[ 0- 3] = stack heap pointer (esp)
|
||||
mov [eax+4],edx ;cothread_t[ 4- 7] = coentry
|
||||
mov ecx,[esp+4]
|
||||
mov [eax+8],ecx ;cothread_t[ 8-11] = data
|
||||
ret 4 ;return allocated memory block as thread handle
|
||||
mov [eax],ecx ;*cothread_t = stack heap pointer (esp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
@@ -150,18 +146,3 @@ co_switch:
|
||||
pop ebp
|
||||
|
||||
ret
|
||||
|
||||
;*****
|
||||
;void fastcall co_entrypoint();
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_entrypoint:
|
||||
mov ebp,esp
|
||||
.loop
|
||||
mov eax,[co_active_context]
|
||||
mov ecx,[eax+8] ;fastcall
|
||||
push ecx ;stdcall
|
||||
call [eax+4]
|
||||
mov esp,ebp ;cdecl
|
||||
jmp .loop
|
||||
+14
-14
@@ -1,26 +1,26 @@
|
||||
/*
|
||||
libco_x86 : version 0.10 ~byuu (2007-06-04)
|
||||
libco_x86 : version 0.10 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
#undef fastcall
|
||||
#if defined(_MSC_VER)
|
||||
#define fastcall __fastcall
|
||||
#elif defined(__GNUC__)
|
||||
#define fastcall __attribute__((fastcall))
|
||||
#else
|
||||
#error "fastcall undefined"
|
||||
#if !defined(fastcall)
|
||||
#if defined(_MSC_VER)
|
||||
#define fastcall __fastcall
|
||||
#elif defined(__GNUC__)
|
||||
#define fastcall __attribute__((fastcall))
|
||||
#else
|
||||
#error "fastcall undefined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define cocall fastcall
|
||||
typedef void (*cothread_t);
|
||||
typedef void *cothread_t;
|
||||
|
||||
extern "C" cothread_t cocall co_active();
|
||||
extern "C" cothread_t cocall co_create(unsigned int heapsize, void (cocall *coentry)(void *data), void *data);
|
||||
extern "C" void cocall co_delete(cothread_t cothread);
|
||||
extern "C" void cocall co_switch(cothread_t cothread);
|
||||
extern "C" cothread_t fastcall co_active();
|
||||
extern "C" cothread_t fastcall co_create(unsigned int heapsize, void (*coentry)());
|
||||
extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
extern "C" void fastcall co_switch(cothread_t cothread);
|
||||
|
||||
#endif
|
||||
@@ -1,12 +1,12 @@
|
||||
;*****
|
||||
;libco_x86_64 : version 0.10 ~byuu (2007-04-18)
|
||||
;libco_x86_64 : version 0.10 ~byuu (2007-09-08)
|
||||
;cross-platform x86-64 implementation of libco
|
||||
;special thanks to Aaron Giles and Joel Yliluoma for various optimizations
|
||||
;
|
||||
;[ABI compatibility]
|
||||
;- SystemV ( http://refspecs.freestandards.org/elf/x86_64-SysV-psABI.pdf )
|
||||
;- gcc; linux-x86-64
|
||||
;- gcc; freebsd-x86-64
|
||||
;- gcc; linux; x86-64
|
||||
;- gcc; freebsd; x86-64
|
||||
;
|
||||
;[nonvolatile registers]
|
||||
;- rsp, rbp, rbx, r12, r13, r14, r15
|
||||
@@ -50,10 +50,9 @@ co_active:
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)(void *data), void *data);
|
||||
;extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
;rdi = heapsize
|
||||
;rsi = coentry
|
||||
;rdx = data
|
||||
;return = rax
|
||||
;*****
|
||||
|
||||
@@ -63,11 +62,9 @@ co_create:
|
||||
add rdi,512 ;allocate extra memory for contextual info
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
|
||||
call malloc ;rax = malloc(rdi)
|
||||
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
|
||||
@@ -75,7 +72,7 @@ co_create:
|
||||
and rdi,-16 ;force 16-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers, so that first call to co_switch will execute coentry
|
||||
mov qword[rdi-8],co_entrypoint ;entry point
|
||||
mov qword[rdi-8],rsi ;entry point
|
||||
mov qword[rdi-16],0 ;r15
|
||||
mov qword[rdi-24],0 ;r14
|
||||
mov qword[rdi-32],0 ;r13
|
||||
@@ -85,9 +82,7 @@ co_create:
|
||||
sub rdi,56
|
||||
|
||||
;initialize context memory heap and return
|
||||
mov [rax],rdi ;cothread_t[ 0- 7] = stack heap pointer (rsp)
|
||||
mov [rax+8],rsi ;cothread_t[ 8-15] = coentry
|
||||
mov [rax+16],rdx ;cothread_t[16-23] = data
|
||||
mov [rax],rdi ;*cothread_t = stack heap pointer (rsp)
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
@@ -126,14 +121,3 @@ co_switch:
|
||||
pop rbp
|
||||
|
||||
ret
|
||||
|
||||
;*****
|
||||
;void co_entrypoint();
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_entrypoint:
|
||||
mov rax,[co_active_context wrt rip]
|
||||
mov rdi,[rax+16]
|
||||
call [rax+8]
|
||||
jmp co_entrypoint
|
||||
@@ -1,15 +1,15 @@
|
||||
/*
|
||||
libco_x86_64 : version 0.10 ~byuu (2007-04-18)
|
||||
libco_x86_64 : version 0.10 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBCO_H
|
||||
#define LIBCO_H
|
||||
|
||||
#define cocall
|
||||
typedef void (*cothread_t);
|
||||
typedef void *cothread_t;
|
||||
|
||||
extern "C" cothread_t co_active();
|
||||
extern "C" cothread_t co_create(unsigned int heapsize, void (cocall *coentry)(void *data), void *data);
|
||||
extern "C" cothread_t co_create(unsigned int heapsize, void (*coentry)());
|
||||
extern "C" void co_delete(cothread_t cothread);
|
||||
extern "C" void co_switch(cothread_t cothread);
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
libconfig : version 0.14 ~byuu (2007-06-10)
|
||||
libconfig : version 0.14 ~byuu (2007-06-12)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
@@ -103,7 +103,7 @@ string data;
|
||||
bool operator==(const char *x) { return !strcmp(data, x); }
|
||||
bool operator!=(const char *x) { return strcmp(data, x); }
|
||||
|
||||
StringSetting(Config *parent, const char *r_name, const char *r_desc, char *r_data) {
|
||||
StringSetting(Config *parent, const char *r_name, const char *r_desc, const char *r_data) {
|
||||
type = Setting::String;
|
||||
name = strdup(r_name);
|
||||
desc = strdup(r_desc);
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
libfunctor : version 0.05 ~byuu (2007-09-08)
|
||||
license: public domain
|
||||
*/
|
||||
|
||||
#ifndef LIBFUNCTOR_H
|
||||
#define LIBFUNCTOR_H
|
||||
|
||||
//prologue
|
||||
|
||||
#define TN typename
|
||||
|
||||
template<typename T> class functor;
|
||||
|
||||
//parameters = 0
|
||||
|
||||
#define cat(n) n
|
||||
#define TL typename R
|
||||
#define PL
|
||||
#define CL
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 1
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1
|
||||
#define PL P1 p1
|
||||
#define CL p1
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 2
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2
|
||||
#define PL P1 p1, P2 p2
|
||||
#define CL p1, p2
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 3
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3
|
||||
#define PL P1 p1, P2 p2, P3 p3
|
||||
#define CL p1, p2, p3
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 4
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4
|
||||
#define CL p1, p2, p3, p4
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 5
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5
|
||||
#define CL p1, p2, p3, p4, p5
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 6
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6
|
||||
#define CL p1, p2, p3, p4, p5, p6
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 7
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//parameters = 8
|
||||
|
||||
#define cat(n) , n
|
||||
#define TL TN R, TN P1, TN P2, TN P3, TN P4, TN P5, TN P6, TN P7, TN P8
|
||||
#define PL P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8
|
||||
#define CL p1, p2, p3, p4, p5, p6, p7, p8
|
||||
|
||||
#include "libfunctor_impl.h"
|
||||
|
||||
//epilogue
|
||||
|
||||
#undef TN
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifdef LIBFUNCTOR_H
|
||||
|
||||
template<TL>
|
||||
class functor<R (PL)> {
|
||||
private:
|
||||
struct base1 { virtual void func1(PL) {} };
|
||||
struct base2 { virtual void func2(PL) {} };
|
||||
struct derived : base1, virtual base2 {};
|
||||
|
||||
struct data_t {
|
||||
R (*fn_call)(const data_t& cat(PL));
|
||||
union {
|
||||
R (*fn_global)(PL);
|
||||
struct {
|
||||
R (derived::*fn_member)(PL);
|
||||
void *object;
|
||||
};
|
||||
};
|
||||
} data;
|
||||
|
||||
static R fn_call_global(const data_t &d cat(PL)) {
|
||||
return d.fn_global(CL);
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
static R fn_call_member(const data_t &d cat(PL)) {
|
||||
return (((C*)d.object)->*((R (C::*&)(PL))d.fn_member))(CL);
|
||||
}
|
||||
|
||||
public:
|
||||
R operator()(PL) const { return data.fn_call(data cat(CL)); }
|
||||
operator bool() const { return data.fn_call; }
|
||||
|
||||
functor() { data.fn_call = 0; }
|
||||
|
||||
functor(R (*fn)(PL)) {
|
||||
data.fn_call = &fn_call_global;
|
||||
data.fn_global = fn;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
functor(R (C::*fn)(PL), C *obj) {
|
||||
data.fn_call = &fn_call_member<C>;
|
||||
(R (C::*&)(PL))data.fn_member = fn;
|
||||
assert(sizeof data.fn_member >= sizeof fn);
|
||||
data.object = obj;
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
functor(R (C::*fn)(PL) const, C *obj) {
|
||||
data.fn_call = &fn_call_member<C>;
|
||||
(R (C::*&)(PL))data.fn_member = (R (C::*&)(PL))fn;
|
||||
assert(sizeof data.fn_member >= sizeof fn);
|
||||
data.object = obj;
|
||||
}
|
||||
|
||||
functor &operator=(const functor &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
|
||||
functor(const functor &source) { memcpy(&data, &source.data, sizeof(data_t)); }
|
||||
};
|
||||
|
||||
template<TL>
|
||||
functor<R (PL)> bind(R (*fn)(PL)) {
|
||||
return functor<R (PL)>(fn);
|
||||
}
|
||||
|
||||
template<typename C, TL>
|
||||
functor<R (PL)> bind(R (C::*fn)(PL), C *obj) {
|
||||
return functor<R (PL)>(fn, obj);
|
||||
}
|
||||
|
||||
template<typename C, TL>
|
||||
functor<R (PL)> bind(R (C::*fn)(PL) const, C *obj) {
|
||||
return functor<R (PL)>(fn, obj);
|
||||
}
|
||||
|
||||
#undef cat
|
||||
#undef TL
|
||||
#undef PL
|
||||
#undef CL
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,5 @@
|
||||
#define _WIN32_IE 0x0600
|
||||
|
||||
#include "libui_win.h"
|
||||
#include "libui_win_window.cpp"
|
||||
#include "libui_win_control.cpp"
|
||||
|
||||
+6
-2
@@ -148,8 +148,12 @@ struct {
|
||||
void cgram_write(uint16 addr, uint8 value);
|
||||
|
||||
uint16 get_vram_address();
|
||||
uint8 vram_mmio_read (uint16 addr);
|
||||
void vram_mmio_write(uint16 addr, uint8 data);
|
||||
uint8 vram_mmio_read (uint16 addr);
|
||||
void vram_mmio_write (uint16 addr, uint8 data);
|
||||
uint8 oam_mmio_read (uint16 addr);
|
||||
void oam_mmio_write (uint16 addr, uint8 data);
|
||||
uint8 cgram_mmio_read (uint16 addr);
|
||||
void cgram_mmio_write(uint16 addr, uint8 data);
|
||||
|
||||
void mmio_w2100(uint8 value); //INIDISP
|
||||
void mmio_w2101(uint8 value); //OBSEL
|
||||
|
||||
+92
-16
@@ -16,6 +16,11 @@ uint16 addr;
|
||||
return (addr << 1);
|
||||
}
|
||||
|
||||
//NOTE: all VRAM writes during active display are invalid. Unlike OAM and CGRAM, they will
|
||||
//not be written anywhere at all. The below address ranges for where writes are invalid have
|
||||
//been validated on hardware, as has the edge case where the S-CPU MDR can be written if the
|
||||
//write occurs during the very last clock cycle of vblank.
|
||||
|
||||
uint8 bPPU::vram_mmio_read(uint16 addr) {
|
||||
if(regs.display_disabled == true) {
|
||||
return vram_read(addr);
|
||||
@@ -46,20 +51,17 @@ uint16 ls = (r_cpu->region_scanlines() >> 1) - 1;
|
||||
|
||||
void bPPU::vram_mmio_write(uint16 addr, uint8 data) {
|
||||
if(regs.display_disabled == true) {
|
||||
vram_write(addr, data);
|
||||
return;
|
||||
return vram_write(addr, data);
|
||||
}
|
||||
|
||||
uint16 v = r_cpu->vcounter();
|
||||
uint16 hc = r_cpu->hclock();
|
||||
if(v == 0) {
|
||||
if(hc <= 4) {
|
||||
vram_write(addr, data);
|
||||
return;
|
||||
return vram_write(addr, data);
|
||||
}
|
||||
if(hc == 6) {
|
||||
vram_write(addr, r_cpu->regs.mdr);
|
||||
return;
|
||||
return vram_write(addr, r_cpu->regs.mdr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -72,13 +74,87 @@ uint16 hc = r_cpu->hclock();
|
||||
if(hc <= 4) {
|
||||
return;
|
||||
}
|
||||
vram_write(addr, data);
|
||||
return;
|
||||
return vram_write(addr, data);
|
||||
}
|
||||
|
||||
vram_write(addr, data);
|
||||
}
|
||||
|
||||
//NOTE: OAM accesses during active display are rerouted to 0x0218 ... this can be considered
|
||||
//a hack. The actual address varies during rendering, as the S-PPU reads in data itself for
|
||||
//processing. Unfortunately, we have yet to determine how this works. The algorithm cannot be
|
||||
//reverse engineered using a scanline renderer such as this, and at this time, there does not
|
||||
//exist a more accurate SNES PPU emulator to work from. The only known game to actually access
|
||||
//OAM during active display is Uniracers. It expects accesses to map to offset 0x0218.
|
||||
//It was decided by public consensus to map writes to this address to match Uniracers, primarily
|
||||
//because it is the only game observed to do this, but also because mapping to this address does
|
||||
//not contradict any of our findings, because we have no findings whatsoever on this behavior.
|
||||
//Think of this what you will, I openly admit that this is a hack. But it is more accurate than
|
||||
//writing to the 'expected' address set by $2102,$2103, and will catch problems in software that
|
||||
//accidentally accesses OAM during active display by virtue of not returning the expected data.
|
||||
//You may disable this behavior by setting config::ppu.hack.oam_address_invalidation to false,
|
||||
//or by changing the address from 0x0218 to 0x0000 below if it bothers you that greatly.
|
||||
|
||||
uint8 bPPU::oam_mmio_read(uint16 addr) {
|
||||
if(config::ppu.hack.oam_address_invalidation == false || regs.display_disabled == true) {
|
||||
return oam_read(addr);
|
||||
}
|
||||
|
||||
uint16 v = r_cpu->vcounter();
|
||||
if(v < (!r_cpu->overscan() ? 225 : 240)) {
|
||||
return oam_read(0x0218);
|
||||
}
|
||||
|
||||
return oam_read(addr);
|
||||
}
|
||||
|
||||
void bPPU::oam_mmio_write(uint16 addr, uint8 data) {
|
||||
if(config::ppu.hack.oam_address_invalidation == false || regs.display_disabled == true) {
|
||||
return oam_write(addr, data);
|
||||
}
|
||||
|
||||
uint16 v = r_cpu->vcounter();
|
||||
if(v < (!r_cpu->overscan() ? 225 : 240)) {
|
||||
return oam_write(0x0218, data);
|
||||
}
|
||||
|
||||
oam_write(addr, data);
|
||||
}
|
||||
|
||||
//NOTE: CGRAM writes during hblank are valid. During active display, the actual address the
|
||||
//data is written to varies, as the S-PPU itself changes the address. Like OAM, we do not know
|
||||
//the exact algorithm used, but we have zero known examples of any commercial software that
|
||||
//attempts to do this. Therefore, the addresses are mapped to 0x0000. There is nothing special
|
||||
//about this address, it is simply more accurate to invalidate the 'expected' address than not.
|
||||
|
||||
uint8 bPPU::cgram_mmio_read(uint16 addr) {
|
||||
if(config::ppu.hack.cgram_address_invalidation == false || regs.display_disabled == true) {
|
||||
return cgram_read(addr);
|
||||
}
|
||||
|
||||
uint16 v = r_cpu->vcounter();
|
||||
uint16 hc = r_cpu->hclock();
|
||||
if(v < (!r_cpu->overscan() ? 225 : 240) && hc > 0 && hc < 1096) {
|
||||
return cgram_read(0x0000);
|
||||
}
|
||||
|
||||
return cgram_read(addr);
|
||||
}
|
||||
|
||||
void bPPU::cgram_mmio_write(uint16 addr, uint8 data) {
|
||||
if(config::ppu.hack.cgram_address_invalidation == false || regs.display_disabled == true) {
|
||||
return cgram_write(addr, data);
|
||||
}
|
||||
|
||||
uint16 v = r_cpu->vcounter();
|
||||
uint16 hc = r_cpu->hclock();
|
||||
if(v < (!r_cpu->overscan() ? 225 : 240) && hc > 0 && hc < 1096) {
|
||||
return cgram_write(0x0000, data);
|
||||
}
|
||||
|
||||
cgram_write(addr, data);
|
||||
}
|
||||
|
||||
//INIDISP
|
||||
void bPPU::mmio_w2100(uint8 value) {
|
||||
if(regs.display_disabled == true && r_cpu->vcounter() == (!r_cpu->overscan() ? 225 : 240)) {
|
||||
@@ -117,12 +193,12 @@ void bPPU::mmio_w2103(uint8 data) {
|
||||
//OAMDATA
|
||||
void bPPU::mmio_w2104(uint8 data) {
|
||||
if(regs.oam_addr & 0x0200) {
|
||||
oam_write(regs.oam_addr, data);
|
||||
oam_mmio_write(regs.oam_addr, data);
|
||||
} else if((regs.oam_addr & 1) == 0) {
|
||||
regs.oam_latchdata = data;
|
||||
} else {
|
||||
oam_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam_write((regs.oam_addr & ~1) + 1, data);
|
||||
oam_mmio_write((regs.oam_addr & ~1) + 0, regs.oam_latchdata);
|
||||
oam_mmio_write((regs.oam_addr & ~1) + 1, data);
|
||||
}
|
||||
|
||||
regs.oam_addr++;
|
||||
@@ -353,8 +429,8 @@ void bPPU::mmio_w2122(uint8 value) {
|
||||
if(!(regs.cgram_addr & 1)) {
|
||||
regs.cgram_latchdata = value;
|
||||
} else {
|
||||
cgram_write((regs.cgram_addr & 0x01fe), regs.cgram_latchdata);
|
||||
cgram_write((regs.cgram_addr & 0x01fe) + 1, value & 0x7f);
|
||||
cgram_mmio_write((regs.cgram_addr & 0x01fe), regs.cgram_latchdata);
|
||||
cgram_mmio_write((regs.cgram_addr & 0x01fe) + 1, value & 0x7f);
|
||||
}
|
||||
regs.cgram_addr++;
|
||||
regs.cgram_addr &= 0x01ff;
|
||||
@@ -540,7 +616,7 @@ uint8 bPPU::mmio_r2137() {
|
||||
|
||||
//OAMDATAREAD
|
||||
uint8 bPPU::mmio_r2138() {
|
||||
regs.ppu1_mdr = oam_read(regs.oam_addr);
|
||||
regs.ppu1_mdr = oam_mmio_read(regs.oam_addr);
|
||||
|
||||
regs.oam_addr++;
|
||||
regs.oam_addr &= 0x03ff;
|
||||
@@ -581,10 +657,10 @@ uint16 addr = get_vram_address() + 1;
|
||||
//update bit 7 of the PPU2 MDR.
|
||||
uint8 bPPU::mmio_r213b() {
|
||||
if(!(regs.cgram_addr & 1)) {
|
||||
regs.ppu2_mdr = cgram_read(regs.cgram_addr) & 0xff;
|
||||
regs.ppu2_mdr = cgram_mmio_read(regs.cgram_addr) & 0xff;
|
||||
} else {
|
||||
regs.ppu2_mdr &= 0x80;
|
||||
regs.ppu2_mdr |= cgram_read(regs.cgram_addr) & 0x7f;
|
||||
regs.ppu2_mdr |= cgram_mmio_read(regs.cgram_addr) & 0x7f;
|
||||
}
|
||||
regs.cgram_addr++;
|
||||
regs.cgram_addr &= 0x01ff;
|
||||
|
||||
@@ -27,7 +27,9 @@ uint16 bPPU::bg_get_tile(uint8 bg, uint16 x, uint16 y) {
|
||||
uint16 pos = ((y & 0x1f) << 5) + (x & 0x1f);
|
||||
if(y & 0x20)pos += bg_info[bg].scy;
|
||||
if(x & 0x20)pos += bg_info[bg].scx;
|
||||
return read16(vram, regs.bg_scaddr[bg] + (pos << 1));
|
||||
|
||||
uint16 addr = regs.bg_scaddr[bg] + (pos << 1);
|
||||
return (vram_read(addr + 0) << 0) | (vram_read(addr + 1) << 8);
|
||||
}
|
||||
|
||||
#define setpixel_main(x) \
|
||||
|
||||
@@ -61,14 +61,14 @@ tclr_addr_a(0x4e, &~) {
|
||||
5:op_writeaddr(dp, rd $1 regs.a);
|
||||
}
|
||||
|
||||
incw_dp(0x3a, rd++),
|
||||
decw_dp(0x1a, rd--) {
|
||||
incw_dp(0x3a, ++),
|
||||
decw_dp(0x1a, --) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
$1;
|
||||
rd$1;
|
||||
3:op_writedp(dp++, rd);
|
||||
4:rd += op_readdp(dp) << 8;
|
||||
5:op_write(dp, rd >> 8);
|
||||
5:op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
}
|
||||
@@ -212,7 +212,7 @@ void sSMP::op_incw_dp() {
|
||||
rd++;
|
||||
op_writedp(dp++, rd);
|
||||
rd += op_readdp(dp) << 8;
|
||||
op_write(dp, rd >> 8);
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
}
|
||||
@@ -223,7 +223,7 @@ void sSMP::op_decw_dp() {
|
||||
rd--;
|
||||
op_writedp(dp++, rd);
|
||||
rd += op_readdp(dp) << 8;
|
||||
op_write(dp, rd >> 8);
|
||||
op_writedp(dp, rd >> 8);
|
||||
regs.p.n = !!(rd & 0x8000);
|
||||
regs.p.z = (rd == 0);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ class SNESInterface { public:
|
||||
|
||||
void audio_sample(uint16 l_sample, uint16 r_sample);
|
||||
|
||||
functor<bool ()> input_ready;
|
||||
void input_poll();
|
||||
bool input_poll(uint deviceid, uint button);
|
||||
|
||||
|
||||
@@ -2,10 +2,10 @@ Scheduler scheduler;
|
||||
|
||||
//
|
||||
|
||||
void cocall threadentry_cpu(void*) { r_cpu->enter(); }
|
||||
void cocall threadentry_smp(void*) { r_smp->enter(); }
|
||||
void cocall threadentry_ppu(void*) {} //currently unused
|
||||
void cocall threadentry_dsp(void*) { r_dsp->enter(); }
|
||||
void threadentry_cpu() { r_cpu->enter(); }
|
||||
void threadentry_smp() { r_smp->enter(); }
|
||||
void threadentry_ppu() { } //currently unused
|
||||
void threadentry_dsp() { r_dsp->enter(); }
|
||||
|
||||
//
|
||||
|
||||
@@ -41,10 +41,10 @@ void Scheduler::init() {
|
||||
if(thread_dsp)co_delete(thread_dsp);
|
||||
|
||||
thread_snes = co_active();
|
||||
thread_cpu = co_create(sizeof(void*) * 64 * 1024, threadentry_cpu, 0);
|
||||
thread_smp = co_create(sizeof(void*) * 64 * 1024, threadentry_smp, 0);
|
||||
thread_ppu = co_create(sizeof(void*) * 64 * 1024, threadentry_ppu, 0);
|
||||
thread_dsp = co_create(sizeof(void*) * 64 * 1024, threadentry_dsp, 0);
|
||||
thread_cpu = co_create(sizeof(void*) * 64 * 1024, threadentry_cpu);
|
||||
thread_smp = co_create(sizeof(void*) * 64 * 1024, threadentry_smp);
|
||||
thread_ppu = co_create(sizeof(void*) * 64 * 1024, threadentry_ppu);
|
||||
thread_dsp = co_create(sizeof(void*) * 64 * 1024, threadentry_dsp);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Tracer tracer;
|
||||
|
||||
void tprintf(char *s, ...) {
|
||||
void tprintf(const char *s, ...) {
|
||||
if(tracer.enabled() == false) { return; }
|
||||
|
||||
char str[4096];
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
void tprintf(char *s, ...);
|
||||
void tprintf(const char *s, ...);
|
||||
|
||||
class Tracer {
|
||||
private:
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
Tracer();
|
||||
~Tracer();
|
||||
|
||||
friend void tprintf(char *s, ...);
|
||||
friend void tprintf(const char *s, ...);
|
||||
};
|
||||
|
||||
extern Tracer tracer;
|
||||
+1
-97
@@ -1,100 +1,4 @@
|
||||
/*
|
||||
* interpolation routines are located in: /src/lib/libinterp.h
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
inline uint Audio::bind_range(uint min, uint max, uint index) {
|
||||
return index < min ? min : index > max ? max : index;
|
||||
}
|
||||
|
||||
void Audio::resample_point(
|
||||
uint32 *output, uint32 *input, uint output_samples, uint input_samples
|
||||
) {
|
||||
double scalar = double(input_samples--) / double(output_samples--); //convert lengths to upper bounds
|
||||
double sindex = 0.0;
|
||||
for(uint x = 0; x <= output_samples; x++) {
|
||||
uint32 y0 = input[bind_range(0, input_samples, uint32(sindex) + 0)];
|
||||
uint32 y1 = input[bind_range(0, input_samples, uint32(sindex) + 1)];
|
||||
double mu = sindex - uint(sindex); //calculate fractional portion of step
|
||||
uint16 yl = interpolate_point(mu, int16(y0 >> 0), int16(y1 >> 0));
|
||||
uint16 yr = interpolate_point(mu, int16(y0 >> 16), int16(y1 >> 16));
|
||||
output[x] = (yl << 0) + (yr << 16);
|
||||
sindex += scalar;
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::resample_linear(
|
||||
uint32 *output, uint32 *input, uint output_samples, uint input_samples
|
||||
) {
|
||||
double scalar = double(input_samples--) / double(output_samples--); //convert lengths to upper bounds
|
||||
double sindex = 0.0;
|
||||
for(uint x = 0; x <= output_samples; x++) {
|
||||
uint32 y0 = input[bind_range(0, input_samples, uint32(sindex) + 0)];
|
||||
uint32 y1 = input[bind_range(0, input_samples, uint32(sindex) + 1)];
|
||||
double mu = sindex - uint(sindex); //calculate fractional portion of step
|
||||
uint16 yl = interpolate_linear(mu, int16(y0 >> 0), int16(y1 >> 0));
|
||||
uint16 yr = interpolate_linear(mu, int16(y0 >> 16), int16(y1 >> 16));
|
||||
output[x] = (yl << 0) + (yr << 16);
|
||||
sindex += scalar;
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::resample_cosine(
|
||||
uint32 *output, uint32 *input, uint output_samples, uint input_samples
|
||||
) {
|
||||
double scalar = double(input_samples--) / double(output_samples--); //convert lengths to upper bounds
|
||||
double sindex = 0.0;
|
||||
for(uint x = 0; x <= output_samples; x++) {
|
||||
uint32 y0 = input[bind_range(0, input_samples, uint32(sindex) + 0)];
|
||||
uint32 y1 = input[bind_range(0, input_samples, uint32(sindex) + 1)];
|
||||
double mu = sindex - uint(sindex); //calculate fractional portion of step
|
||||
uint16 yl = interpolate_cosine(mu, int16(y0 >> 0), int16(y1 >> 0));
|
||||
uint16 yr = interpolate_cosine(mu, int16(y0 >> 16), int16(y1 >> 16));
|
||||
output[x] = (yl << 0) + (yr << 16);
|
||||
sindex += scalar;
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::resample_cubic(
|
||||
uint32 *output, uint32 *input, uint output_samples, uint input_samples
|
||||
) {
|
||||
double scalar = double(input_samples--) / double(output_samples--); //convert lengths to upper bounds
|
||||
double sindex = 0.0;
|
||||
for(uint x = 0; x <= output_samples; x++) {
|
||||
uint32 y0 = input[bind_range(0, input_samples, uint32(sindex) - 1)];
|
||||
uint32 y1 = input[bind_range(0, input_samples, uint32(sindex) + 0)];
|
||||
uint32 y2 = input[bind_range(0, input_samples, uint32(sindex) + 1)];
|
||||
uint32 y3 = input[bind_range(0, input_samples, uint32(sindex) + 2)];
|
||||
double mu = sindex - uint(sindex); //calculate fractional portion of step
|
||||
uint16 yl = sclamp<16>( interpolate_cubic(mu, int16(y0 >> 0), int16(y1 >> 0), int16(y2 >> 0), int16(y3 >> 0)) );
|
||||
uint16 yr = sclamp<16>( interpolate_cubic(mu, int16(y0 >> 16), int16(y1 >> 16), int16(y2 >> 16), int16(y3 >> 16)) );
|
||||
output[x] = (yl << 0) + (yr << 16);
|
||||
sindex += scalar;
|
||||
}
|
||||
}
|
||||
|
||||
void Audio::resample_hermite(
|
||||
uint32 *output, uint32 *input, uint output_samples, uint input_samples
|
||||
) {
|
||||
double scalar = double(input_samples--) / double(output_samples--); //convert lengths to upper bounds
|
||||
double sindex = 0.0;
|
||||
for(uint x = 0; x <= output_samples; x++) {
|
||||
uint32 y0 = input[bind_range(0, input_samples, uint32(sindex) - 1)];
|
||||
uint32 y1 = input[bind_range(0, input_samples, uint32(sindex) + 0)];
|
||||
uint32 y2 = input[bind_range(0, input_samples, uint32(sindex) + 1)];
|
||||
uint32 y3 = input[bind_range(0, input_samples, uint32(sindex) + 2)];
|
||||
double mu = sindex - uint(sindex); //calculate fractional portion of step
|
||||
uint16 yl = sclamp<16>( interpolate_hermite(mu, 0.0, 0.0, int16(y0 >> 0), int16(y1 >> 0), int16(y2 >> 0), int16(y3 >> 0)) );
|
||||
uint16 yr = sclamp<16>( interpolate_hermite(mu, 0.0, 0.0, int16(y0 >> 16), int16(y1 >> 16), int16(y2 >> 16), int16(y3 >> 16)) );
|
||||
output[x] = (yl << 0) + (yr << 16);
|
||||
sindex += scalar;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
//
|
||||
#include "audio.h"
|
||||
|
||||
void Audio::update_frequency() {
|
||||
uint freq = config::audio.frequency;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
class Audio {
|
||||
public:
|
||||
uint frequency, latency;
|
||||
@@ -7,14 +10,7 @@ uint frequency, latency;
|
||||
virtual void init() {}
|
||||
virtual void term() {}
|
||||
|
||||
/*
|
||||
uint bind_range(uint min, uint max, uint index);
|
||||
void resample_point (uint32 *output, uint32 *input, uint output_samples, uint input_samples);
|
||||
void resample_linear (uint32 *output, uint32 *input, uint output_samples, uint input_samples);
|
||||
void resample_cosine (uint32 *output, uint32 *input, uint output_samples, uint input_samples);
|
||||
void resample_cubic (uint32 *output, uint32 *input, uint output_samples, uint input_samples);
|
||||
void resample_hermite(uint32 *output, uint32 *input, uint output_samples, uint input_samples);
|
||||
*/
|
||||
|
||||
Audio();
|
||||
} *uiAudio;
|
||||
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@ void AudioDS::sample(uint16 l_sample, uint16 r_sample) {
|
||||
data.buffer[data.buffer_pos++] = (l_sample << 0) + (r_sample << 16);
|
||||
if(data.buffer_pos < latency)return;
|
||||
|
||||
uint32 ring_pos, pos, size;
|
||||
DWORD ring_pos, pos, size;
|
||||
for(;;) {
|
||||
dsb_b->GetCurrentPosition(&pos, 0);
|
||||
ring_pos = pos / data.ring_size;
|
||||
@@ -30,7 +30,7 @@ void *output;
|
||||
data.buffer[data.buffer_pos++] = (l_sample << 0) + (r_sample << 16);
|
||||
//if(data.buffer_pos & 15)return;
|
||||
|
||||
uint32 ring_pos, pos, size;
|
||||
DWORD ring_pos, pos, size;
|
||||
dsb_b->GetCurrentPosition(&pos, 0);
|
||||
ring_pos = pos / data.ring_size;
|
||||
if(ring_pos == data.ring_pos)return;
|
||||
@@ -66,7 +66,7 @@ void AudioDS::clear_audio() {
|
||||
dsb_b->Stop();
|
||||
dsb_b->SetCurrentPosition(0);
|
||||
|
||||
uint32 size;
|
||||
DWORD size;
|
||||
void *output;
|
||||
dsb_b->Lock(0, data.ring_size * 3, &output, &size, 0, 0, 0);
|
||||
memset(output, 0, size);
|
||||
|
||||
+11
-1
@@ -29,6 +29,7 @@ struct Video {
|
||||
static IntegerSetting synchronize;
|
||||
static IntegerSetting fullscreen;
|
||||
static IntegerSetting multiplier, aspect_correction, region;
|
||||
static IntegerSetting aspect_ntsc_x, aspect_ntsc_y, aspect_pal_x, aspect_pal_y;
|
||||
static IntegerSetting hardware_filter, software_filter;
|
||||
static IntegerSetting frameskip;
|
||||
static IntegerSetting use_vram;
|
||||
@@ -40,10 +41,19 @@ IntegerSetting Video::multiplier(&config_file, "video.multiplier", "Video output
|
||||
"2 = 2x (~512x448)\n"
|
||||
"etc.",
|
||||
IntegerSetting::Decimal, 2);
|
||||
IntegerSetting Video::aspect_correction(&config_file, "video.aspect_correction", "Correct video aspect ratio", IntegerSetting::Boolean, true);
|
||||
IntegerSetting Video::aspect_correction(&config_file, "video.aspect_correction",
|
||||
"Correct video aspect ratio\n"
|
||||
"Formula: width = width * video.aspect_<region>_x / video.aspect_<region>_y",
|
||||
IntegerSetting::Boolean, true);
|
||||
IntegerSetting Video::region(&config_file, "video.region", "Video output region\n"
|
||||
"0 = NTSC, 1 = PAL",
|
||||
IntegerSetting::Decimal, 0);
|
||||
|
||||
IntegerSetting Video::aspect_ntsc_x(&config_file, "video.aspect_ntsc_x", "", IntegerSetting::Decimal, 54);
|
||||
IntegerSetting Video::aspect_ntsc_y(&config_file, "video.aspect_ntsc_y", "", IntegerSetting::Decimal, 47);
|
||||
IntegerSetting Video::aspect_pal_x (&config_file, "video.aspect_pal_x", "", IntegerSetting::Decimal, 32);
|
||||
IntegerSetting Video::aspect_pal_y (&config_file, "video.aspect_pal_y", "", IntegerSetting::Decimal, 23);
|
||||
|
||||
IntegerSetting Video::hardware_filter(&config_file, "video.hardware_filter", "Video hardware filter\n"
|
||||
"0 = Point\n"
|
||||
"1 = Linear\n",
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#include "dinput.h"
|
||||
|
||||
void InputDI::clear_input() {
|
||||
memset(keystate, 0, sizeof keystate);
|
||||
}
|
||||
|
||||
void InputDI::poll() {
|
||||
clear_input();
|
||||
|
||||
HRESULT hr;
|
||||
DIJOYSTATE2 js;
|
||||
memset(keystate, 0, sizeof(keystate));
|
||||
|
||||
if(di_key) {
|
||||
hr = di_key->GetDeviceState(256, keystate);
|
||||
if(FAILED(hr)) {
|
||||
|
||||
@@ -15,6 +15,7 @@ LPDIRECTINPUT8 di;
|
||||
LPDIRECTINPUTDEVICE8 di_key, di_joy[DIRECTINPUT_JOYMAX];
|
||||
uint32 di_joy_count;
|
||||
|
||||
void clear_input();
|
||||
void poll();
|
||||
void init();
|
||||
void term();
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "input.h"
|
||||
@@ -5,9 +5,6 @@ class Input { public:
|
||||
virtual bool key_down(uint16 key) { return false; }
|
||||
virtual bool key_up (uint16 key) { return !key_down(key); }
|
||||
|
||||
virtual void signal_key_down(uint16 key) {}
|
||||
virtual void signal_key_up (uint16 key) {}
|
||||
|
||||
virtual void clear_input() {}
|
||||
virtual void poll() {}
|
||||
virtual void init() {}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "inputui.h"
|
||||
@@ -1,28 +0,0 @@
|
||||
/*****
|
||||
* InputUI
|
||||
*
|
||||
* Input wrapper to capture UI key presses. Useful for when OS does not
|
||||
* support direct input polling methods (eg Xorg, etc)
|
||||
*****/
|
||||
|
||||
#ifndef INPUTUI_H
|
||||
#define INPUTUI_H
|
||||
|
||||
class InputUI : public Input {
|
||||
private:
|
||||
bool keystate[65536];
|
||||
|
||||
public:
|
||||
void init() {
|
||||
Input::init();
|
||||
memset(keystate, 0, sizeof(keystate));
|
||||
}
|
||||
|
||||
bool key_down(uint16 key) { return keystate[key]; }
|
||||
void signal_key_down(uint16 key) { keystate[key] = true; }
|
||||
void signal_key_up (uint16 key) { keystate[key] = false; }
|
||||
|
||||
void clear_input() { memset(keystate, 0, sizeof(keystate)); }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
#include "xinput.h"
|
||||
|
||||
bool InputX::key_down(uint16 key) {
|
||||
#define map(i) (keymap[i >> 3] & (1 << (i & 7)))
|
||||
switch(key) {
|
||||
case keymap::esc: return map(0x09);
|
||||
|
||||
case keymap::f1: return map(0x43);
|
||||
case keymap::f2: return map(0x44);
|
||||
case keymap::f3: return map(0x45);
|
||||
case keymap::f4: return map(0x46);
|
||||
case keymap::f5: return map(0x47);
|
||||
case keymap::f6: return map(0x48);
|
||||
case keymap::f7: return map(0x49);
|
||||
case keymap::f8: return map(0x4a);
|
||||
case keymap::f9: return map(0x4b);
|
||||
case keymap::f10: return map(0x4c);
|
||||
case keymap::f11: return map(0x5f);
|
||||
case keymap::f12: return map(0x60);
|
||||
|
||||
case keymap::print_screen: return map(0x6f);
|
||||
case keymap::scroll_lock: return map(0x4e);
|
||||
case keymap::pause: return map(0x6e);
|
||||
|
||||
case keymap::grave: return map(0x31);
|
||||
|
||||
case keymap::num_1: return map(0x0a);
|
||||
case keymap::num_2: return map(0x0b);
|
||||
case keymap::num_3: return map(0x0c);
|
||||
case keymap::num_4: return map(0x0d);
|
||||
case keymap::num_5: return map(0x0e);
|
||||
case keymap::num_6: return map(0x0f);
|
||||
case keymap::num_7: return map(0x10);
|
||||
case keymap::num_8: return map(0x11);
|
||||
case keymap::num_9: return map(0x12);
|
||||
case keymap::num_0: return map(0x13);
|
||||
|
||||
case keymap::minus: return map(0x14);
|
||||
case keymap::equal: return map(0x15);
|
||||
case keymap::backspace: return map(0x16);
|
||||
|
||||
case keymap::ins: return map(0x6a);
|
||||
case keymap::del: return map(0x6b);
|
||||
case keymap::home: return map(0x61);
|
||||
case keymap::end: return map(0x67);
|
||||
case keymap::page_up: return map(0x63);
|
||||
case keymap::page_down: return map(0x69);
|
||||
|
||||
case keymap::a: return map(0x26);
|
||||
case keymap::b: return map(0x38);
|
||||
case keymap::c: return map(0x36);
|
||||
case keymap::d: return map(0x28);
|
||||
case keymap::e: return map(0x1a);
|
||||
case keymap::f: return map(0x29);
|
||||
case keymap::g: return map(0x2a);
|
||||
case keymap::h: return map(0x2b);
|
||||
case keymap::i: return map(0x1f);
|
||||
case keymap::j: return map(0x2c);
|
||||
case keymap::k: return map(0x2d);
|
||||
case keymap::l: return map(0x2e);
|
||||
case keymap::m: return map(0x3a);
|
||||
case keymap::n: return map(0x39);
|
||||
case keymap::o: return map(0x20);
|
||||
case keymap::p: return map(0x21);
|
||||
case keymap::q: return map(0x18);
|
||||
case keymap::r: return map(0x1b);
|
||||
case keymap::s: return map(0x27);
|
||||
case keymap::t: return map(0x1c);
|
||||
case keymap::u: return map(0x1e);
|
||||
case keymap::v: return map(0x37);
|
||||
case keymap::w: return map(0x19);
|
||||
case keymap::x: return map(0x35);
|
||||
case keymap::y: return map(0x1d);
|
||||
case keymap::z: return map(0x34);
|
||||
|
||||
case keymap::lbracket: return map(0x22);
|
||||
case keymap::rbracket: return map(0x23);
|
||||
case keymap::backslash: return map(0x33);
|
||||
case keymap::semicolon: return map(0x2f);
|
||||
case keymap::apostrophe: return map(0x30);
|
||||
case keymap::comma: return map(0x3b);
|
||||
case keymap::period: return map(0x3c);
|
||||
case keymap::slash: return map(0x3d);
|
||||
|
||||
case keymap::kp_1: return map(0x57);
|
||||
case keymap::kp_2: return map(0x58);
|
||||
case keymap::kp_3: return map(0x59);
|
||||
case keymap::kp_4: return map(0x53);
|
||||
case keymap::kp_5: return map(0x54);
|
||||
case keymap::kp_6: return map(0x55);
|
||||
case keymap::kp_7: return map(0x4f);
|
||||
case keymap::kp_8: return map(0x50);
|
||||
case keymap::kp_9: return map(0x51);
|
||||
|
||||
case keymap::kp_plus: return map(0x56);
|
||||
case keymap::kp_minus: return map(0x52);
|
||||
case keymap::kp_mul: return map(0x3f);
|
||||
case keymap::kp_div: return map(0x70);
|
||||
case keymap::kp_enter: return map(0x6c);
|
||||
|
||||
case keymap::num_lock: return map(0x4d);
|
||||
case keymap::caps_lock: return map(0x42);
|
||||
|
||||
case keymap::up: return map(0x62);
|
||||
case keymap::down: return map(0x68);
|
||||
case keymap::left: return map(0x64);
|
||||
case keymap::right: return map(0x66);
|
||||
|
||||
case keymap::tab: return map(0x17);
|
||||
case keymap::enter: return map(0x24);
|
||||
case keymap::space: return map(0x41);
|
||||
|
||||
case keymap::lctrl: return map(0x25);
|
||||
case keymap::rctrl: return map(0x6d);
|
||||
case keymap::lalt: return map(0x40);
|
||||
case keymap::ralt: return map(0x71);
|
||||
case keymap::lshift: return map(0x32);
|
||||
case keymap::rshift: return map(0x3e);
|
||||
case keymap::lsuper: return map(0x73);
|
||||
case keymap::rsuper: return map(0x74);
|
||||
case keymap::menu: return map(0x75);
|
||||
}
|
||||
#undef map
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void InputX::clear_input() {
|
||||
memset(keymap, 0, sizeof keymap);
|
||||
}
|
||||
|
||||
void InputX::poll() {
|
||||
XQueryKeymap(display, keymap);
|
||||
}
|
||||
|
||||
void InputX::init() {
|
||||
Input::init();
|
||||
display = XOpenDisplay(0);
|
||||
}
|
||||
|
||||
void InputX::term() {
|
||||
Input::term();
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef XINPUT_H
|
||||
#define XINPUT_H
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xv.h>
|
||||
#include <X11/extensions/Xvlib.h>
|
||||
#include <X11/extensions/XShm.h>
|
||||
|
||||
class InputX : public Input { public:
|
||||
bool key_down(uint16 key);
|
||||
|
||||
void clear_input();
|
||||
void poll();
|
||||
void init();
|
||||
void term();
|
||||
|
||||
private:
|
||||
Display *display;
|
||||
char keymap[32];
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -40,7 +40,11 @@ void SNESInterface::audio_sample(uint16 l_sample, uint16 r_sample) {
|
||||
//input
|
||||
|
||||
void SNESInterface::input_poll() {
|
||||
uiInput->poll();
|
||||
if(input_ready && input_ready() == false) {
|
||||
uiInput->clear_input();
|
||||
} else {
|
||||
uiInput->poll();
|
||||
}
|
||||
input_manager.poll();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,10 +16,10 @@ uint multiplier = minmax<1, 5>(uint(config::video.multiplier));
|
||||
width *= multiplier;
|
||||
height *= multiplier;
|
||||
if(config::video.aspect_correction == true) {
|
||||
if(config::video.region == 0) {
|
||||
width = uint( double(width) * 8.0 / 7.0 ); //NTSC
|
||||
} else {
|
||||
width = uint( double(width) * 48.0 / 35.0 ); //PAL
|
||||
if(config::video.region == 0) { //NTSC
|
||||
width = uint( double(width) * double(config::video.aspect_ntsc_x) / double(config::video.aspect_ntsc_y) );
|
||||
} else { //PAL
|
||||
width = uint( double(width) * double(config::video.aspect_pal_x) / double(config::video.aspect_pal_y) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ char fn[PATH_MAX];
|
||||
cartridge.load(fn);
|
||||
cartridge.load_end();
|
||||
snes.power();
|
||||
window_cheat_editor.refresh();
|
||||
}
|
||||
|
||||
void unload_rom() {
|
||||
@@ -112,6 +113,7 @@ void unload_rom() {
|
||||
uiAudio->clear_audio();
|
||||
}
|
||||
window_main.set_text(BSNES_TITLE);
|
||||
window_cheat_editor.refresh();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
|
||||
+8
-3
@@ -18,7 +18,7 @@ bool _term_ = false;
|
||||
#include "ui.cpp"
|
||||
#include "event.cpp"
|
||||
|
||||
void alert(char *s, ...) {
|
||||
void alert(const char *s, ...) {
|
||||
char str[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
@@ -27,7 +27,7 @@ va_list args;
|
||||
fprintf(stdout, "%s\r\n", str);
|
||||
}
|
||||
|
||||
void dprintf(char *s, ...) {
|
||||
void dprintf(const char *s, ...) {
|
||||
char str[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
@@ -36,7 +36,7 @@ va_list args;
|
||||
fprintf(stdout, "%s\r\n", str);
|
||||
}
|
||||
|
||||
void dprintf(uint source, char *s, ...) {
|
||||
void dprintf(uint source, const char *s, ...) {
|
||||
char str[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
@@ -58,6 +58,11 @@ void run() {
|
||||
snes.runtoframe();
|
||||
event::update_frame_counter();
|
||||
}
|
||||
|
||||
#if defined(PLATFORM_WIN)
|
||||
//prevent bsnes from consuming 100% CPU resources when idle
|
||||
else { Sleep(1); }
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(PLATFORM_WIN)
|
||||
|
||||
@@ -1,4 +1,62 @@
|
||||
void CheatEditorWindow::refresh() {
|
||||
list.reset();
|
||||
|
||||
for(uint i = 0; i < cheat.count(); i++) {
|
||||
bool enabled;
|
||||
uint32 addr;
|
||||
uint8 data;
|
||||
char s_code[256], s_desc[256], s_result[1024];
|
||||
cheat.get(i, enabled, addr, data, s_code, s_desc);
|
||||
sprintf(s_result, "%s|%s|%s", enabled ? "Enabled" : "Disabled", s_code, s_desc);
|
||||
list.add_item(s_result);
|
||||
}
|
||||
|
||||
list.autosize_columns();
|
||||
|
||||
//enable controls only if cartridge is loaded
|
||||
bool loaded = cartridge.loaded();
|
||||
add_code.enable(loaded);
|
||||
toggle_code.enable(loaded);
|
||||
delete_code.enable(loaded);
|
||||
}
|
||||
|
||||
bool CheatEditorWindow::message(uint id, uintptr_t param) {
|
||||
ui::Control *control = (ui::Control*)param;
|
||||
|
||||
if(id == ui::Message::Clicked && control == &add_code) {
|
||||
char s_code[256], s_desc[256];
|
||||
code.get_text(s_code, sizeof s_code);
|
||||
desc.get_text(s_desc, sizeof s_desc);
|
||||
cheat.add(false, s_code, s_desc); //param 0 = new codes disabled by default
|
||||
refresh();
|
||||
return true;
|
||||
}
|
||||
|
||||
if((id == ui::Message::Clicked && control == &toggle_code) ||
|
||||
(id == ui::Message::DoubleClicked && control == &list)) {
|
||||
int index = list.get_selection();
|
||||
if(index >= 0 && index < cheat.count()) {
|
||||
cheat.enabled(index) ? cheat.disable(index) : cheat.enable(index);
|
||||
bool enabled;
|
||||
uint32 addr;
|
||||
uint8 data;
|
||||
char s_code[256], s_desc[256], s_result[1024];
|
||||
cheat.get(index, enabled, addr, data, s_code, s_desc);
|
||||
sprintf(s_result, "%s|%s|%s", enabled ? "Enabled" : "Disabled", s_code, s_desc);
|
||||
list.set_item(index, s_result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(id == ui::Message::Clicked && control == &delete_code) {
|
||||
int index = list.get_selection();
|
||||
if(index >= 0 && index < cheat.count()) {
|
||||
cheat.remove(index);
|
||||
refresh();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7,9 +65,6 @@ void CheatEditorWindow::setup() {
|
||||
|
||||
int x = 0, y = 0;
|
||||
list.create(*this, ui::Listbox::Header | ui::Listbox::VerticalScrollAlways, x, y, 475, 285, "Status|Code|Description");
|
||||
list.add_item("Enabled|0123-4567|Infinite Energy");
|
||||
list.add_item("Disabled|89ab-cdef|Infinite Lives");
|
||||
list.autosize_columns();
|
||||
y += 290;
|
||||
|
||||
add_code.create (*this, 0, x, y, 155, 30, "Add Code");
|
||||
@@ -20,7 +75,5 @@ int x = 0, y = 0;
|
||||
code.create(*this, 0, x, y, 155, 30, "<code>");
|
||||
desc.create(*this, 0, x + 160, y, 315, 30, "<description>");
|
||||
|
||||
add_code.disable();
|
||||
toggle_code.disable();
|
||||
delete_code.disable();
|
||||
refresh();
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
class CheatEditorWindow : public ui::Window { public:
|
||||
ui::Listbox list;
|
||||
ui::Button add_code;
|
||||
ui::Button toggle_code;
|
||||
ui::Button delete_code;
|
||||
ui::Editbox code;
|
||||
ui::Editbox desc;
|
||||
bool message(uint id, uintptr_t param);
|
||||
void setup();
|
||||
} window_cheat_editor;
|
||||
class CheatEditorWindow : public ui::Window { public:
|
||||
ui::Listbox list;
|
||||
ui::Button add_code;
|
||||
ui::Button toggle_code;
|
||||
ui::Button delete_code;
|
||||
ui::Editbox code;
|
||||
ui::Editbox desc;
|
||||
bool message(uint id, uintptr_t param);
|
||||
void setup();
|
||||
|
||||
void refresh();
|
||||
} window_cheat_editor;
|
||||
@@ -99,16 +99,6 @@ void InputConfigWindow::refresh_list() {
|
||||
|
||||
bool InputConfigWindow::message(uint id, uintptr_t param) {
|
||||
ui::Control *control = (ui::Control*)param;
|
||||
if(id == ui::Message::KeyDown) {
|
||||
if(uiInput) { uiInput->signal_key_down(param); }
|
||||
return true;
|
||||
}
|
||||
|
||||
if(id == ui::Message::KeyUp) {
|
||||
if(uiInput) { uiInput->signal_key_up(param); }
|
||||
return true;
|
||||
}
|
||||
|
||||
if(id == ui::Message::Changed && control == &list) {
|
||||
int pos = list.get_selection();
|
||||
setkey.enable(pos >= 0);
|
||||
@@ -180,16 +170,6 @@ bool InputCaptureWindow::message(uint id, uintptr_t param) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(id == ui::Message::KeyDown) {
|
||||
if(uiInput) { uiInput->signal_key_down(param); }
|
||||
return true;
|
||||
}
|
||||
|
||||
if(id == ui::Message::KeyUp) {
|
||||
if(uiInput) { uiInput->signal_key_up(param); }
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -20,10 +20,9 @@
|
||||
#include "../video/xv.cpp"
|
||||
#include "../video/gtk.cpp"
|
||||
#include "../audio/ao.cpp"
|
||||
#include "../input/xinput.cpp"
|
||||
#endif
|
||||
|
||||
#include "../input/inputui.cpp"
|
||||
|
||||
void ui_init() {
|
||||
window_main.setup();
|
||||
window_about.setup();
|
||||
@@ -49,7 +48,6 @@ void ui_init() {
|
||||
(Audio*)new AudioDS(window_main.handle());
|
||||
uiInput =
|
||||
config::system.input == "none" ? (Input*)new Input() :
|
||||
config::system.input == "ui" ? (Input*)new InputUI() :
|
||||
(Input*)new InputDI(window_main.handle());
|
||||
#elif defined(PLATFORM_X)
|
||||
uiVideo =
|
||||
@@ -61,7 +59,7 @@ void ui_init() {
|
||||
(Audio*)new AudioAO(config::system.audio_flags);
|
||||
uiInput =
|
||||
config::system.input == "none" ? (Input*)new Input() :
|
||||
(Input*)new InputUI();
|
||||
(Input*)new InputX();
|
||||
#endif
|
||||
|
||||
uiVideo->init();
|
||||
|
||||
+15
-9
@@ -1,3 +1,13 @@
|
||||
bool MainWindow::input_ready() {
|
||||
#if defined(PLATFORM_X)
|
||||
//FIXME: focused() is broken in X port
|
||||
return true;
|
||||
#endif
|
||||
|
||||
//only allow input when main window is focused
|
||||
return focused() == true;
|
||||
}
|
||||
|
||||
bool MainWindow::message(uint id, uintptr_t param) {
|
||||
ui::Control *control = (ui::Control*)param;
|
||||
if(id == ui::Message::Close) {
|
||||
@@ -12,17 +22,11 @@ ui::Control *control = (ui::Control*)param;
|
||||
}
|
||||
|
||||
if(id == ui::Message::KeyDown) {
|
||||
if(uiInput) { uiInput->signal_key_down(param); }
|
||||
if(param == keymap::esc) { event::toggle_menu(); }
|
||||
if(param == keymap::f11) { event::toggle_fullscreen(); }
|
||||
return true;
|
||||
}
|
||||
|
||||
if(id == ui::Message::KeyUp) {
|
||||
if(uiInput) { uiInput->signal_key_up(param); }
|
||||
return true;
|
||||
}
|
||||
|
||||
if(id == ui::Message::Clicked) {
|
||||
if(control == &menu_file_load) {
|
||||
event::load_rom();
|
||||
@@ -108,13 +112,15 @@ ui::Control *control = (ui::Control*)param;
|
||||
}
|
||||
|
||||
void MainWindow::setup() {
|
||||
snesinterface.input_ready = bind(&MainWindow::input_ready, this);
|
||||
|
||||
ui::ControlGroup group;
|
||||
create(ui::Window::Center, 256, 224, BSNES_TITLE);
|
||||
set_background_color(0, 0, 0);
|
||||
|
||||
menu.create(*this);
|
||||
menu_file.create(menu, "File");
|
||||
menu_file_load.create(menu_file, "Load Cartridge");
|
||||
menu_file_load.create(menu_file, "Load Cartridge ...");
|
||||
menu_file_unload.create(menu_file, "Unload");
|
||||
menu_file_sep1.create(menu_file);
|
||||
menu_file_reset.create(menu_file, "Reset");
|
||||
@@ -175,7 +181,7 @@ ui::ControlGroup group;
|
||||
group.add(menu_settings_videoframeskip_7);
|
||||
group.add(menu_settings_videoframeskip_8);
|
||||
group.add(menu_settings_videoframeskip_9);
|
||||
menu_settings_videoframeskip_0.create(menu_settings_videoframeskip, group, "0 (off)");
|
||||
menu_settings_videoframeskip_0.create(menu_settings_videoframeskip, group, "0");
|
||||
menu_settings_videoframeskip_sep1.create(menu_settings_videoframeskip);
|
||||
menu_settings_videoframeskip_1.create(menu_settings_videoframeskip, group, "1");
|
||||
menu_settings_videoframeskip_2.create(menu_settings_videoframeskip, group, "2");
|
||||
@@ -210,7 +216,7 @@ ui::ControlGroup group;
|
||||
menu_settings_speedreg.finish();
|
||||
|
||||
menu_settings_sep3.create(menu_settings);
|
||||
menu_settings_config.create(menu_settings, "Configuration");
|
||||
menu_settings_config.create(menu_settings, "Configuration ...");
|
||||
menu_settings.finish();
|
||||
|
||||
menu_misc.create(menu, "Misc");
|
||||
|
||||
@@ -60,6 +60,8 @@ ui::MenuGroup menu_misc;
|
||||
ui::Container view;
|
||||
//
|
||||
|
||||
bool input_ready();
|
||||
|
||||
bool message(uint id, uintptr_t param = 0);
|
||||
void setup();
|
||||
void setup_menu();
|
||||
|
||||
@@ -11,10 +11,6 @@ void term_snes();
|
||||
* hardware abstraction layer
|
||||
*****/
|
||||
|
||||
#include "video/video.h"
|
||||
#include "audio/audio.h"
|
||||
#include "input/input.h"
|
||||
|
||||
#include "video/video.cpp"
|
||||
#include "audio/audio.cpp"
|
||||
#include "input/input.cpp"
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#include "video.h"
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifndef VIDEO_H
|
||||
#define VIDEO_H
|
||||
|
||||
class Video { public:
|
||||
|
||||
enum Filter {
|
||||
@@ -18,3 +21,5 @@ enum Filter {
|
||||
Video() {}
|
||||
virtual ~Video() {}
|
||||
} *uiVideo;
|
||||
|
||||
#endif
|
||||
Reference in new issue
Block a user