mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-19 19:41:43 +02:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c9ca01fe20 | ||
|
becf122aaa | ||
|
1e130d7872 |
24
readme.txt
24
readme.txt
@@ -1,8 +1,8 @@
|
||||
bsnes
|
||||
Version 0.022
|
||||
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
|
||||
|
45
src/Makefile
45
src/Makefile
@@ -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
|
||||
|
||||
####################################
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#define BSNES_VERSION "0.022"
|
||||
#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 {
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
||||
|
100
src/lib/libfunctor.h
Normal file
100
src/lib/libfunctor.h
Normal file
@@ -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
|
81
src/lib/libfunctor_impl.h
Normal file
81
src/lib/libfunctor_impl.h
Normal file
@@ -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"
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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",
|
||||
|
@@ -39,12 +39,12 @@ void SNESInterface::audio_sample(uint16 l_sample, uint16 r_sample) {
|
||||
|
||||
//input
|
||||
|
||||
//allow_input() returns true only when main emulator window has focus
|
||||
//TODO: draft a more elegant way to poll lui, etc platforms from here
|
||||
bool allow_input(); //defined in lui/main.cpp
|
||||
|
||||
void SNESInterface::input_poll() {
|
||||
allow_input() ? uiInput->poll() : uiInput->clear_input();
|
||||
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) * 54.0 / 47.0 ); //NTSC
|
||||
} else {
|
||||
width = uint( double(width) * 32.0 / 23.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) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -18,16 +18,7 @@ bool _term_ = false;
|
||||
#include "ui.cpp"
|
||||
#include "event.cpp"
|
||||
|
||||
bool allow_input() {
|
||||
#if defined(PLATFORM_X)
|
||||
//TODO: window_main.focused() does not work at all on X
|
||||
return true;
|
||||
#endif
|
||||
//only allow input capture when main window is active
|
||||
return window_main.focused() == true;
|
||||
}
|
||||
|
||||
void alert(char *s, ...) {
|
||||
void alert(const char *s, ...) {
|
||||
char str[4096];
|
||||
va_list args;
|
||||
va_start(args, s);
|
||||
@@ -36,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);
|
||||
@@ -45,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);
|
||||
@@ -67,7 +58,8 @@ void run() {
|
||||
snes.runtoframe();
|
||||
event::update_frame_counter();
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
|
||||
#if defined(PLATFORM_WIN)
|
||||
//prevent bsnes from consuming 100% CPU resources when idle
|
||||
else { Sleep(1); }
|
||||
#endif
|
||||
|
@@ -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) {
|
||||
@@ -102,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");
|
||||
@@ -169,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");
|
||||
@@ -204,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();
|
||||
|
Reference in New Issue
Block a user