Compare commits

...

3 Commits
v022 ... v023

Author SHA1 Message Date
byuu
c9ca01fe20 Update to bsnes v023 release.
I've recently fixed a bug in bsnes that I feel is serious enough to warrant a new release, even though little else has changed.
I attempted to build this release with MinGW, but ran into problems with profiling and JMA support, so this release was built with Visual C++ once again.
Changelog:
    - Fixed serious bug in S-SMP incw and decw instructions -- fixes sound bug in Emerald Dragon
    - Added Nach's MinGW fixes -- can now be compiled with MinGW/GCC3 or MinGW/GCC4
    - Fixed const char* cast warnings in GCC 4.2, thanks to [vEX] for the feedback
    - Updated source to use latest libraries for libco, libui, etc.
    - Added new advanced options to adjust aspect ratio correction
    - Cleaned up source code a bit
2007-09-16 19:30:35 +00:00
byuu
becf122aaa Update to bsnes v022r04? release.
Ok, I've posted a new WIP with the Emerald Dragon bug
fix. This time, I'm not posting the WIP publically. My last request
not to link directly to the file elsewhere was ignored, and ended up
on at least two emulation news sites (I won't mention names.) I'm not
trying to be a jerk about it, I really can't spare that kind of
bandwidth.

 If anyone has contributed any code or bug fixes, reported any
confirmed bugs, or is an emulator author I've spoken to in the past,
feel free to request a link to the WIP page from me in PM if desired.

               Sorry to everyone else. I'll have the new version out
as soon as possible.







> As for the AR advanced option, I think option 2 looks perfect.




 Done. I didn't add any sanity checks, so that people can have a
little fun with it. It's not going to be a GUI option, so only
advanced users can play with it anyway. Try setting a crazy aspect
like 3:1 and play a platform game. It's guaranteed to mess with your
mind.

 I also added the ... stuff, but I did not add the pause support back
in yet. Not sure if that'll make the next release, because it requires
some changes to the main loop functions that have been missing for a
while now. I usually like to leave more of a beta testing window
before messing with that stuff.







> byuu, you may know this, but on the front page of your web site, the
> link to your Philosophical Ramblings page is
> "http://localhost/index.php?page=articles/philosophy".




               Hahah, oops. No, I didn't notice that. I must have
copied the link from my browser instead of typing it manually.

 It's a stupid article, anyway. Didn't come out like I planned. I was
also reading some comments by Miguel de Icaza (supporting patent
pacts) and Linus Torvalds (bashing the hell out of C++ programmers),
and came across an interesting comment that got me thinking. Basically
that people who have any kind of notability really shouldn't go around
talking about things outside their specific expertise, because it
makes them look foolish when people take them too seriously (and
people do) as those two comments by de Icaza and Torvalds did. Lucky
for me I really _don't_ have any kind of notability, but it's a good
principle to adhere to anyway. Stick to talking about what I know
best. That goes against my whole personality though, so I probably
won't change at all anyway.

[No archive available]
2007-09-12 10:08:00 +00:00
byuu
1e130d7872 Update to bsnes v022r03 release.
Double post!

 I've uploaded a new WIP, which I'll make public (only to this forum,
please don't post about it anywhere else unless you mirror the file):







    http://byuu.org/files/bsnes_v022_wip03.zip




 This version adds all of Nach's MinGW fixes, updated libco, libui and
libfunctor, cleans up the code that detects if the main window has
focus or not (if not, ignore keyboard input), adds the new makefile
target win-mingw-lui, finally fixes all of the char* conversion
warnings with GCC 4.2.x (thanks [vEX]), and I'm sure there's more, but
I don't remember.

 The ZIP includes a Visual C++ generated binary, but it also works
with MinGW GCC4. It won't work with MinGW GCC3 because that one lacks
a C99-compliant vsnprintf function. You can hack your way around that
by editing src/lib/libstring_sprintf.cpp if you really want to use
MinGW GCC3.

 You may also need to change the CC / CPP variable names. I went with
the generic names mingw32-gcc and mingw32-g++, but the GCC4 binaries
have -sjlj or -dw2 appended to them. You'll also need to set
-I/path/to/directxheaders, or copy them all into
/path/to/mingw/include, since MinGW seems to ignore the include
environment variable.

 And finally, a bit of good news. It appears that MinGW GCC4 builds
binaries that are ~6% faster than Visual C++. That means with PGO
enabled, they should be at least ~16% faster than v0.022 official. If
I can figure out how to hide the ugly terminal window in the
background, I'll start making official releases with MinGW GCC4 from
now on.
2007-09-08 08:41:18 +00:00
24 changed files with 356 additions and 146 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,3 +1,5 @@
#define _WIN32_IE 0x0600
#include "libui_win.h"
#include "libui_win_window.cpp"
#include "libui_win_control.cpp"

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
Tracer tracer;
void tprintf(char *s, ...) {
void tprintf(const char *s, ...) {
if(tracer.enabled() == false) { return; }
char str[4096];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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