Merge pull request #2 from aliaspider/master

initial port of gpsp to libretro.
This commit is contained in:
Twinaphex 2014-12-09 13:28:17 +01:00
commit 988c2e2655
31 changed files with 3781 additions and 99 deletions

73
Makefile Normal file
View File

@ -0,0 +1,73 @@
TARGET := gpsp_libretro
CC = gcc
AR = psp-ar
STATIC_LINKING = 0
CFLAGS += -Werror-implicit-function-declaration
CFLAGS += -DPC_BUILD -Wall -m32
CFLAGS += -D__LIBRETRO__
ifeq ($(DEBUG), 1)
OPTIMIZE := -O0 -g
OPTIMIZE_SAFE := -O0 -g
else
OPTIMIZE := -O3
OPTIMIZE_SAFE := -O2
endif
OBJS := main.o
OBJS += cpu.o
OBJS += memory.o
OBJS += video.o
OBJS += input.o
OBJS += sound.o
OBJS += cpu_threaded.o
OBJS += x86/x86_stub.o
OBJS += cheats.o
OBJS += zip.o
OBJS += libretro.o
OBJS += libco/libco.o
ifeq ($(STATIC_LINKING), 1)
TARGET := $(TARGET).a
else
TARGET := $(TARGET).so
endif
ASFLAGS = $(CFLAGS)
INCDIRS := -I.
LDFLAGS += -shared -m32 -Wl,--no-undefined -Wl,--version-script=link.T
LDLIBS += -lz
all: $(TARGET)
$(TARGET): $(OBJS)
ifeq ($(STATIC_LINKING), 1)
$(AR) rcs $@ $(OBJS)
else
$(CC) -o $@ $(CFLAGS) $^ $(LDFLAGS) $(LDLIBS)
endif
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS) $(OPTIMIZE) $(INCDIRS)
cpu.o: cpu.c
$(CC) -c -o $@ $< $(CFLAGS) -Wno-unused-variable -Wno-unused-label $(OPTIMIZE_SAFE) $(INCDIRS)
cpu_threaded.o: cpu_threaded.c
$(CC) -c -o $@ $< $(CFLAGS) -Wno-unused-variable -Wno-unused-label $(OPTIMIZE_SAFE) $(INCDIRS)
%.o: %.S
$(CC) -c -o $@ $< $(ASFLAGS) $(OPTIMIZE)
clean:
# rm -f main.o memory.o input.o sound.o x86_stub.o cheats.o zip.o libretro.o
rm -f $(OBJS)
rm -f $(TARGET)
.PHONY: $(TARGET) clean

View File

@ -103,8 +103,18 @@
#include <time.h> #include <time.h>
#include <stdio.h> #include <stdio.h>
#else
#ifdef __LIBRETRO__
#define GBA_SCREEN_WIDTH (240)
#define GBA_SCREEN_HEIGHT (160)
#define GBA_SCREEN_PITCH (240)
void switch_to_main_thread(void);
#else #else
#include "SDL.h" #include "SDL.h"
#endif
#ifdef ARM_ARCH #ifdef ARM_ARCH
#define function_cc #define function_cc
@ -210,7 +220,9 @@ typedef u32 fixed8_24;
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#ifndef __LIBRETRO__
#include "SDL.h" #include "SDL.h"
#endif
#include "cpu.h" #include "cpu.h"
#include "memory.h" #include "memory.h"
#include "video.h" #include "video.h"

6
cpu.c
View File

@ -4146,8 +4146,10 @@ void function_cc step_debug(u32 pc, u32 cycles)
{ {
u32 key = 0; u32 key = 0;
#ifndef __LIBRETRO__
SDL_LockMutex(sound_mutex); SDL_LockMutex(sound_mutex);
SDL_PauseAudio(1); SDL_PauseAudio(1);
#endif
if(output_field >= num_output_fields) if(output_field >= num_output_fields)
{ {
@ -4272,7 +4274,7 @@ void function_cc step_debug(u32 pc, u32 cycles)
u16 *current_screen = copy_screen(); u16 *current_screen = copy_screen();
get_savestate_filename_noshot(savestate_slot, get_savestate_filename_noshot(savestate_slot,
current_savestate_filename); current_savestate_filename);
save_state(current_savestate_filename, current_screen); gba_save_state(current_savestate_filename, current_screen);
free(current_screen); free(current_screen);
break; break;
} }
@ -4281,8 +4283,10 @@ void function_cc step_debug(u32 pc, u32 cycles)
quit(); quit();
} }
#ifndef __LIBRETRO__
SDL_PauseAudio(0); SDL_PauseAudio(0);
SDL_UnlockMutex(sound_mutex); SDL_UnlockMutex(sound_mutex);
#endif
} }
last_instruction = reg[REG_PC]; last_instruction = reg[REG_PC];

6
cpu.h
View File

@ -152,9 +152,15 @@ s32 translate_block_thumb(u32 pc, translation_region_type translation_region,
#endif #endif
#ifdef __LIBRETRO__
extern u8* rom_translation_cache;
extern u8* ram_translation_cache;
extern u8* bios_translation_cache;
#else
extern u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE]; extern u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE];
extern u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE]; extern u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE];
extern u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE]; extern u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE];
#endif
extern u8 *rom_translation_ptr; extern u8 *rom_translation_ptr;
extern u8 *ram_translation_ptr; extern u8 *ram_translation_ptr;
extern u8 *bios_translation_ptr; extern u8 *bios_translation_ptr;

View File

@ -23,18 +23,27 @@
#include "common.h" #include "common.h"
#ifdef __LIBRETRO__
u8* rom_translation_cache;
u8* ram_translation_cache;
u8* bios_translation_cache;
u8 *rom_translation_ptr;
u8 *ram_translation_ptr;
u8 *bios_translation_ptr;
#else
u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE]; u8 rom_translation_cache[ROM_TRANSLATION_CACHE_SIZE];
u8 *rom_translation_ptr = rom_translation_cache;
u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE]; u8 ram_translation_cache[RAM_TRANSLATION_CACHE_SIZE];
u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE];
u8 *rom_translation_ptr = rom_translation_cache;
u8 *ram_translation_ptr = ram_translation_cache; u8 *ram_translation_ptr = ram_translation_cache;
u8 *bios_translation_ptr = bios_translation_cache;
#endif
u32 iwram_code_min = 0xFFFFFFFF; u32 iwram_code_min = 0xFFFFFFFF;
u32 iwram_code_max = 0xFFFFFFFF; u32 iwram_code_max = 0xFFFFFFFF;
u32 ewram_code_min = 0xFFFFFFFF; u32 ewram_code_min = 0xFFFFFFFF;
u32 ewram_code_max = 0xFFFFFFFF; u32 ewram_code_max = 0xFFFFFFFF;
u8 bios_translation_cache[BIOS_TRANSLATION_CACHE_SIZE];
u8 *bios_translation_ptr = bios_translation_cache;
u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE]; u32 *rom_branch_hash[ROM_BRANCH_HASH_SIZE];

6
gui.c
View File

@ -1150,7 +1150,7 @@ u32 menu(u16 *original_screen)
{ {
get_savestate_filename_noshot(savestate_slot, get_savestate_filename_noshot(savestate_slot,
current_savestate_filename); current_savestate_filename);
save_state(current_savestate_filename, original_screen); gba_save_state(current_savestate_filename, original_screen);
} }
menu_change_state(); menu_change_state();
} }
@ -1159,7 +1159,7 @@ u32 menu(u16 *original_screen)
{ {
if(!first_load) if(!first_load)
{ {
load_state(current_savestate_filename); gba_load_state(current_savestate_filename);
return_value = 1; return_value = 1;
repeat = 0; repeat = 0;
} }
@ -1171,7 +1171,7 @@ u32 menu(u16 *original_screen)
char load_filename[512]; char load_filename[512];
if(load_file(file_ext, load_filename) != -1) if(load_file(file_ext, load_filename) != -1)
{ {
load_state(load_filename); gba_load_state(load_filename);
return_value = 1; return_value = 1;
repeat = 0; repeat = 0;
} }

27
input.c
View File

@ -343,10 +343,33 @@ void init_input()
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
} }
#endif #elif defined(__LIBRETRO__)
static retro_input_state_t input_state_cb;
void retro_set_input_state(retro_input_state_t cb) { input_state_cb = cb; }
#if defined(PC_BUILD) u32 update_input(void)
{
// return;
unsigned i;
uint32_t new_key = 0;
if (!input_state_cb)
return 0;
for (i = 0; i < sizeof(btn_map) / sizeof(map); i++)
new_key |= input_state_cb(0, RETRO_DEVICE_JOYPAD, 0, btn_map[i].retropad) ? btn_map[i].gba : 0;
if ((new_key | key) != key)
trigger_key(new_key);
key = new_key;
io_registers[REG_P1] = (~key) & 0x3FF;
return 0;
}
#elif defined(PC_BUILD)
u32 key_map(SDLKey key_sym) u32 key_map(SDLKey key_sym)
{ {

22
input.h
View File

@ -82,6 +82,28 @@ gui_action_type get_gui_input_fs_hold(u32 button_id);
void input_write_mem_savestate(file_tag_type savestate_file); void input_write_mem_savestate(file_tag_type savestate_file);
void input_read_savestate(file_tag_type savestate_file); void input_read_savestate(file_tag_type savestate_file);
#ifdef __LIBRETRO__
#include "libretro.h"
typedef struct
{
unsigned retropad ;
input_buttons_type gba;
} map;
static const map btn_map[] = {
{ RETRO_DEVICE_ID_JOYPAD_L, BUTTON_L },
{ RETRO_DEVICE_ID_JOYPAD_R, BUTTON_R },
{ RETRO_DEVICE_ID_JOYPAD_DOWN, BUTTON_DOWN },
{ RETRO_DEVICE_ID_JOYPAD_UP, BUTTON_UP },
{ RETRO_DEVICE_ID_JOYPAD_LEFT, BUTTON_LEFT },
{ RETRO_DEVICE_ID_JOYPAD_RIGHT, BUTTON_RIGHT },
{ RETRO_DEVICE_ID_JOYPAD_START, BUTTON_START },
{ RETRO_DEVICE_ID_JOYPAD_SELECT, BUTTON_SELECT },
{ RETRO_DEVICE_ID_JOYPAD_B, BUTTON_B },
{ RETRO_DEVICE_ID_JOYPAD_A, BUTTON_A }
};
#endif
extern u32 gamepad_config_map[]; extern u32 gamepad_config_map[];
extern u32 global_enable_analog; extern u32 global_enable_analog;
extern u32 analog_sensitivity_level; extern u32 analog_sensitivity_level;

37
libco.h Normal file
View File

@ -0,0 +1,37 @@
/*
libco
version: 0.16 (2010-12-24)
license: public domain
*/
#ifndef LIBCO_H
#define LIBCO_H
#ifdef LIBCO_C
#ifdef LIBCO_MP
#define thread_local __thread
#else
#define thread_local
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void* cothread_t;
cothread_t co_active(void);
cothread_t co_create(unsigned int, void (*)(void));
void co_delete(cothread_t);
void co_switch(cothread_t);
#ifdef __cplusplus
}
#endif
/* ifndef LIBCO_H */
#endif

161
libco/amd64.c Normal file
View File

@ -0,0 +1,161 @@
/*
libco.amd64 (2009-10-12)
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 long co_active_buffer[64];
static thread_local cothread_t co_active_handle = 0;
static void (*co_swap)(cothread_t, cothread_t) = 0;
#ifdef _WIN32
//ABI: Win64
static unsigned char co_swap_function[] = {
0x48, 0x89, 0x22, /* mov [rdx],rsp */
0x48, 0x8b, 0x21, /* mov rsp,[rcx] */
0x58, /* pop rax */
0x48, 0x89, 0x6a, 0x08, /* mov [rdx+0x8],rbp */
0x48, 0x89, 0x72, 0x10, /* mov [rdx+0x10],rsi */
0x48, 0x89, 0x7a, 0x18, /* mov [rdx+0x18],rdi */
0x48, 0x89, 0x5a, 0x20, /* mov [rdx+0x20],rbx */
0x4c, 0x89, 0x62, 0x28, /* mov [rdx+0x28],r12 */
0x4c, 0x89, 0x6a, 0x30, /* mov [rdx+0x30],r13 */
0x4c, 0x89, 0x72, 0x38, /* mov [rdx+0x38],r14 */
0x4c, 0x89, 0x7a, 0x40, /* mov [rdx+0x40],r15 */
0x48, 0x81, 0xc2, 0x80, 0x00, 0x00, 0x00, /* add rdx,0x80 */
0x48, 0x83, 0xe2, 0xf0, /* and rdx,-0x10 */
0x0f, 0x29, 0x32, /* movaps [rdx],xmm6 */
0x0f, 0x29, 0x7a, 0x10, /* movaps [rdx+0x10],xmm7 */
0x44, 0x0f, 0x29, 0x42, 0x20, /* movaps [rdx+0x20],xmm8 */
0x44, 0x0f, 0x29, 0x4a, 0x30, /* movaps [rdx+0x30],xmm9 */
0x44, 0x0f, 0x29, 0x52, 0x40, /* movaps [rdx+0x40],xmm10 */
0x44, 0x0f, 0x29, 0x5a, 0x50, /* movaps [rdx+0x50],xmm11 */
0x44, 0x0f, 0x29, 0x62, 0x60, /* movaps [rdx+0x60],xmm12 */
0x44, 0x0f, 0x29, 0x6a, 0x70, /* movaps [rdx+0x70],xmm13 */
0x44, 0x0f, 0x29, 0xb2, 0x80, 0x00, 0x00, 0x00, /* movaps [rdx+0x80],xmm14 */
0x44, 0x0f, 0x29, 0xba, 0x90, 0x00, 0x00, 0x00, /* movaps [rdx+0x90],xmm15 */
0x48, 0x8b, 0x69, 0x08, /* mov rbp,[rcx+0x8] */
0x48, 0x8b, 0x71, 0x10, /* mov rsi,[rcx+0x10] */
0x48, 0x8b, 0x79, 0x18, /* mov rdi,[rcx+0x18] */
0x48, 0x8b, 0x59, 0x20, /* mov rbx,[rcx+0x20] */
0x4c, 0x8b, 0x61, 0x28, /* mov r12,[rcx+0x28] */
0x4c, 0x8b, 0x69, 0x30, /* mov r13,[rcx+0x30] */
0x4c, 0x8b, 0x71, 0x38, /* mov r14,[rcx+0x38] */
0x4c, 0x8b, 0x79, 0x40, /* mov r15,[rcx+0x40] */
0x48, 0x81, 0xc1, 0x80, 0x00, 0x00, 0x00, /* add rcx,0x80 */
0x48, 0x83, 0xe1, 0xf0, /* and rcx,-0x10 */
0x0f, 0x29, 0x31, /* movaps [rcx],xmm6 */
0x0f, 0x29, 0x79, 0x10, /* movaps [rcx+0x10],xmm7 */
0x44, 0x0f, 0x29, 0x41, 0x20, /* movaps [rcx+0x20],xmm8 */
0x44, 0x0f, 0x29, 0x49, 0x30, /* movaps [rcx+0x30],xmm9 */
0x44, 0x0f, 0x29, 0x51, 0x40, /* movaps [rcx+0x40],xmm10 */
0x44, 0x0f, 0x29, 0x59, 0x50, /* movaps [rcx+0x50],xmm11 */
0x44, 0x0f, 0x29, 0x61, 0x60, /* movaps [rcx+0x60],xmm12 */
0x44, 0x0f, 0x29, 0x69, 0x70, /* movaps [rcx+0x70],xmm13 */
0x44, 0x0f, 0x29, 0xb1, 0x80, 0x00, 0x00, 0x00, /* movaps [rcx+0x80],xmm14 */
0x44, 0x0f, 0x29, 0xb9, 0x90, 0x00, 0x00, 0x00, /* movaps [rcx+0x90],xmm15 */
0xff, 0xe0, /* jmp rax */
};
#include <windows.h>
void co_init(void)
{
DWORD old_privileges;
VirtualProtect(co_swap_function,
sizeof(co_swap_function), PAGE_EXECUTE_READWRITE, &old_privileges);
}
#else
//ABI: SystemV
static unsigned char co_swap_function[] = {
0x48, 0x89, 0x26, /* mov [rsi],rsp */
0x48, 0x8b, 0x27, /* mov rsp,[rdi] */
0x58, /* pop rax */
0x48, 0x89, 0x6e, 0x08, /* mov [rsi+0x08],rbp */
0x48, 0x89, 0x5e, 0x10, /* mov [rsi+0x10],rbx */
0x4c, 0x89, 0x66, 0x18, /* mov [rsi+0x18],r12 */
0x4c, 0x89, 0x6e, 0x20, /* mov [rsi+0x20],r13 */
0x4c, 0x89, 0x76, 0x28, /* mov [rsi+0x28],r14 */
0x4c, 0x89, 0x7e, 0x30, /* mov [rsi+0x30],r15 */
0x48, 0x8b, 0x6f, 0x08, /* mov rbp,[rdi+0x08] */
0x48, 0x8b, 0x5f, 0x10, /* mov rbx,[rdi+0x10] */
0x4c, 0x8b, 0x67, 0x18, /* mov r12,[rdi+0x18] */
0x4c, 0x8b, 0x6f, 0x20, /* mov r13,[rdi+0x20] */
0x4c, 0x8b, 0x77, 0x28, /* mov r14,[rdi+0x28] */
0x4c, 0x8b, 0x7f, 0x30, /* mov r15,[rdi+0x30] */
0xff, 0xe0, /* jmp rax */
};
#include <unistd.h>
#include <sys/mman.h>
void co_init(void)
{
unsigned long long addr = (unsigned long long)co_swap_function;
unsigned long long base = addr - (addr % sysconf(_SC_PAGESIZE));
unsigned long long size = (addr - base) + sizeof(co_swap_function);
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
}
#endif
static void crash(void)
{
assert(0); /* called only if cothread_t entrypoint returns */
}
cothread_t co_active(void)
{
if (!co_active_handle)
co_active_handle = &co_active_buffer;
return co_active_handle;
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void))
{
cothread_t handle;
if(!co_swap)
{
co_init();
co_swap = (void (*)(cothread_t, cothread_t))co_swap_function;
}
if (!co_active_handle)
co_active_handle = &co_active_buffer;
size += 512; /* allocate additional space for storage */
size &= ~15; /* align stack to 16-byte boundary */
if(handle = (cothread_t)malloc(size))
{
long long *p = (long long*)((char*)handle + size); /* seek to top of stack */
*--p = (long long)crash; /* crash if entrypoint returns */
*--p = (long long)entrypoint; /* start of function */
*(long long*)handle = (long long)p; /* stack pointer */
}
return handle;
}
void co_delete(cothread_t handle)
{
free(handle);
}
void co_switch(cothread_t handle)
{
register cothread_t co_previous_handle = co_active_handle;
co_swap(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif

95
libco/armeabi.c Normal file
View File

@ -0,0 +1,95 @@
/*
libco.armeabi (2013-04-05)
author: Themaister
license: public domain
*/
#define LIBCO_C
#include <libco.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#ifndef IOS
#include <malloc.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
static thread_local uint32_t co_active_buffer[64];
static thread_local cothread_t co_active_handle;
asm (
".arm\n"
".align 4\n"
".globl co_switch_arm\n"
".globl _co_switch_arm\n"
"co_switch_arm:\n"
"_co_switch_arm:\n"
" stmia r1!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, lr}\n"
" ldmia r0!, {r4, r5, r6, r7, r8, r9, r10, r11, sp, pc}\n"
);
/* ASM */
void co_switch_arm(cothread_t handle, cothread_t current);
static void crash(void)
{
/* Called only if cothread_t entrypoint returns. */
assert(0);
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void))
{
size = (size + 1023) & ~1023;
cothread_t handle = 0;
#if HAVE_POSIX_MEMALIGN >= 1
if (posix_memalign(&handle, 1024, size + 256) < 0)
return 0;
#else
handle = memalign(1024, size + 256);
#endif
if (!handle)
return handle;
uint32_t *ptr = (uint32_t*)handle;
/* Non-volatiles. */
ptr[0] = 0; /* r4 */
ptr[1] = 0; /* r5 */
ptr[2] = 0; /* r6 */
ptr[3] = 0; /* r7 */
ptr[4] = 0; /* r8 */
ptr[5] = 0; /* r9 */
ptr[6] = 0; /* r10 */
ptr[7] = 0; /* r11 */
ptr[8] = (uintptr_t)ptr + size + 256 - 4; /* r13, stack pointer */
ptr[9] = (uintptr_t)entrypoint; /* r15, PC (link register r14 gets saved here). */
return handle;
}
cothread_t co_active(void)
{
if (!co_active_handle)
co_active_handle = co_active_buffer;
return co_active_handle;
}
void co_delete(cothread_t handle)
{
free(handle);
}
void co_switch(cothread_t handle)
{
cothread_t co_previous_handle = co_active();
co_switch_arm(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif

58
libco/fiber.c Normal file
View File

@ -0,0 +1,58 @@
/*
libco.win (2008-01-28)
authors: Nach, byuu
license: public domain
*/
#define LIBCO_C
#include <libco.h>
#define WINVER 0x0400
#define _WIN32_WINNT 0x0400
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
static thread_local cothread_t co_active_ = 0;
static void __stdcall co_thunk(void *coentry)
{
((void (*)(void))coentry)();
}
cothread_t co_active(void)
{
if(!co_active_)
{
ConvertThreadToFiber(0);
co_active_ = GetCurrentFiber();
}
return co_active_;
}
cothread_t co_create(unsigned int heapsize, void (*coentry)(void))
{
if(!co_active_)
{
ConvertThreadToFiber(0);
co_active_ = GetCurrentFiber();
}
return (cothread_t)CreateFiber(heapsize, co_thunk, (void*)coentry);
}
void co_delete(cothread_t cothread)
{
DeleteFiber(cothread);
}
void co_switch(cothread_t cothread)
{
co_active_ = cothread;
SwitchToFiber(cothread);
}
#ifdef __cplusplus
}
#endif

21
libco/libco.c Normal file
View File

@ -0,0 +1,21 @@
/*
libco
auto-selection module
license: public domain
*/
#if defined(__GNUC__) && defined(__i386__) || (defined(_MSC_VER) && defined(_M_IX86))
#include "x86.c"
#elif defined(__GNUC__) && defined(__amd64__) || (defined(_MSC_VER) && defined(_M_AMD64))
#include "amd64.c"
#elif defined(__GNUC__) && defined(_ARCH_PPC)
#include "ppc.c"
#elif defined(__GNUC__) && (defined(__ARM_EABI__) || defined(__arm__))
#include "armeabi.c"
#elif defined(__GNUC__)
#include "sjlj.c"
#elif defined(_MSC_VER)
#include "fiber.c"
#else
#error "libco: unsupported processor, compiler or operating system"
#endif

407
libco/ppc.c Normal file
View File

@ -0,0 +1,407 @@
/*
libco.ppc (2010-10-17)
author: blargg
license: public domain
*/
/* PowerPC 32/64 using embedded or external asm, with optional
floating-point and AltiVec save/restore */
#define LIBCO_C
#include <libco.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#define LIBCO_MPROTECT (__unix__ && !LIBCO_PPC_ASM)
#if LIBCO_MPROTECT
#include <unistd.h>
#include <sys/mman.h>
#endif
/* State format (offsets in 32-bit words)
+0 Pointer to swap code
Rest of function descriptor for entry function
+8 PC
+10 SP
Special regs
GPRs
FPRs
VRs
stack
*/
enum { state_size = 1024 };
enum { above_stack = 2048 };
enum { stack_align = 256 };
static thread_local cothread_t co_active_handle = 0;
/**** Determine environment ****/
#define LIBCO_PPC64 (_ARCH_PPC64 || __PPC64__ || __ppc64__ || __powerpc64__)
/* Whether function calls are indirect through a descriptor,
or are directly to function */
#ifndef LIBCO_PPCDESC
#if !_CALL_SYSV && (_CALL_AIX || _CALL_AIXDESC || LIBCO_PPC64)
#define LIBCO_PPCDESC 1
#endif
#endif
#ifdef LIBCO_PPC_ASM
#ifdef __cplusplus
extern "C"
#endif
/* Swap code is in ppc.S */
void co_swap_asm( cothread_t, cothread_t );
#define CO_SWAP_ASM( x, y ) co_swap_asm( x, y )
#else
/* Swap code is here in array. Please leave dieassembly comments,
as they make it easy to see what it does, and reorder instructions
if one wants to see whether that improves performance. */
static const uint32_t libco_ppc_code [] = {
#if LIBCO_PPC64
0x7d000026, /* mfcr r8 */
0xf8240028, /* std r1,40(r4) */
0x7d2802a6, /* mflr r9 */
0xf9c40048, /* std r14,72(r4) */
0xf9e40050, /* std r15,80(r4) */
0xfa040058, /* std r16,88(r4) */
0xfa240060, /* std r17,96(r4) */
0xfa440068, /* std r18,104(r4) */
0xfa640070, /* std r19,112(r4) */
0xfa840078, /* std r20,120(r4) */
0xfaa40080, /* std r21,128(r4) */
0xfac40088, /* std r22,136(r4) */
0xfae40090, /* std r23,144(r4) */
0xfb040098, /* std r24,152(r4) */
0xfb2400a0, /* std r25,160(r4) */
0xfb4400a8, /* std r26,168(r4) */
0xfb6400b0, /* std r27,176(r4) */
0xfb8400b8, /* std r28,184(r4) */
0xfba400c0, /* std r29,192(r4) */
0xfbc400c8, /* std r30,200(r4) */
0xfbe400d0, /* std r31,208(r4) */
0xf9240020, /* std r9,32(r4) */
0xe8e30020, /* ld r7,32(r3) */
0xe8230028, /* ld r1,40(r3) */
0x48000009, /* bl 1 */
0x7fe00008, /* trap */
0x91040030,/*1:stw r8,48(r4) */
0x80c30030, /* lwz r6,48(r3) */
0x7ce903a6, /* mtctr r7 */
0xe9c30048, /* ld r14,72(r3) */
0xe9e30050, /* ld r15,80(r3) */
0xea030058, /* ld r16,88(r3) */
0xea230060, /* ld r17,96(r3) */
0xea430068, /* ld r18,104(r3) */
0xea630070, /* ld r19,112(r3) */
0xea830078, /* ld r20,120(r3) */
0xeaa30080, /* ld r21,128(r3) */
0xeac30088, /* ld r22,136(r3) */
0xeae30090, /* ld r23,144(r3) */
0xeb030098, /* ld r24,152(r3) */
0xeb2300a0, /* ld r25,160(r3) */
0xeb4300a8, /* ld r26,168(r3) */
0xeb6300b0, /* ld r27,176(r3) */
0xeb8300b8, /* ld r28,184(r3) */
0xeba300c0, /* ld r29,192(r3) */
0xebc300c8, /* ld r30,200(r3) */
0xebe300d0, /* ld r31,208(r3) */
0x7ccff120, /* mtcr r6 */
#else
0x7d000026, /* mfcr r8 */
0x90240028, /* stw r1,40(r4) */
0x7d2802a6, /* mflr r9 */
0x91a4003c, /* stw r13,60(r4) */
0x91c40040, /* stw r14,64(r4) */
0x91e40044, /* stw r15,68(r4) */
0x92040048, /* stw r16,72(r4) */
0x9224004c, /* stw r17,76(r4) */
0x92440050, /* stw r18,80(r4) */
0x92640054, /* stw r19,84(r4) */
0x92840058, /* stw r20,88(r4) */
0x92a4005c, /* stw r21,92(r4) */
0x92c40060, /* stw r22,96(r4) */
0x92e40064, /* stw r23,100(r4) */
0x93040068, /* stw r24,104(r4) */
0x9324006c, /* stw r25,108(r4) */
0x93440070, /* stw r26,112(r4) */
0x93640074, /* stw r27,116(r4) */
0x93840078, /* stw r28,120(r4) */
0x93a4007c, /* stw r29,124(r4) */
0x93c40080, /* stw r30,128(r4) */
0x93e40084, /* stw r31,132(r4) */
0x91240020, /* stw r9,32(r4) */
0x80e30020, /* lwz r7,32(r3) */
0x80230028, /* lwz r1,40(r3) */
0x48000009, /* bl 1 */
0x7fe00008, /* trap */
0x91040030,/*1:stw r8,48(r4) */
0x80c30030, /* lwz r6,48(r3) */
0x7ce903a6, /* mtctr r7 */
0x81a3003c, /* lwz r13,60(r3) */
0x81c30040, /* lwz r14,64(r3) */
0x81e30044, /* lwz r15,68(r3) */
0x82030048, /* lwz r16,72(r3) */
0x8223004c, /* lwz r17,76(r3) */
0x82430050, /* lwz r18,80(r3) */
0x82630054, /* lwz r19,84(r3) */
0x82830058, /* lwz r20,88(r3) */
0x82a3005c, /* lwz r21,92(r3) */
0x82c30060, /* lwz r22,96(r3) */
0x82e30064, /* lwz r23,100(r3) */
0x83030068, /* lwz r24,104(r3) */
0x8323006c, /* lwz r25,108(r3) */
0x83430070, /* lwz r26,112(r3) */
0x83630074, /* lwz r27,116(r3) */
0x83830078, /* lwz r28,120(r3) */
0x83a3007c, /* lwz r29,124(r3) */
0x83c30080, /* lwz r30,128(r3) */
0x83e30084, /* lwz r31,132(r3) */
0x7ccff120, /* mtcr r6 */
#endif
#ifndef LIBCO_PPC_NOFP
0xd9c400e0, /* stfd f14,224(r4) */
0xd9e400e8, /* stfd f15,232(r4) */
0xda0400f0, /* stfd f16,240(r4) */
0xda2400f8, /* stfd f17,248(r4) */
0xda440100, /* stfd f18,256(r4) */
0xda640108, /* stfd f19,264(r4) */
0xda840110, /* stfd f20,272(r4) */
0xdaa40118, /* stfd f21,280(r4) */
0xdac40120, /* stfd f22,288(r4) */
0xdae40128, /* stfd f23,296(r4) */
0xdb040130, /* stfd f24,304(r4) */
0xdb240138, /* stfd f25,312(r4) */
0xdb440140, /* stfd f26,320(r4) */
0xdb640148, /* stfd f27,328(r4) */
0xdb840150, /* stfd f28,336(r4) */
0xdba40158, /* stfd f29,344(r4) */
0xdbc40160, /* stfd f30,352(r4) */
0xdbe40168, /* stfd f31,360(r4) */
0xc9c300e0, /* lfd f14,224(r3) */
0xc9e300e8, /* lfd f15,232(r3) */
0xca0300f0, /* lfd f16,240(r3) */
0xca2300f8, /* lfd f17,248(r3) */
0xca430100, /* lfd f18,256(r3) */
0xca630108, /* lfd f19,264(r3) */
0xca830110, /* lfd f20,272(r3) */
0xcaa30118, /* lfd f21,280(r3) */
0xcac30120, /* lfd f22,288(r3) */
0xcae30128, /* lfd f23,296(r3) */
0xcb030130, /* lfd f24,304(r3) */
0xcb230138, /* lfd f25,312(r3) */
0xcb430140, /* lfd f26,320(r3) */
0xcb630148, /* lfd f27,328(r3) */
0xcb830150, /* lfd f28,336(r3) */
0xcba30158, /* lfd f29,344(r3) */
0xcbc30160, /* lfd f30,352(r3) */
0xcbe30168, /* lfd f31,360(r3) */
#endif
#ifdef __ALTIVEC__
0x7ca042a6, /* mfvrsave r5 */
0x39040180, /* addi r8,r4,384 */
0x39240190, /* addi r9,r4,400 */
0x70a00fff, /* andi. r0,r5,4095 */
0x90a40034, /* stw r5,52(r4) */
0x4182005c, /* beq- 2 */
0x7e8041ce, /* stvx v20,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ea049ce, /* stvx v21,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7ec041ce, /* stvx v22,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ee049ce, /* stvx v23,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f0041ce, /* stvx v24,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f2049ce, /* stvx v25,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f4041ce, /* stvx v26,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f6049ce, /* stvx v27,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f8041ce, /* stvx v28,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7fa049ce, /* stvx v29,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7fc041ce, /* stvx v30,r0,r8 */
0x7fe049ce, /* stvx v31,r0,r9 */
0x80a30034,/*2:lwz r5,52(r3) */
0x39030180, /* addi r8,r3,384 */
0x39230190, /* addi r9,r3,400 */
0x70a00fff, /* andi. r0,r5,4095 */
0x7ca043a6, /* mtvrsave r5 */
0x4d820420, /* beqctr */
0x7e8040ce, /* lvx v20,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ea048ce, /* lvx v21,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7ec040ce, /* lvx v22,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7ee048ce, /* lvx v23,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f0040ce, /* lvx v24,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f2048ce, /* lvx v25,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f4040ce, /* lvx v26,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7f6048ce, /* lvx v27,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7f8040ce, /* lvx v28,r0,r8 */
0x39080020, /* addi r8,r8,32 */
0x7fa048ce, /* lvx v29,r0,r9 */
0x39290020, /* addi r9,r9,32 */
0x7fc040ce, /* lvx v30,r0,r8 */
0x7fe048ce, /* lvx v31,r0,r9 */
#endif
0x4e800420, /* bctr */
};
#if LIBCO_PPCDESC
/* Function call goes through indirect descriptor */
#define CO_SWAP_ASM( x, y ) \
((void (*)( cothread_t, cothread_t )) (uintptr_t) x)( x, y )
#else
/* Function call goes directly to code */
#define CO_SWAP_ASM( x, y ) \
((void (*)( cothread_t, cothread_t )) (uintptr_t) libco_ppc_code)( x, y )
#endif
#endif
static uint32_t* co_create_( unsigned size, uintptr_t entry )
{
uint32_t* t = (uint32_t*) malloc( size );
(void) entry;
#if LIBCO_PPCDESC
if ( t )
{
/* Copy entry's descriptor */
memcpy( t, (void*) entry, sizeof (void*) * 3 );
/* Set function pointer to swap routine */
#ifdef LIBCO_PPC_ASM
*(const void**) t = *(void**) &co_swap_asm;
#else
*(const void**) t = libco_ppc_code;
#endif
}
#endif
return t;
}
cothread_t co_create( unsigned int size, void (*entry_)( void ) )
{
uintptr_t entry = (uintptr_t) entry_;
uint32_t* t = NULL;
/* Be sure main thread was successfully allocated */
if ( co_active() )
{
size += state_size + above_stack + stack_align;
t = co_create_( size, entry );
}
if ( t )
{
uintptr_t sp;
int shift;
/* Save current registers into new thread, so that any special ones will
have proper values when thread is begun */
CO_SWAP_ASM( t, t );
#if LIBCO_PPCDESC
/* Get real address */
entry = (uintptr_t) *(void**) entry;
#endif
/* Put stack near end of block, and align */
sp = (uintptr_t) t + size - above_stack;
sp -= sp % stack_align;
/* On PPC32, we save and restore GPRs as 32 bits. For PPC64, we
save and restore them as 64 bits, regardless of the size the ABI
uses. So, we manually write pointers at the proper size. We always
save and restore at the same address, and since PPC is big-endian,
we must put the low byte first on PPC32. */
/* If uintptr_t is 32 bits, >>32 is undefined behavior, so we do two shifts
and don't have to care how many bits uintptr_t is. */
#if LIBCO_PPC64
shift = 16;
#else
shift = 0;
#endif
/* Set up so entry will be called on next swap */
t [8] = (uint32_t) (entry >> shift >> shift);
t [9] = (uint32_t) entry;
t [10] = (uint32_t) (sp >> shift >> shift);
t [11] = (uint32_t) sp;
}
return t;
}
void co_delete( cothread_t t )
{
free(t);
}
static void co_init_( void )
{
#if LIBCO_MPROTECT
/* TODO: pre- and post-pad PPC code so that this doesn't make other
data executable and writable */
long page_size = sysconf( _SC_PAGESIZE );
if ( page_size > 0 )
{
uintptr_t align = page_size;
uintptr_t begin = (uintptr_t) libco_ppc_code;
uintptr_t end = begin + sizeof libco_ppc_code;
/* Align beginning and end */
end += align - 1;
end -= end % align;
begin -= begin % align;
mprotect( (void*) begin, end - begin, PROT_READ | PROT_WRITE | PROT_EXEC );
}
#endif
co_active_handle = co_create_( state_size, (uintptr_t) &co_switch );
}
cothread_t co_active(void)
{
if (!co_active_handle)
co_init_();
return co_active_handle;
}
void co_switch(cothread_t t)
{
cothread_t old = co_active_handle;
co_active_handle = t;
CO_SWAP_ASM( t, old );
}

115
libco/sjlj.c Normal file
View File

@ -0,0 +1,115 @@
/*
libco.sjlj (2008-01-28)
author: Nach
license: public domain
*/
/*
* Note this was designed for UNIX systems. Based on ideas expressed in a paper
* by Ralf Engelschall.
* For SJLJ on other systems, one would want to rewrite springboard() and
* co_create() and hack the jmb_buf stack pointer.
*/
#define LIBCO_C
#include <libco.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
sigjmp_buf context;
void (*coentry)(void);
void *stack;
} cothread_struct;
static thread_local cothread_struct co_primary;
static thread_local cothread_struct *creating, *co_running = 0;
static void springboard(int ignored)
{
if(sigsetjmp(creating->context, 0))
co_running->coentry();
}
cothread_t co_active(void)
{
if (!co_running)
co_running = &co_primary;
return (cothread_t)co_running;
}
cothread_t co_create(unsigned int size, void (*coentry)(void))
{
if(!co_running)
co_running = &co_primary;
cothread_struct *thread = (cothread_struct*)malloc(sizeof(cothread_struct));
if(thread)
{
struct sigaction handler;
struct sigaction old_handler;
stack_t stack;
stack_t old_stack;
thread->coentry = thread->stack = 0;
stack.ss_flags = 0;
stack.ss_size = size;
thread->stack = stack.ss_sp = malloc(size);
if(stack.ss_sp && !sigaltstack(&stack, &old_stack))
{
handler.sa_handler = springboard;
handler.sa_flags = SA_ONSTACK;
sigemptyset(&handler.sa_mask);
creating = thread;
if(!sigaction(SIGUSR1, &handler, &old_handler))
{
if(!raise(SIGUSR1))
thread->coentry = coentry;
sigaltstack(&old_stack, 0);
sigaction(SIGUSR1, &old_handler, 0);
}
}
if(thread->coentry != coentry)
{
co_delete(thread);
thread = 0;
}
}
return (cothread_t)thread;
}
void co_delete(cothread_t cothread)
{
if(cothread)
{
if(((cothread_struct*)cothread)->stack)
free(((cothread_struct*)cothread)->stack);
free(cothread);
}
}
void co_switch(cothread_t cothread)
{
if(!sigsetjmp(co_running->context, 0))
{
co_running = (cothread_struct*)cothread;
siglongjmp(co_running->context, 1);
}
}
#ifdef __cplusplus
}
#endif

81
libco/ucontext.c Normal file
View File

@ -0,0 +1,81 @@
/*
libco.ucontext (2008-01-28)
author: Nach
license: public domain
*/
/*
* WARNING: the overhead of POSIX ucontext is very high,
* assembly versions of libco or libco_sjlj should be much faster
*
* This library only exists for two reasons:
* 1 - as an initial test for the viability of a ucontext implementation
* 2 - to demonstrate the power and speed of libco over existing implementations,
* such as pth (which defaults to wrapping ucontext on unix targets)
*
* Use this library only as a *last resort*
*/
#define LIBCO_C
#include <libco.h>
#include <stdlib.h>
#include <ucontext.h>
#ifdef __cplusplus
extern "C" {
#endif
static thread_local ucontext_t co_primary;
static thread_local ucontext_t *co_running = 0;
cothread_t co_active(void)
{
if (!co_running)
co_running = &co_primary;
return (cothread_t)co_running;
}
cothread_t co_create(unsigned int heapsize, void (*coentry)(void))
{
if (!co_running)
co_running = &co_primary;
ucontext_t *thread = (ucontext_t*)malloc(sizeof(ucontext_t));
if(thread)
{
if((!getcontext(thread) && !(thread->uc_stack.ss_sp = 0)) && (thread->uc_stack.ss_sp = malloc(heapsize)))
{
thread->uc_link = co_running;
thread->uc_stack.ss_size = heapsize;
makecontext(thread, coentry, 0);
}
else
{
co_delete((cothread_t)thread);
thread = 0;
}
}
return (cothread_t)thread;
}
void co_delete(cothread_t cothread)
{
if (!cothread)
return;
if(((ucontext_t*)cothread)->uc_stack.ss_sp)
free(((ucontext_t*)cothread)->uc_stack.ss_sp);
free(cothread);
}
void co_switch(cothread_t cothread)
{
ucontext_t *old_thread = co_running;
co_running = (ucontext_t*)cothread;
swapcontext(old_thread, co_running);
}
#ifdef __cplusplus
}
#endif

117
libco/x86.c Normal file
View File

@ -0,0 +1,117 @@
/*
libco.x86 (2009-10-12)
author: byuu
license: public domain
*/
#define LIBCO_C
#include <libco.h>
#include <assert.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_MSC_VER)
#define fastcall __fastcall
#elif defined(__GNUC__)
#define fastcall __attribute__((fastcall))
#else
#error "libco: please define fastcall macro"
#endif
static thread_local long co_active_buffer[64];
static thread_local cothread_t co_active_handle = 0;
static void (fastcall *co_swap)(cothread_t, cothread_t) = 0;
//ABI: fastcall
static unsigned char co_swap_function[] = {
0x89, 0x22, /* mov [edx],esp */
0x8b, 0x21, /* mov esp,[ecx] */
0x58, /* pop eax */
0x89, 0x6a, 0x04, /* mov [edx+0x04],ebp */
0x89, 0x72, 0x08, /* mov [edx+0x08],esi */
0x89, 0x7a, 0x0c, /* mov [edx+0x0c],edi */
0x89, 0x5a, 0x10, /* mov [edx+0x10],ebx */
0x8b, 0x69, 0x04, /* mov ebp,[ecx+0x04] */
0x8b, 0x71, 0x08, /* mov esi,[ecx+0x08] */
0x8b, 0x79, 0x0c, /* mov edi,[ecx+0x0c] */
0x8b, 0x59, 0x10, /* mov ebx,[ecx+0x10] */
0xff, 0xe0, /* jmp eax */
};
#ifdef _WIN32
#include <windows.h>
void co_init(void)
{
DWORD old_privileges;
VirtualProtect(co_swap_function,
sizeof co_swap_function, PAGE_EXECUTE_READWRITE, &old_privileges);
}
#else
#include <unistd.h>
#include <sys/mman.h>
void co_init(void)
{
unsigned long addr = (unsigned long)co_swap_function;
unsigned long base = addr - (addr % sysconf(_SC_PAGESIZE));
unsigned long size = (addr - base) + sizeof co_swap_function;
mprotect((void*)base, size, PROT_READ | PROT_WRITE | PROT_EXEC);
}
#endif
static void crash(void)
{
assert(0); /* called only if cothread_t entrypoint returns */
}
cothread_t co_active(void)
{
if(!co_active_handle)
co_active_handle = &co_active_buffer;
return co_active_handle;
}
cothread_t co_create(unsigned int size, void (*entrypoint)(void))
{
cothread_t handle;
if(!co_swap)
{
co_init();
co_swap = (void (fastcall*)(cothread_t, cothread_t))co_swap_function;
}
if(!co_active_handle)
co_active_handle = &co_active_buffer;
size += 256; /* allocate additional space for storage */
size &= ~15; /* align stack to 16-byte boundary */
if(handle = (cothread_t)malloc(size))
{
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);
}
void co_switch(cothread_t handle)
{
register cothread_t co_previous_handle = co_active_handle;
co_swap(co_active_handle = handle, co_previous_handle);
}
#ifdef __cplusplus
}
#endif

367
libretro.c Normal file
View File

@ -0,0 +1,367 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "common.h"
#include "libco.h"
#include "libretro.h"
#ifndef MAX_PATH
#define MAX_PATH (512)
#endif
static retro_log_printf_t log_cb;
static retro_video_refresh_t video_cb;
static retro_input_poll_t input_poll_cb;
static retro_environment_t environ_cb;
struct retro_perf_callback perf_cb;
static cothread_t main_thread;
static cothread_t cpu_thread;
/* to be removed */
u32 savestate_slot = 0;
void get_savestate_filename_noshot(u32 slot, char* name_buffer)
{
(void) slot;
sprintf(name_buffer, "dummy.svs");
}
/* ------------ */
void switch_to_main_thread(void)
{
co_switch(main_thread);
}
static inline void switch_to_cpu_thread(void)
{
co_switch(cpu_thread);
}
static void cpu_thread_entry(void)
{
execute_arm_translate(execute_cycles);
execute_arm(execute_cycles);
}
static inline void init_context_switch(void)
{
main_thread = co_active();
cpu_thread = co_create(0x20000, cpu_thread_entry);
}
static inline void deinit_context_switch(void)
{
co_delete(cpu_thread);
}
#ifdef PERF_TEST
extern struct retro_perf_callback perf_cb;
#define RETRO_PERFORMANCE_INIT(X) \
static struct retro_perf_counter X = {#X}; \
do { \
if (!(X).registered) \
perf_cb.perf_register(&(X)); \
} while(0)
#define RETRO_PERFORMANCE_START(X) perf_cb.perf_start(&(X))
#define RETRO_PERFORMANCE_STOP(X) perf_cb.perf_stop(&(X))
#else
#define RETRO_PERFORMANCE_INIT(X)
#define RETRO_PERFORMANCE_START(X)
#define RETRO_PERFORMANCE_STOP(X)
#endif
void retro_get_system_info(struct retro_system_info* info)
{
info->library_name = "gpSP";
info->library_version = "v0.91";
info->need_fullpath = true;
info->block_extract = false;
info->valid_extensions = "gba|bin|agb|gbz" ;
}
void retro_get_system_av_info(struct retro_system_av_info* info)
{
info->geometry.base_width = GBA_SCREEN_WIDTH;
info->geometry.base_height = GBA_SCREEN_HEIGHT;
info->geometry.max_width = GBA_SCREEN_WIDTH;
info->geometry.max_height = GBA_SCREEN_HEIGHT;
info->geometry.aspect_ratio = 0;
// 59.72750057 hz
info->timing.fps = ((float)(16 * 1024 * 1024)) / (308 * 228 * 4);
info->timing.sample_rate = GBA_SOUND_FREQUENCY;
}
#include <sys/mman.h>
void retro_init()
{
init_gamepak_buffer();
init_sound(1);
rom_translation_cache = mmap(NULL, ROM_TRANSLATION_CACHE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
ram_translation_cache = mmap(NULL, RAM_TRANSLATION_CACHE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
bios_translation_cache = mmap(NULL, BIOS_TRANSLATION_CACHE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0);
rom_translation_ptr = rom_translation_cache;
ram_translation_ptr = ram_translation_cache;
bios_translation_ptr = bios_translation_cache;
}
void retro_deinit()
{
perf_cb.perf_log();
memory_term();
munmap(rom_translation_cache, ROM_TRANSLATION_CACHE_SIZE);
munmap(ram_translation_cache, RAM_TRANSLATION_CACHE_SIZE);
munmap(bios_translation_cache, BIOS_TRANSLATION_CACHE_SIZE);
}
void retro_set_environment(retro_environment_t cb)
{
struct retro_log_callback log;
environ_cb = cb;
if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
log_cb = log.log;
else
log_cb = NULL;
environ_cb(RETRO_ENVIRONMENT_GET_PERF_INTERFACE, &perf_cb);
}
void retro_set_video_refresh(retro_video_refresh_t cb)
{
video_cb = cb;
}
void retro_set_input_poll(retro_input_poll_t cb)
{
input_poll_cb = cb;
}
void retro_set_controller_port_device(unsigned port, unsigned device) {}
void retro_reset()
{
deinit_context_switch();
update_backup();
reset_gba();
init_context_switch();
}
size_t retro_serialize_size()
{
// return SAVESTATE_SIZE;
return 0;
}
bool retro_serialize(void* data, size_t size)
{
// if (size < SAVESTATE_SIZE)
return false;
// gba_save_state(data);
// return true;
}
bool retro_unserialize(const void* data, size_t size)
{
// if (size < SAVESTATE_SIZE)
return false;
// gba_load_state(data);
// return true;
}
void retro_cheat_reset() {}
void retro_cheat_set(unsigned index, bool enabled, const char* code) {}
void error_msg(const char* text)
{
if (log_cb)
log_cb(RETRO_LOG_ERROR, text);
}
void info_msg(const char* text)
{
if (log_cb)
log_cb(RETRO_LOG_INFO, text);
}
static void extract_directory(char* buf, const char* path, size_t size)
{
strncpy(buf, path, size - 1);
buf[size - 1] = '\0';
char* base = strrchr(buf, '/');
if (base)
*base = '\0';
else
strncpy(buf, ".", size);
}
bool retro_load_game(const struct retro_game_info* info)
{
char filename_bios[MAX_PATH];
const char* dir = NULL;
enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_RGB565;
if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
{
if (log_cb)
log_cb(RETRO_LOG_INFO, "[TempGBA]: 0RGB1555 is not supported.\n");
return false;
}
extract_directory(main_path, info->path, sizeof(main_path));
if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir)
strncpy(filename_bios, dir, sizeof(filename_bios));
else
strncpy(filename_bios, main_path, sizeof(filename_bios));
strncat(filename_bios, "/gba_bios.bin", sizeof(filename_bios));
// if (environ_cb(RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY, &dir) && dir)
// strncpy(dir_save, dir, sizeof(dir_save));
// else
// strncpy(dir_save, main_path, sizeof(dir_save));
// strncat(dir_save, "/",sizeof(dir_save));
// strncat(main_path, "/",sizeof(main_path));
if (load_bios(filename_bios) != 0)
{
error_msg("Could not load BIOS image file.\n");
return false;
}
if (bios_rom[0] != 0x18)
{
info_msg("You have an incorrect BIOS image.\n");
info_msg("While many games will work fine, some will not. It\n");
info_msg("is strongly recommended that you obtain the\n");
info_msg("correct BIOS file.\n");
}
gamepak_filename[0] = 0;
if (load_gamepak(info->path) != 0)
{
error_msg("Could not load the game file.\n");
return false;
}
reset_gba();
init_context_switch();
return true;
}
bool retro_load_game_special(unsigned game_type,
const struct retro_game_info* info, size_t num_info)
{
return false;
}
void retro_unload_game()
{
deinit_context_switch();
update_backup();
}
unsigned retro_get_region()
{
return RETRO_REGION_NTSC;
}
void* retro_get_memory_data(unsigned id)
{
// switch (id)
// {
// case RETRO_MEMORY_SAVE_RAM:
// return gamepak_backup;
// }
return 0;
}
size_t retro_get_memory_size(unsigned id)
{
// switch (id)
// {
// case RETRO_MEMORY_SAVE_RAM:
// switch(backup_type)
// {
// case BACKUP_SRAM:
// return sram_size;
// case BACKUP_FLASH:
// return flash_size;
// case BACKUP_EEPROM:
// return eeprom_size;
// case BACKUP_NONE:
// return 0x0;
// default:
// return 0x8000;
// }
// }
return 0;
}
static void check_variables(void)
{
}
void retro_run()
{
bool updated = false;
input_poll_cb();
switch_to_cpu_thread();
update_input();
render_audio();
video_cb(gba_screen_pixels, GBA_SCREEN_WIDTH, GBA_SCREEN_HEIGHT,
GBA_SCREEN_PITCH * 2);
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated)
check_variables();
}
unsigned retro_api_version()
{
return RETRO_API_VERSION;
}

1926
libretro.h Normal file

File diff suppressed because it is too large Load Diff

6
link.T Normal file
View File

@ -0,0 +1,6 @@
{
global: retro_*;
local: *;
};

27
main.c
View File

@ -18,6 +18,7 @@
*/ */
#include "common.h" #include "common.h"
#include <ctype.h>
#ifdef PSP_BUILD #ifdef PSP_BUILD
@ -213,6 +214,7 @@ void init_main()
flush_translation_cache_bios(); flush_translation_cache_bios();
} }
#ifndef __LIBRETRO__
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char bios_filename[512]; char bios_filename[512];
@ -383,6 +385,7 @@ int main(int argc, char *argv[])
#endif #endif
return 0; return 0;
} }
#endif
void print_memory_stats(u32 *counter, u32 *region_stats, char *stats_str) void print_memory_stats(u32 *counter, u32 *region_stats, char *stats_str)
{ {
@ -436,7 +439,7 @@ void trigger_ext_event()
get_savestate_filename_noshot(savestate_slot, get_savestate_filename_noshot(savestate_slot,
current_savestate_filename); current_savestate_filename);
load_state(current_savestate_filename); gba_load_state(current_savestate_filename);
switch(event_number) switch(event_number)
{ {
@ -511,8 +514,10 @@ void trigger_ext_event()
event_number++; event_number++;
} }
#ifndef __LIBRETRO__
static u32 fps = 60; static u32 fps = 60;
static u32 frames_drawn = 60; static u32 frames_drawn = 60;
#endif
u32 update_gba() u32 update_gba()
{ {
@ -624,6 +629,12 @@ u32 update_gba()
flush_ram_count = 0; flush_ram_count = 0;
#endif #endif
#ifdef __LIBRETRO__
switch_to_main_thread();
update_gbc_sound(cpu_ticks);
gbc_sound_update = 0;
#else
if(update_input()) if(update_input())
continue; continue;
@ -644,7 +655,7 @@ u32 update_gba()
if(update_backup_flag) if(update_backup_flag)
update_backup(); update_backup();
#endif
process_cheats(); process_cheats();
event_cycles++; event_cycles++;
@ -773,6 +784,8 @@ void synchronize()
*/ */
} }
#elif defined(__LIBRETRO__)
#else #else
u32 real_frame_count = 0; u32 real_frame_count = 0;
@ -870,6 +883,8 @@ void quit()
sound_exit(); sound_exit();
#ifndef __LIBRETRO__
#ifdef REGISTER_USAGE_ANALYZE #ifdef REGISTER_USAGE_ANALYZE
print_register_usage(); print_register_usage();
#endif #endif
@ -885,6 +900,8 @@ void quit()
exit(0); exit(0);
#endif #endif
#endif
} }
void reset_gba() void reset_gba()
@ -919,7 +936,7 @@ void get_ticks_us(u64 *tick_return)
#else #else
u32 file_length(char *dummy, FILE *fp) u32 file_length(const char *dummy, FILE *fp)
{ {
u32 length; u32 length;
@ -930,7 +947,9 @@ u32 file_length(char *dummy, FILE *fp)
return length; return length;
} }
#ifdef PC_BUILD #ifdef __LIBRETRO__
#elif defined(PC_BUILD)
void delay_us(u32 us_count) void delay_us(u32 us_count)
{ {

7
main.h
View File

@ -90,7 +90,12 @@ extern u32 clock_speed;
u32 update_gba(); u32 update_gba();
void reset_gba(); void reset_gba();
#ifdef __LIBRETRO__
#define synchronize()
void init_main();
#else
void synchronize(); void synchronize();
#endif
void quit(); void quit();
void delay_us(u32 us_count); void delay_us(u32 us_count);
void get_ticks_us(u64 *tick_return); void get_ticks_us(u64 *tick_return);
@ -105,7 +110,7 @@ u32 file_length(char *filename, s32 dummy);
#else #else
u32 file_length(char *dummy, FILE *fp); u32 file_length(const char *dummy, FILE *fp);
#endif #endif

View File

@ -2115,7 +2115,7 @@ s32 load_game_config(char *gamepak_title, char *gamepak_code, char *gamepak_make
return -1; return -1;
} }
s32 load_gamepak_raw(char *name) s32 load_gamepak_raw(const char *name)
{ {
file_open(gamepak_file, name, read); file_open(gamepak_file, name, read);
@ -2160,7 +2160,7 @@ char gamepak_code[5];
char gamepak_maker[3]; char gamepak_maker[3];
char gamepak_filename[512]; char gamepak_filename[512];
u32 load_gamepak(char *name) u32 load_gamepak(const char *name)
{ {
char *dot_position = strrchr(name, '.'); char *dot_position = strrchr(name, '.');
s32 file_size; s32 file_size;
@ -2197,7 +2197,9 @@ u32 load_gamepak(char *name)
gamepak_maker[2] = 0; gamepak_maker[2] = 0;
load_game_config(gamepak_title, gamepak_code, gamepak_maker); load_game_config(gamepak_title, gamepak_code, gamepak_maker);
#ifndef __LIBRETRO__
load_game_config_file(); load_game_config_file();
#endif
change_ext(gamepak_filename, cheats_filename, ".cht"); change_ext(gamepak_filename, cheats_filename, ".cht");
add_cheats(cheats_filename); add_cheats(cheats_filename);
@ -3119,6 +3121,26 @@ void init_memory()
bios_read_protect = 0xe129f000; bios_read_protect = 0xe129f000;
} }
void memory_term(void)
{
if (file_check_valid(gamepak_file_large))
{
file_close(gamepak_file_large);
}
if (gamepak_memory_map != NULL)
{
free(gamepak_memory_map);
gamepak_memory_map = NULL;
}
if (gamepak_rom != NULL)
{
free(gamepak_rom);
gamepak_rom = NULL;
}
}
void bios_region_read_allow() void bios_region_read_allow()
{ {
memory_map_read[0] = bios_rom; memory_map_read[0] = bios_rom;
@ -3138,7 +3160,7 @@ void bios_region_read_protect()
sound_##type##_savestate(savestate_file); \ sound_##type##_savestate(savestate_file); \
video_##type##_savestate(savestate_file) \ video_##type##_savestate(savestate_file) \
void load_state(char *savestate_filename) void gba_load_state(char *savestate_filename)
{ {
file_open(savestate_file, savestate_filename, read); file_open(savestate_file, savestate_filename, read);
if(file_check_valid(savestate_file)) if(file_check_valid(savestate_file))
@ -3174,7 +3196,7 @@ void load_state(char *savestate_filename)
{ {
reset_gba(); reset_gba();
// Okay, so this takes a while, but for now it works. // Okay, so this takes a while, but for now it works.
load_state(savestate_filename); gba_load_state(savestate_filename);
} }
else else
{ {
@ -3207,7 +3229,7 @@ void load_state(char *savestate_filename)
u8 savestate_write_buffer[506947]; u8 savestate_write_buffer[506947];
u8 *write_mem_ptr; u8 *write_mem_ptr;
void save_state(char *savestate_filename, u16 *screen_capture) void gba_save_state(char *savestate_filename, u16 *screen_capture)
{ {
write_mem_ptr = savestate_write_buffer; write_mem_ptr = savestate_write_buffer;
file_open(savestate_file, savestate_filename, write); file_open(savestate_file, savestate_filename, write);

View File

@ -175,20 +175,21 @@ extern char gamepak_filename[512];
cpu_alert_type dma_transfer(dma_transfer_type *dma); cpu_alert_type dma_transfer(dma_transfer_type *dma);
u8 *memory_region(u32 address, u32 *memory_limit); u8 *memory_region(u32 address, u32 *memory_limit);
u32 load_gamepak(char *name); u32 load_gamepak(const char *name);
u32 load_backup(char *name); u32 load_backup(char *name);
s32 load_bios(char *name); s32 load_bios(char *name);
void update_backup(); void update_backup();
void update_backup_force(); void update_backup_force();
void init_memory(); void init_memory();
void init_gamepak_buffer(); void init_gamepak_buffer();
void memory_term(void);
void bios_region_read_allow(); void bios_region_read_allow();
void bios_region_read_protect(); void bios_region_read_protect();
u8 *load_gamepak_page(u32 physical_index); u8 *load_gamepak_page(u32 physical_index);
void memory_write_mem_savestate(file_tag_type savestate_file); void memory_write_mem_savestate(file_tag_type savestate_file);
void memory_read_savestate(file_tag_type savestate_file); void memory_read_savestate(file_tag_type savestate_file);
void load_state(char *savestate_filename); void gba_load_state(char *savestate_filename);
void save_state(char *savestate_filename, u16 *screen_capture); void gba_save_state(char *savestate_filename, u16 *screen_capture);
extern u8 *gamepak_rom; extern u8 *gamepak_rom;
extern u32 gamepak_ram_buffer_size; extern u32 gamepak_ram_buffer_size;

55
sound.c
View File

@ -19,16 +19,24 @@
#include "common.h" #include "common.h"
#ifndef __LIBRETRO__
#include <SDL.h> #include <SDL.h>
#endif
u32 global_enable_audio = 1; u32 global_enable_audio = 1;
direct_sound_struct direct_sound_channel[2]; direct_sound_struct direct_sound_channel[2];
gbc_sound_struct gbc_sound_channel[4]; gbc_sound_struct gbc_sound_channel[4];
#ifdef __LIBRETRO__
u32 sound_frequency = GBA_SOUND_FREQUENCY;
#else
u32 sound_frequency = 44100; u32 sound_frequency = 44100;
#endif
#ifndef __LIBRETRO__
SDL_mutex *sound_mutex; SDL_mutex *sound_mutex;
static SDL_cond *sound_cv; static SDL_cond *sound_cv;
#endif
#ifdef PSP_BUILD #ifdef PSP_BUILD
u32 audio_buffer_size_number = 1; u32 audio_buffer_size_number = 1;
@ -44,7 +52,9 @@ static u32 sound_buffer_base;
static u32 sound_last_cpu_ticks; static u32 sound_last_cpu_ticks;
static fixed16_16 gbc_sound_tick_step; static fixed16_16 gbc_sound_tick_step;
#ifndef __LIBRETRO__
static u32 sound_exit_flag; static u32 sound_exit_flag;
#endif
// Queue 1, 2, or 4 samples to the top of the DS FIFO, wrap around circularly // Queue 1, 2, or 4 samples to the top of the DS FIFO, wrap around circularly
@ -447,6 +457,7 @@ void update_gbc_sound(u32 cpu_ticks)
gbc_sound_partial_ticks &= 0xFFFF; gbc_sound_partial_ticks &= 0xFFFF;
} }
#ifndef __LIBRETRO__
SDL_LockMutex(sound_mutex); SDL_LockMutex(sound_mutex);
if(synchronize_flag) if(synchronize_flag)
{ {
@ -487,6 +498,7 @@ void update_gbc_sound(u32 cpu_ticks)
} }
} }
#endif
if(sound_on == 1) if(sound_on == 1)
{ {
gs = gbc_sound_channel + 0; gs = gbc_sound_channel + 0;
@ -562,9 +574,11 @@ void update_gbc_sound(u32 cpu_ticks)
gbc_sound_buffer_index = gbc_sound_buffer_index =
(gbc_sound_buffer_index + (buffer_ticks * 2)) % BUFFER_SIZE; (gbc_sound_buffer_index + (buffer_ticks * 2)) % BUFFER_SIZE;
#ifndef __LIBRETRO__
SDL_UnlockMutex(sound_mutex); SDL_UnlockMutex(sound_mutex);
SDL_CondSignal(sound_cv); SDL_CondSignal(sound_cv);
#endif
} }
#define sound_copy_normal() \ #define sound_copy_normal() \
@ -594,8 +608,8 @@ void update_gbc_sound(u32 cpu_ticks)
source[i] = 0; \ source[i] = 0; \
} \ } \
#ifndef __LIBRETRO__
void sound_callback(void *userdata, Uint8 *stream, int length) void sound_callback(void *userdata, u8 *stream, int length)
{ {
u32 sample_length = length / 2; u32 sample_length = length / 2;
u32 _length; u32 _length;
@ -649,6 +663,7 @@ void sound_callback(void *userdata, Uint8 *stream, int length)
SDL_UnlockMutex(sound_mutex); SDL_UnlockMutex(sound_mutex);
} }
#endif
// Special thanks to blarrg for the LSFR frequency used in Meridian, as posted // Special thanks to blarrg for the LSFR frequency used in Meridian, as posted
// on the forum at http://meridian.overclocked.org: // on the forum at http://meridian.overclocked.org:
@ -689,7 +704,9 @@ void reset_sound()
gbc_sound_struct *gs = gbc_sound_channel; gbc_sound_struct *gs = gbc_sound_channel;
u32 i; u32 i;
#ifndef __LIBRETRO__
SDL_LockMutex(sound_mutex); SDL_LockMutex(sound_mutex);
#endif
sound_on = 0; sound_on = 0;
sound_buffer_base = 0; sound_buffer_base = 0;
@ -723,13 +740,16 @@ void reset_sound()
gs->active_flag = 0; gs->active_flag = 0;
} }
#ifndef __LIBRETRO__
SDL_UnlockMutex(sound_mutex); SDL_UnlockMutex(sound_mutex);
#endif
} }
void sound_exit() void sound_exit()
{ {
gbc_sound_buffer_index = gbc_sound_buffer_index =
(sound_buffer_base + audio_buffer_size) % BUFFER_SIZE; (sound_buffer_base + audio_buffer_size) % BUFFER_SIZE;
#ifndef __LIBRETRO__
SDL_PauseAudio(1); SDL_PauseAudio(1);
sound_exit_flag = 1; sound_exit_flag = 1;
SDL_CondSignal(sound_cv); SDL_CondSignal(sound_cv);
@ -739,10 +759,12 @@ void sound_exit()
sound_mutex = NULL; sound_mutex = NULL;
SDL_DestroyCond(sound_cv); SDL_DestroyCond(sound_cv);
sound_cv = NULL; sound_cv = NULL;
#endif
} }
void init_sound(int need_reset) void init_sound(int need_reset)
{ {
#ifndef __LIBRETRO__
SDL_AudioSpec sound_settings; SDL_AudioSpec sound_settings;
sound_exit_flag = 0; sound_exit_flag = 0;
@ -777,6 +799,8 @@ void init_sound(int need_reset)
audio_buffer_size_number++; audio_buffer_size_number++;
#ifndef PSP_BUILD #ifndef PSP_BUILD
printf("audio: freq %d, size %d\n", sound_frequency, audio_buffer_size); printf("audio: freq %d, size %d\n", sound_frequency, audio_buffer_size);
#endif
#endif #endif
gbc_sound_tick_step = gbc_sound_tick_step =
@ -788,7 +812,9 @@ void init_sound(int need_reset)
if (need_reset) if (need_reset)
reset_sound(); reset_sound();
#ifndef __LIBRETRO__
SDL_PauseAudio(0); SDL_PauseAudio(0);
#endif
} }
#define sound_savestate_builder(type) \ #define sound_savestate_builder(type) \
@ -811,3 +837,28 @@ void sound_##type##_savestate(file_tag_type savestate_file) \
sound_savestate_builder(read); sound_savestate_builder(read);
sound_savestate_builder(write_mem); sound_savestate_builder(write_mem);
#ifdef __LIBRETRO__
#include "libretro.h"
static retro_audio_sample_batch_t audio_batch_cb;
void retro_set_audio_sample(retro_audio_sample_t cb) { }
void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { audio_batch_cb = cb; }
void render_audio(void)
{
static s16 stream_base[512];
u32 _length;
s16 *source;
u32 i;
s32 current_sample;
while (((gbc_sound_buffer_index - sound_buffer_base) & BUFFER_SIZE_MASK) > 512) {
sound_copy(sound_buffer_base, 1024, normal);
audio_batch_cb(stream_base, 256);
sound_buffer_base += 512;
sound_buffer_base &= BUFFER_SIZE_MASK;
}
}
#endif

119
sound.h
View File

@ -20,84 +20,90 @@
#ifndef SOUND_H #ifndef SOUND_H
#define SOUND_H #define SOUND_H
#define BUFFER_SIZE 65536 #define BUFFER_SIZE (1 << 16)
#define BUFFER_SIZE_MASK (BUFFER_SIZE - 1)
#ifdef __LIBRETRO__
#define GBA_SOUND_FREQUENCY (64 * 1024)
#endif
#define GBA_XTAL 16777216.0f #define GBA_XTAL 16777216.0f
#define GBA_60HZ_RATE 16853760.0f /* 228*(272+960)*60 */ #define GBA_60HZ_RATE 16853760.0f /* 228*(272+960)*60 */
#if !defined(PSP_BUILD) #if !defined(PSP_BUILD) && !defined(__LIBRETRO__)
// run GBA at 60Hz (~0.5% faster) to better match host display // run GBA at 60Hz (~0.5% faster) to better match host display
#define GBC_BASE_RATE GBA_60HZ_RATE #define GBC_BASE_RATE GBA_60HZ_RATE
#else #else
#define GBC_BASE_RATE GBA_XTAL #define GBC_BASE_RATE GBA_XTAL
#endif #endif
typedef enum typedef enum
{ {
DIRECT_SOUND_INACTIVE, DIRECT_SOUND_INACTIVE,
DIRECT_SOUND_RIGHT, DIRECT_SOUND_RIGHT,
DIRECT_SOUND_LEFT, DIRECT_SOUND_LEFT,
DIRECT_SOUND_LEFTRIGHT DIRECT_SOUND_LEFTRIGHT
} direct_sound_status_type; } direct_sound_status_type;
typedef enum typedef enum
{ {
DIRECT_SOUND_VOLUME_50, DIRECT_SOUND_VOLUME_50,
DIRECT_SOUND_VOLUME_100 DIRECT_SOUND_VOLUME_100
} direct_sound_volume_type; } direct_sound_volume_type;
typedef struct typedef struct
{ {
s8 fifo[32]; s8 fifo[32];
u32 fifo_base; u32 fifo_base;
u32 fifo_top; u32 fifo_top;
fixed8_24 fifo_fractional; fixed8_24 fifo_fractional;
// The + 1 is to give some extra room for linear interpolation // The + 1 is to give some extra room for linear interpolation
// when wrapping around. // when wrapping around.
u32 buffer_index; u32 buffer_index;
direct_sound_status_type status; direct_sound_status_type status;
direct_sound_volume_type volume; direct_sound_volume_type volume;
u32 last_cpu_ticks; u32 last_cpu_ticks;
} direct_sound_struct; } direct_sound_struct;
typedef enum typedef enum
{ {
GBC_SOUND_INACTIVE, GBC_SOUND_INACTIVE,
GBC_SOUND_RIGHT, GBC_SOUND_RIGHT,
GBC_SOUND_LEFT, GBC_SOUND_LEFT,
GBC_SOUND_LEFTRIGHT GBC_SOUND_LEFTRIGHT
} gbc_sound_status_type; } gbc_sound_status_type;
typedef struct typedef struct
{ {
u32 rate; u32 rate;
fixed16_16 frequency_step; fixed16_16 frequency_step;
fixed16_16 sample_index; fixed16_16 sample_index;
fixed16_16 tick_counter; fixed16_16 tick_counter;
u32 total_volume; u32 total_volume;
u32 envelope_initial_volume; u32 envelope_initial_volume;
u32 envelope_volume; u32 envelope_volume;
u32 envelope_direction; u32 envelope_direction;
u32 envelope_status; u32 envelope_status;
u32 envelope_step; u32 envelope_step;
u32 envelope_ticks; u32 envelope_ticks;
u32 envelope_initial_ticks; u32 envelope_initial_ticks;
u32 sweep_status; u32 sweep_status;
u32 sweep_direction; u32 sweep_direction;
u32 sweep_ticks; u32 sweep_ticks;
u32 sweep_initial_ticks; u32 sweep_initial_ticks;
u32 sweep_shift; u32 sweep_shift;
u32 length_status; u32 length_status;
u32 length_ticks; u32 length_ticks;
u32 noise_type; u32 noise_type;
u32 wave_type; u32 wave_type;
u32 wave_bank; u32 wave_bank;
u32 wave_volume; u32 wave_volume;
gbc_sound_status_type status; gbc_sound_status_type status;
u32 active_flag; u32 active_flag;
u32 master_enable; u32 master_enable;
s8 *sample_data; s8* sample_data;
} gbc_sound_struct; } gbc_sound_struct;
extern direct_sound_struct direct_sound_channel[2]; extern direct_sound_struct direct_sound_channel[2];
@ -116,7 +122,9 @@ extern u32 global_enable_audio;
extern u32 enable_low_pass_filter; extern u32 enable_low_pass_filter;
extern u32 audio_buffer_size_number; extern u32 audio_buffer_size_number;
extern SDL_mutex *sound_mutex; #ifndef __LIBRETRO__
extern SDL_mutex* sound_mutex;
#endif
void sound_timer_queue8(u32 channel, u8 value); void sound_timer_queue8(u32 channel, u8 value);
void sound_timer_queue16(u32 channel, u16 value); void sound_timer_queue16(u32 channel, u16 value);
@ -128,6 +136,11 @@ void init_sound(int need_reset);
void sound_write_mem_savestate(file_tag_type savestate_file); void sound_write_mem_savestate(file_tag_type savestate_file);
void sound_read_savestate(file_tag_type savestate_file); void sound_read_savestate(file_tag_type savestate_file);
#ifdef __LIBRETRO__
void render_audio(void);
#endif
#ifdef IN_MEMORY_C #ifdef IN_MEMORY_C
#define gbc_sound_tone_control_low(channel, address) \ #define gbc_sound_tone_control_low(channel, address) \

15
video.c
View File

@ -86,8 +86,13 @@ static void Ge_Finish_Callback(int id, void *arg)
#define get_screen_pitch() \ #define get_screen_pitch() \
screen_pitch \ screen_pitch \
#else #elif defined(__LIBRETRO__)
u16 gba_screen_pixels[GBA_SCREEN_PITCH * GBA_SCREEN_HEIGHT];
#define get_screen_pixels() gba_screen_pixels
#define get_screen_pitch() GBA_SCREEN_PITCH
#else
SDL_Surface *screen; SDL_Surface *screen;
const u32 video_scale = 1; const u32 video_scale = 1;
@ -3303,7 +3308,7 @@ void flip_screen()
} }
} }
#else #elif !defined(__LIBRETRO__)
#define integer_scale_copy_2() \ #define integer_scale_copy_2() \
current_scanline_ptr[x2] = current_pixel; \ current_scanline_ptr[x2] = current_pixel; \
@ -3381,6 +3386,7 @@ void flip_screen()
#endif #endif
#ifndef __LIBRETRO__
u32 frame_to_render; u32 frame_to_render;
void update_screen() void update_screen()
@ -3388,6 +3394,7 @@ void update_screen()
if(!skip_next_frame) if(!skip_next_frame)
flip_screen(); flip_screen();
} }
#endif
#ifdef PSP_BUILD #ifdef PSP_BUILD
@ -3476,7 +3483,7 @@ void init_video()
GE_CMD(NOP, 0); GE_CMD(NOP, 0);
} }
#else #elif !defined(__LIBRETRO__)
void init_video() void init_video()
{ {
@ -3593,7 +3600,7 @@ void clear_screen(u16 color)
sceGuSync(0, 0); */ sceGuSync(0, 0); */
} }
#else #elif !defined(__LIBRETRO__)
void video_resolution_large() void video_resolution_large()
{ {

View File

@ -21,7 +21,9 @@
#define VIDEO_H #define VIDEO_H
void update_scanline(); void update_scanline();
#ifndef __LIBRETRO__
void update_screen(); void update_screen();
#endif
void init_video(); void init_video();
void video_resolution_large(); void video_resolution_large();
void video_resolution_small(); void video_resolution_small();
@ -103,4 +105,8 @@ extern video_filter_type2 screen_filter2;
void set_gba_resolution(video_scale_type scale); void set_gba_resolution(video_scale_type scale);
#ifdef __LIBRETRO__
extern u16 gba_screen_pixels[GBA_SCREEN_PITCH * GBA_SCREEN_HEIGHT];
#endif
#endif #endif

View File

@ -8,35 +8,53 @@ STRIP = strip
AS = as AS = as
PREFIX = /usr PREFIX = /usr
OBJS = main.o cpu.o memory.o video.o input.o sound.o \ OBJS = ../main.o ../cpu.o ../memory.o ../video.o ../input.o ../sound.o \
cpu_threaded.o gui.o x86_stub.o cheats.o zip.o ../cpu_threaded.o ../gui.o x86_stub.o ../cheats.o ../zip.o
BIN ?= gpsp.exe
# Platform specific definitions # Platform specific definitions
VPATH += .. ifeq ($(shell uname -a),)
EXE_EXT = .exe
else ifneq ($(findstring MINGW,$(shell uname -a)),)
EXE_EXT = .exe
else
EXE_EXT =
endif
BIN ?= gpsp$(EXE_EXT)
CFLAGS += -DPC_BUILD -Wall -m32 CFLAGS += -DPC_BUILD -Wall -m32
INCLUDES = -I${PREFIX}/include `sdl-config --cflags` INCLUDES = -I$(PREFIX)/include `sdl-config --cflags`
LIBS = -L${PREFIX}/lib `sdl-config --libs` -lz -m32 LIBS = -L$(PREFIX)/lib32 `sdl-config --libs` -lz -m32
# Compilation: # Compilation:
.SUFFIXES: .c .S ifeq ($(DEBUG), 1)
OPTIMIZE := -O0 -g
OPTIMIZE_SAFE := -O0 -g
else
OPTIMIZE := -O3
OPTIMIZE_SAFE := -O2
endif
all: ${BIN} all: $(BIN)
%.o: %.c %.o: %.c
${CC} ${CFLAGS} ${INCLUDES} -c -o $@ $< $(CC) $(CFLAGS) $(OPTIMIZE) $(INCLUDES) -c -o $@ $<
%.o: %.S %.o: %.S
${CC} ${CFLAGS} -c -o $@ $< $(CC) $(CFLAGS) $(OPTIMIZE) -c -o $@ $<
cpu.o cpu_threaded.o: CFLAGS += -Wno-unused-variable -Wno-unused-label ../cpu.o: ../cpu.c
$(CC) -c -o $@ $< $(CFLAGS) -Wno-unused-variable -Wno-unused-label $(OPTIMIZE_SAFE) $(INCLUDES)
${BIN}: ${OBJS} ../cpu_threaded.o: ../cpu_threaded.c
${CC} ${OBJS} ${LIBS} -o ${BIN} $(CC) -c -o $@ $< $(CFLAGS) -Wno-unused-variable -Wno-unused-label $(OPTIMIZE_SAFE) $(INCLUDES)
# ${STRIP} ${BIN}
$(BIN): $(OBJS)
$(CC) $(OBJS) $(LIBS) -o $(BIN)
clean: clean:
rm -f *.o ${BIN} rm -f $(OBJS) $(BIN)

2
zip.c
View File

@ -43,7 +43,7 @@ struct SZIPFileHeader
s16 ExtraFieldLength; s16 ExtraFieldLength;
} __attribute__((packed)); } __attribute__((packed));
u32 load_file_zip(char *filename) u32 load_file_zip(const char *filename)
{ {
struct SZIPFileHeader data; struct SZIPFileHeader data;
char tmp[1024]; char tmp[1024];

2
zip.h
View File

@ -20,7 +20,7 @@
#ifndef ZIP_H #ifndef ZIP_H
#define ZIP_H #define ZIP_H
u32 load_file_zip(char *filename); u32 load_file_zip(const char *filename);
#endif #endif