bsnes/x86.c

111 lines
2.6 KiB
C
Raw Normal View History

Update to bsnes v028 release. Changelog: - OpenGL (with hardware filter mode support) and SDL video drivers added to Linux port - OpenAL (with speed regulation disable support) and OSS audio drivers added to Linux port [Nach] - SDL input driver (with joypad support) added to Linux port - Emulator pause option added - Added option to select behavior of bsnes when idle: allow input, ignore input or pause emulator - Added support to remap common GUI actions to key/joypad presses on the "Input Configuration" screen - bsnes will now clamp the video output size when it is larger than the screen resolution - GUI library has been enhanced, and renamed to hiro - Fullscreen mode now always centers video, rather than approximates - Fullscreen mode now works correctly on Linux/Openbox - Extra layer of abstraction in src/ui has been removed, as GUI lib unifies all ports anyway - Video, audio and input drivers unified into standard library, named ruby - All custom headers have been merged into a new template library, named nall - Makefile rewritten, vastly improved. Allows quick toggling of compiled-in drivers - Makefile: all object files now placed in /src/obj, binary placed in / - libco greatly enhanced, no longer requires an assembler to build [byuu, blargg, Nach] - libco SJLJ driver added; bsnes should now build on any Unix-derivative now (Solaris, OS X, PS3, etc) [Nach] - Fixed register $213e.d4 PPU1 open bus behavior [zones] - Windows port will not activate screensaver while bsnes is running [Nightcrawler] - Visual C++ target no longer requires stdint.h - And lots more -- mostly code refactoring related
2008-02-04 16:16:34 +00:00
/*
libco.x86 (2008-01-28)
author: byuu
license: public domain
*/
#define LIBCO_C
#include "../libco.h"
#include <assert.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
static thread_local long co_active_buffer[32];
static thread_local cothread_t co_active_ = 0;
static void crash() {
assert(0); /* called only if cothread_t entrypoint returns */
}
cothread_t co_active() {
if(!co_active_) co_active_ = &co_active_buffer;
return co_active_;
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void)) {
cothread_t handle;
assert(sizeof(long) == 4);
if(!co_active_) co_active_ = &co_active_buffer;
size += 128; /* allocate additional space for storage */
size &= ~15; /* align stack to 16-byte boundary */
if(handle = (cothread_t)calloc(size, 1)) {
long *p = (long*)((char*)handle + size); /* seek to top of stack */
*--p = (long)crash; /* crash if entrypoint returns */
*--p = (long)entrypoint; /* start of function */
*(long*)handle = (long)p; /* stack pointer */
}
return handle;
}
void co_delete(cothread_t handle) {
free(handle);
}
#if defined(__GNUC__)
void co_switch(cothread_t to) {
register long stack = *(long*)to; /* stack[0] = "to" thread entry point */
register cothread_t from = co_active_;
co_active_ = to;
__asm__ __volatile__(
"movl %%esp,(%1) \n\t" /* save old stack pointer */
"movl (%0),%%esp \n\t" /* load new stack pointer */
"addl $4,%%esp \n\t" /* "pop" return address off stack */
"movl %%ebp, 4(%1) \n\t" /* backup non-volatile registers */
"movl %%esi, 8(%1) \n\t"
"movl %%edi,12(%1) \n\t"
"movl %%ebx,16(%1) \n\t"
"movl 4(%0),%%ebp \n\t" /* restore non-volatile registers */
"movl 8(%0),%%esi \n\t"
"movl 12(%0),%%edi \n\t"
"movl 16(%0),%%ebx \n\t"
"jmp *(%2) \n\t" /* jump into "to" thread */
: /* no outputs */
: "r" (to), "r" (from), "r" (stack)
);
}
#elif defined(_MSC_VER)
__declspec(naked) __declspec(noinline)
static void __fastcall co_swap(register cothread_t to, register cothread_t from) {
/* ecx = to, edx = from */
__asm {
mov [edx],esp
mov esp,[ecx]
pop eax
mov [edx+ 4],ebp
mov [edx+ 8],esi
mov [edx+12],edi
mov [edx+16],ebx
mov ebp,[ecx+ 4]
mov esi,[ecx+ 8]
mov edi,[ecx+12]
mov ebx,[ecx+16]
jmp eax
}
}
void co_switch(cothread_t handle) {
register cothread_t co_prev_ = co_active_;
co_swap(co_active_ = handle, co_prev_);
}
#endif
#ifdef __cplusplus
}
#endif