Merge branch 'master' into qt

This commit is contained in:
Jeffrey Pfau 2014-02-10 23:59:12 -08:00
commit c5d243fca2
15 changed files with 503 additions and 81 deletions

View File

@ -31,6 +31,13 @@ else()
source_group("POSIX-specific code" FILES ${OS_SRC})
endif()
if(BUILD_BBB OR BUILD_RASPI)
enable_language(ASM)
if(NOT BUILD_EGL)
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5)
endif()
endif()
set(DEBUGGER_SRC "${CMAKE_SOURCE_DIR}/src/debugger/debugger.c;${CMAKE_SOURCE_DIR}/src/debugger/memory-debugger.c")
if(USE_CLI_DEBUGGER)

View File

@ -1,13 +1,8 @@
#include "gdb-stub.h"
#include <errno.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
enum GDBError {
GDB_NO_ERROR = 0x00,
@ -50,15 +45,12 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas
static void _gdbStubPoll(struct ARMDebugger* debugger) {
struct GDBStub* stub = (struct GDBStub*) debugger;
int flags;
while (stub->d.state == DEBUGGER_PAUSED) {
if (stub->connection >= 0) {
flags = fcntl(stub->connection, F_GETFL);
if (flags == -1) {
if (!SocketSetBlocking(stub->connection, 1)) {
GDBStubHangup(stub);
return;
}
fcntl(stub->connection, F_SETFL, flags & ~O_NONBLOCK);
}
GDBStubUpdate(stub);
}
@ -66,7 +58,7 @@ static void _gdbStubPoll(struct ARMDebugger* debugger) {
static void _ack(struct GDBStub* stub) {
char ack = '+';
send(stub->connection, &ack, 1, 0);
SocketSend(stub->connection, &ack, 1);
}
static void _nak(struct GDBStub* stub) {
@ -74,7 +66,7 @@ static void _nak(struct GDBStub* stub) {
if (stub->d.log) {
stub->d.log(&stub->d, DEBUGGER_LOG_WARN, "Packet error");
}
send(stub->connection, &nak, 1, 0);
SocketSend(stub->connection, &nak, 1);
}
static uint32_t _hex2int(const char* hex, int maxDigits) {
@ -155,7 +147,7 @@ static void _sendMessage(struct GDBStub* stub) {
if (stub->d.log) {
stub->d.log(&stub->d, DEBUGGER_LOG_DEBUG, "> %s", stub->outgoing);
}
send(stub->connection, stub->outgoing, i + 3, 0);
SocketSend(stub->connection, stub->outgoing, i + 3);
}
static void _error(struct GDBStub* stub, enum GDBError error) {
@ -171,12 +163,10 @@ static void _writeHostInfo(struct GDBStub* stub) {
static void _continue(struct GDBStub* stub, const char* message) {
stub->d.state = DEBUGGER_RUNNING;
if (stub->connection >= 0) {
int flags = fcntl(stub->connection, F_GETFL);
if (flags == -1) {
if (!SocketSetBlocking(stub->connection, 0)) {
GDBStubHangup(stub);
return;
}
fcntl(stub->connection, F_SETFL, flags | O_NONBLOCK);
}
// TODO: parse message
(void) (message);
@ -445,34 +435,20 @@ int GDBStubListen(struct GDBStub* stub, int port, uint32_t bindAddress) {
GDBStubShutdown(stub);
}
// TODO: support IPv6
stub->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
stub->socket = SocketOpenTCP(port, bindAddress);
if (stub->socket < 0) {
if (stub->d.log) {
stub->d.log(&stub->d, DEBUGGER_LOG_ERROR, "Couldn't open socket");
}
return 0;
}
struct sockaddr_in bindInfo = {
.sin_family = AF_INET,
.sin_port = htons(port),
.sin_addr = {
.s_addr = htonl(bindAddress)
}
};
int err = bind(stub->socket, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in));
int err = SocketListen(stub->socket, 1);
if (err) {
goto cleanup;
}
err = listen(stub->socket, 1);
if (err) {
if (!SocketSetBlocking(stub->socket, 0)) {
goto cleanup;
}
int flags = fcntl(stub->socket, F_GETFL);
if (flags == -1) {
goto cleanup;
}
fcntl(stub->socket, F_SETFL, flags | O_NONBLOCK);
return 1;
@ -480,14 +456,14 @@ cleanup:
if (stub->d.log) {
stub->d.log(&stub->d, DEBUGGER_LOG_ERROR, "Couldn't listen on port");
}
close(stub->socket);
SocketClose(stub->socket);
stub->socket = -1;
return 0;
}
void GDBStubHangup(struct GDBStub* stub) {
if (stub->connection >= 0) {
close(stub->connection);
SocketClose(stub->connection);
stub->connection = -1;
}
if (stub->d.state == DEBUGGER_PAUSED) {
@ -498,7 +474,7 @@ void GDBStubHangup(struct GDBStub* stub) {
void GDBStubShutdown(struct GDBStub* stub) {
GDBStubHangup(stub);
if (stub->socket >= 0) {
close(stub->socket);
SocketClose(stub->socket);
stub->socket = -1;
}
}
@ -508,13 +484,11 @@ void GDBStubUpdate(struct GDBStub* stub) {
return;
}
if (stub->connection == -1) {
stub->connection = accept(stub->socket, 0, 0);
stub->connection = SocketAccept(stub->socket, 0, 0);
if (stub->connection >= 0) {
int flags = fcntl(stub->connection, F_GETFL);
if (flags == -1) {
if (!SocketSetBlocking(stub->connection, 0)) {
goto connectionLost;
}
fcntl(stub->connection, F_SETFL, flags | O_NONBLOCK);
ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED);
} else if (errno == EWOULDBLOCK || errno == EAGAIN) {
return;
@ -523,7 +497,7 @@ void GDBStubUpdate(struct GDBStub* stub) {
}
}
while (1) {
ssize_t messageLen = recv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1, 0);
ssize_t messageLen = SocketRecv(stub->connection, stub->line, GDB_STUB_MAX_LINE - 1);
if (messageLen == 0) {
goto connectionLost;
}

View File

@ -2,6 +2,7 @@
#define GDB_STUB_H
#include "debugger.h"
#include "socket.h"
#define GDB_STUB_MAX_LINE 1200
@ -19,8 +20,8 @@ struct GDBStub {
char outgoing[GDB_STUB_MAX_LINE];
enum GDBStubAckState lineAck;
int socket;
int connection;
Socket socket;
Socket connection;
};
void GDBStubCreate(struct GDBStub*);

View File

@ -1,6 +1,7 @@
#include "gba-io.h"
#include "gba-serialize.h"
#include "gba-sio.h"
#include "gba-video.h"
static const int _isValidRegister[REG_MAX >> 1] = {
@ -89,7 +90,7 @@ static const int _isSpecialRegister[REG_MAX >> 1] = {
void GBAIOInit(struct GBA* gba) {
gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
gba->memory.io[REG_RCNT >> 1] = 0x8000;
gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL;
gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
gba->memory.io[REG_SOUNDBIAS >> 1] = 0x200;
}
@ -254,6 +255,18 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
GBATimerWriteTMCNT_HI(gba, 3, value);
break;
// SIO
case REG_SIOCNT:
GBASIOWriteSIOCNT(&gba->sio, value);
break;
case REG_RCNT:
value &= 0xC1FF;
GBASIOWriteRCNT(&gba->sio, value);
break;
case REG_SIOMLT_SEND:
GBASIOWriteSIOMLT_SEND(&gba->sio, value);
break;
// Interrupts and misc
case REG_WAITCNT:
GBAAdjustWaitstates(&gba->memory, value);
@ -369,6 +382,11 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
}
break;
case REG_SIOCNT:
return gba->sio.siocnt;
case REG_RCNT:
return gba->sio.rcnt;
case REG_DMA0CNT_LO:
case REG_DMA1CNT_LO:
case REG_DMA2CNT_LO:
@ -400,6 +418,11 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
case REG_DMA1CNT_HI:
case REG_DMA2CNT_HI:
case REG_DMA3CNT_HI:
case REG_SIOMULTI0:
case REG_SIOMULTI1:
case REG_SIOMULTI2:
case REG_SIOMULTI3:
case REG_SIOMLT_SEND:
case REG_IE:
case REG_IF:
case REG_WAITCNT:

139
src/gba/gba-sio.c Normal file
View File

@ -0,0 +1,139 @@
#include "gba-sio.h"
#include "gba-io.h"
#include <limits.h>
static struct GBASIODriver* _lookupDriver(struct GBASIO* sio, enum GBASIOMode mode) {
switch (mode) {
case SIO_NORMAL_8:
case SIO_NORMAL_32:
return sio->drivers.normal;
case SIO_MULTI:
return sio->drivers.multiplayer;
case SIO_JOYBUS:
return sio->drivers.joybus;
default:
return 0;
}
}
static void _switchMode(struct GBASIO* sio) {
int mode = ((sio->rcnt >> 14) & 0xC) | ((sio->siocnt >> 12) & 0x3);
enum GBASIOMode oldMode = sio->mode;
if (mode < 8) {
sio->mode = (enum GBASIOMode) (mode & 0x3);
} else {
sio->mode = (enum GBASIOMode) (mode & 0xC);
}
if (oldMode != mode) {
if (sio->activeDriver && sio->activeDriver->unload) {
sio->activeDriver->unload(sio->activeDriver);
}
sio->activeDriver = _lookupDriver(sio, mode);
if (sio->activeDriver && sio->activeDriver->load) {
sio->activeDriver->load(sio->activeDriver);
}
}
}
void GBASIOInit(struct GBASIO* sio) {
sio->rcnt = RCNT_INITIAL;
sio->siocnt = 0;
_switchMode(sio);
}
void GBASIODeinit(struct GBASIO* sio) {
if (sio->drivers.multiplayer && sio->drivers.multiplayer->deinit) {
sio->drivers.multiplayer->deinit(sio->drivers.multiplayer);
}
if (sio->drivers.joybus && sio->drivers.joybus->deinit) {
sio->drivers.joybus->deinit(sio->drivers.joybus);
}
}
void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers) {
if (drivers->normal) {
GBASIOSetDriver(sio, drivers->normal, SIO_NORMAL_8);
}
if (drivers->multiplayer) {
GBASIOSetDriver(sio, drivers->multiplayer, SIO_MULTI);
}
if (drivers->joybus) {
GBASIOSetDriver(sio, drivers->multiplayer, SIO_JOYBUS);
}
}
void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode) {
struct GBASIODriver** driverLoc;
switch (mode) {
case SIO_NORMAL_8:
case SIO_NORMAL_32:
driverLoc = &sio->drivers.normal;
break;
case SIO_MULTI:
driverLoc = &sio->drivers.multiplayer;
break;
case SIO_JOYBUS:
driverLoc = &sio->drivers.joybus;
break;
default:
GBALog(sio->p, GBA_LOG_ERROR, "Setting an unsupported SIO driver: %x", mode);
return;
}
if (*driverLoc) {
if ((*driverLoc)->unload) {
(*driverLoc)->unload(*driverLoc);
}
if ((*driverLoc)->deinit) {
(*driverLoc)->deinit(*driverLoc);
}
}
if (driver) {
driver->p = sio;
if (driver->init) {
if (!driver->init(driver)) {
driver->deinit(driver);
GBALog(sio->p, GBA_LOG_ERROR, "Could not initialize SIO driver");
return;
}
}
if (sio->mode == mode) {
sio->activeDriver = driver;
if (driver->load) {
driver->load(driver);
}
}
}
*driverLoc = driver;
}
void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value) {
sio->rcnt = value;
_switchMode(sio);
if (sio->activeDriver && sio->activeDriver->writeRegister) {
sio->activeDriver->writeRegister(sio->activeDriver, REG_RCNT, value);
}
}
void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value) {
if (sio->activeDriver && sio->activeDriver->writeRegister) {
value = sio->activeDriver->writeRegister(sio->activeDriver, REG_SIOCNT, value);
}
sio->siocnt = value;
_switchMode(sio);
}
void GBASIOWriteSIOMLT_SEND(struct GBASIO* sio, uint16_t value) {
if (sio->activeDriver && sio->activeDriver->writeRegister) {
sio->activeDriver->writeRegister(sio->activeDriver, REG_SIOMLT_SEND, value);
}
}
int32_t GBASIOProcessEvents(struct GBASIO* sio, int32_t cycles) {
if (sio->activeDriver && sio->activeDriver->processEvents) {
return sio->activeDriver->processEvents(sio->activeDriver, cycles);
}
return INT_MAX;
}

89
src/gba/gba-sio.h Normal file
View File

@ -0,0 +1,89 @@
#ifndef GBA_SIO_H
#define GBA_SIO_H
#include <stdint.h>
enum GBASIOMode {
SIO_NORMAL_8 = 0,
SIO_NORMAL_32 = 1,
SIO_MULTI = 2,
SIO_UART = 3,
SIO_GPIO = 8,
SIO_JOYBUS = 12
};
enum {
RCNT_INITIAL = 0x8000
};
struct GBASIO;
struct GBASIODriver {
struct GBASIO* p;
int (*init)(struct GBASIODriver* driver);
void (*deinit)(struct GBASIODriver* driver);
int (*load)(struct GBASIODriver* driver);
int (*unload)(struct GBASIODriver* driver);
int (*writeRegister)(struct GBASIODriver* driver, uint32_t address, uint16_t value);
int32_t (*processEvents)(struct GBASIODriver* driver, int32_t cycles);
};
struct GBASIODriverSet {
struct GBASIODriver* normal;
struct GBASIODriver* multiplayer;
struct GBASIODriver* joybus;
};
struct GBASIO {
struct GBA* p;
enum GBASIOMode mode;
struct GBASIODriverSet drivers;
struct GBASIODriver* activeDriver;
uint16_t rcnt;
union {
struct {
unsigned sc : 1;
unsigned internalSc : 1;
unsigned si : 1;
unsigned idleSo : 1;
unsigned : 4;
unsigned start : 1;
unsigned : 3;
unsigned length : 1;
unsigned : 1;
unsigned irq : 1;
unsigned : 1;
} normalControl;
struct {
unsigned baud : 2;
unsigned slave : 1;
unsigned ready : 1;
unsigned id : 2;
unsigned error : 1;
unsigned busy : 1;
unsigned : 6;
unsigned irq : 1;
unsigned : 1;
} multiplayerControl;
uint16_t siocnt;
};
};
void GBASIOInit(struct GBASIO* sio);
void GBASIODeinit(struct GBASIO* sio);
void GBASIOSetDriverSet(struct GBASIO* sio, struct GBASIODriverSet* drivers);
void GBASIOSetDriver(struct GBASIO* sio, struct GBASIODriver* driver, enum GBASIOMode mode);
void GBASIOWriteRCNT(struct GBASIO* sio, uint16_t value);
void GBASIOWriteSIOCNT(struct GBASIO* sio, uint16_t value);
void GBASIOWriteSIOMLT_SEND(struct GBASIO* sio, uint16_t value);
int32_t GBASIOProcessEvents(struct GBASIO* sio, int32_t cycles);
#endif

View File

@ -37,6 +37,12 @@ static void _changeState(struct GBAThread* threadContext, enum ThreadState newSt
MutexUnlock(&threadContext->stateMutex);
}
static void _waitOnInterrupt(struct GBAThread* threadContext) {
while (threadContext->state == THREAD_INTERRUPTED) {
ConditionWait(&threadContext->stateCond, &threadContext->stateMutex);
}
}
static THREAD_ENTRY _GBAThreadRun(void* context) {
#ifdef USE_PTHREADS
pthread_once(&_contextOnce, _createTLS);
@ -99,6 +105,8 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
ARMDebuggerEnter(threadContext->debugger, DEBUGGER_ENTER_ATTACHED);
}
GBASIOSetDriverSet(&gba.sio, &threadContext->sioDrivers);
gba.keySource = &threadContext->activeKeys;
if (threadContext->startCallback) {
@ -120,7 +128,7 @@ static THREAD_ENTRY _GBAThreadRun(void* context) {
}
}
MutexLock(&threadContext->stateMutex);
while (threadContext->state == THREAD_PAUSED) {
while (threadContext->state == THREAD_PAUSED || threadContext->state == THREAD_INTERRUPTED) {
ConditionWait(&threadContext->stateCond, &threadContext->stateMutex);
}
MutexUnlock(&threadContext->stateMutex);
@ -237,9 +245,25 @@ void GBAThreadJoin(struct GBAThread* threadContext) {
free(threadContext->rewindBuffer);
}
void GBAThreadInterrupt(struct GBAThread* threadContext) {
MutexLock(&threadContext->stateMutex);
_waitOnInterrupt(threadContext);
threadContext->savedState = threadContext->state;
threadContext->state = THREAD_INTERRUPTED;
if (threadContext->debugger && threadContext->debugger->state == DEBUGGER_RUNNING) {
threadContext->debugger->state = DEBUGGER_EXITING;
}
MutexUnlock(&threadContext->stateMutex);
}
void GBAThreadContinue(struct GBAThread* threadContext) {
_changeState(threadContext, threadContext->savedState, 1);
}
void GBAThreadPause(struct GBAThread* threadContext) {
int frameOn = 1;
MutexLock(&threadContext->stateMutex);
_waitOnInterrupt(threadContext);
if (threadContext->state == THREAD_RUNNING) {
if (threadContext->debugger && threadContext->debugger->state == DEBUGGER_RUNNING) {
threadContext->debugger->state = DEBUGGER_EXITING;
@ -259,6 +283,7 @@ void GBAThreadPause(struct GBAThread* threadContext) {
void GBAThreadUnpause(struct GBAThread* threadContext) {
int frameOn = 1;
MutexLock(&threadContext->stateMutex);
_waitOnInterrupt(threadContext);
if (threadContext->state == THREAD_PAUSED) {
threadContext->state = THREAD_RUNNING;
ConditionWake(&threadContext->stateCond);
@ -275,6 +300,7 @@ void GBAThreadUnpause(struct GBAThread* threadContext) {
int GBAThreadIsPaused(struct GBAThread* threadContext) {
int isPaused;
MutexLock(&threadContext->stateMutex);
_waitOnInterrupt(threadContext);
isPaused = threadContext->state == THREAD_PAUSED;
MutexUnlock(&threadContext->stateMutex);
return isPaused;
@ -283,6 +309,7 @@ int GBAThreadIsPaused(struct GBAThread* threadContext) {
void GBAThreadTogglePause(struct GBAThread* threadContext) {
int frameOn = 1;
MutexLock(&threadContext->stateMutex);
_waitOnInterrupt(threadContext);
if (threadContext->state == THREAD_PAUSED) {
threadContext->state = THREAD_RUNNING;
ConditionWake(&threadContext->stateCond);

View File

@ -10,9 +10,10 @@ typedef void (*ThreadCallback)(struct GBAThread* threadContext);
enum ThreadState {
THREAD_INITIALIZED = -1,
THREAD_RUNNING = 0,
THREAD_PAUSED = 1,
THREAD_EXITING = 2,
THREAD_SHUTDOWN = 3
THREAD_INTERRUPTED = 1,
THREAD_PAUSED = 2,
THREAD_EXITING = 3,
THREAD_SHUTDOWN = 4
};
struct GBASync {
@ -36,6 +37,7 @@ struct GBAThread {
// Input
struct GBAVideoRenderer* renderer;
struct GBASIODriverSet sioDrivers;
struct ARMDebugger* debugger;
int fd;
int biosFd;
@ -48,6 +50,7 @@ struct GBAThread {
Mutex stateMutex;
Condition stateCond;
enum ThreadState savedState;
GBALogHandler logHandler;
ThreadCallback startCallback;
@ -70,6 +73,9 @@ int GBAThreadHasStarted(struct GBAThread* threadContext);
void GBAThreadEnd(struct GBAThread* threadContext);
void GBAThreadJoin(struct GBAThread* threadContext);
void GBAThreadInterrupt(struct GBAThread* threadContext);
void GBAThreadContinue(struct GBAThread* threadContext);
void GBAThreadPause(struct GBAThread* threadContext);
void GBAThreadUnpause(struct GBAThread* threadContext);
int GBAThreadIsPaused(struct GBAThread* threadContext);

View File

@ -2,6 +2,7 @@
#include "gba-bios.h"
#include "gba-io.h"
#include "gba-sio.h"
#include "gba-thread.h"
#include "memory.h"
@ -122,6 +123,9 @@ void GBAInit(struct GBA* gba) {
GBAIOInit(gba);
gba->sio.p = gba;
GBASIOInit(&gba->sio);
gba->timersEnabled = 0;
memset(gba->timers, 0, sizeof(gba->timers));
@ -195,6 +199,11 @@ static void GBAProcessEvents(struct ARMBoard* board) {
nextEvent = testEvent;
}
testEvent = GBASIOProcessEvents(&gbaBoard->p->sio, cycles);
if (testEvent < nextEvent) {
nextEvent = testEvent;
}
board->cpu->cycles -= cycles;
board->cpu->nextEvent = nextEvent;
} while (board->cpu->cycles >= board->cpu->nextEvent);
@ -444,10 +453,6 @@ void GBATimerWriteTMCNT_HI(struct GBA* gba, int timer, uint16_t control) {
};
void GBAWriteIE(struct GBA* gba, uint16_t value) {
if (value & (1 << IRQ_SIO)) {
GBALog(gba, GBA_LOG_STUB, "SIO interrupts not implemented");
}
if (value & (1 << IRQ_KEYPAD)) {
GBALog(gba, GBA_LOG_STUB, "Keypad interrupts not implemented");
}

View File

@ -7,6 +7,7 @@
#include "gba-memory.h"
#include "gba-video.h"
#include "gba-audio.h"
#include "gba-sio.h"
#include <stdarg.h>
@ -74,6 +75,7 @@ struct GBA {
struct GBAMemory memory;
struct GBAVideo video;
struct GBAAudio audio;
struct GBASIO sio;
struct GBASync* sync;

View File

@ -1,4 +1,19 @@
find_package(SDL 1.2 REQUIRED)
set(SDL_VERSION "2" CACHE STRING "Version of SDL to use (1.2 or 2)")
if (SDL_VERSION EQUAL "2")
include(FindPkgConfig)
pkg_search_module(SDL2 sdl2)
if (SDL2_FOUND)
set(SDL_INCLUDE_DIR ${SDL2_INCLUDE_DIRS})
set(SDL_LIBRARY ${SDL2_LIBRARIES})
set(SDLMAIN_LIBRARY "")
endif()
endif()
if(SDL_VERSION EQUAL "1.2" OR NOT SDL2_FOUND)
find_package(SDL 1.2 REQUIRED)
endif()
file(GLOB PLATFORM_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sdl-*.c)
set(PLATFORM_LIBRARY "${SDL_LIBRARY};${SDLMAIN_LIBRARY}")
include_directories(${CMAKE_SOURCE_DIR}/src/platform/sdl)
@ -9,8 +24,6 @@ if(BUILD_RASPI AND BUILD_EGL)
set(OPENGL_INCLUDE_DIR "")
add_definitions(-DBUILD_RASPI)
elseif(BUILD_BBB OR BUILD_RASPI)
enable_language(ASM)
add_definitions(-DCOLOR_16_BIT -DCOLOR_5_6_5)
set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/sw-main.c)
else()
set(MAIN_SRC ${CMAKE_SOURCE_DIR}/src/platform/sdl/gl-main.c)

View File

@ -22,6 +22,9 @@ struct GLSoftwareRenderer {
struct GBAVideoSoftwareRenderer d;
struct GBASDLAudio audio;
struct GBASDLEvents events;
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Window* window;
#endif
int viewportWidth;
int viewportHeight;
@ -105,15 +108,38 @@ static int _GBASDLInit(struct GLSoftwareRenderer* renderer) {
GBASDLInitEvents(&renderer->events);
GBASDLInitAudio(&renderer->audio);
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
#else
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
#endif
#ifndef COLOR_16_BIT
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
#else
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
#ifdef COLOR_5_6_5
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
#else
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
#endif
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
#endif
#if SDL_VERSION_ATLEAST(2, 0, 0)
renderer->window = SDL_CreateWindow("GBAc", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, renderer->viewportWidth, renderer->viewportHeight, SDL_WINDOW_OPENGL);
SDL_GL_CreateContext(renderer->window);
SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
renderer->events.window = renderer->window;
renderer->events.fullscreen = 0;
#else
#ifdef COLOR_16_BIT
SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 16, SDL_OPENGL);
#else
SDL_SetVideoMode(renderer->viewportWidth, renderer->viewportHeight, 32, SDL_OPENGL);
#endif
#endif
renderer->d.outputBuffer = malloc(256 * 256 * 4);
@ -158,10 +184,20 @@ static void _GBASDLRunloop(struct GBAThread* context, struct GLSoftwareRenderer*
}
}
GBASyncWaitFrameEnd(&context->sync);
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_GL_SwapWindow(renderer->window);
#else
SDL_GL_SwapBuffers();
#endif
while (SDL_PollEvent(&event)) {
GBASDLHandleEvent(context, &event);
int fullscreen = renderer->events.fullscreen;
GBASDLHandleEvent(context, &renderer->events, &event);
// Event handling can change the size of the screen
if (renderer->events.fullscreen != fullscreen) {
SDL_GetWindowSize(renderer->window, &renderer->viewportWidth, &renderer->viewportHeight);
glViewport(0, 0, renderer->viewportWidth, renderer->viewportHeight);
}
}
}
}
@ -171,6 +207,9 @@ static void _GBASDLDeinit(struct GLSoftwareRenderer* renderer) {
GBASDLDeinitEvents(&renderer->events);
GBASDLDeinitAudio(&renderer->audio);
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_DestroyWindow(renderer->window);
#endif
SDL_Quit();
}

View File

@ -5,13 +5,21 @@
#include "gba-serialize.h"
#include "gba-video.h"
#if SDL_VERSION_ATLEAST(2, 0, 0) && defined(__APPLE__)
#define GUI_MOD KMOD_GUI
#else
#define GUI_MOD KMOD_CTRL
#endif
int GBASDLInitEvents(struct GBASDLEvents* context) {
if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0) {
return 0;
}
SDL_JoystickEventState(SDL_ENABLE);
context->joystick = SDL_JoystickOpen(0);
#if !SDL_VERSION_ATLEAST(2, 0, 0)
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
#endif
return 1;
}
@ -45,9 +53,8 @@ static void _pauseAfterFrame(struct GBAThread* context) {
GBAThreadPause(context);
}
static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_KeyboardEvent* event) {
static void _GBASDLHandleKeypress(struct GBAThread* context, struct GBASDLEvents* sdlContext, const struct SDL_KeyboardEvent* event) {
enum GBAKey key = 0;
int isPaused = GBAThreadIsPaused(context);
switch (event->keysym.sym) {
case SDLK_z:
key = GBA_KEY_A;
@ -83,22 +90,25 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_Ke
if (event->type == SDL_KEYDOWN && context->debugger) {
ARMDebuggerEnter(context->debugger, DEBUGGER_ENTER_MANUAL);
}
break;
return;
case SDLK_TAB:
context->sync.audioWait = event->type != SDL_KEYDOWN;
return;
case SDLK_LEFTBRACKET:
if (!isPaused) {
GBAThreadPause(context);
}
GBAThreadInterrupt(context);
GBARewind(context, 10);
if (!isPaused) {
GBAThreadUnpause(context);
}
GBAThreadContinue(context);
return;
default:
if (event->type == SDL_KEYDOWN) {
if (event->keysym.mod & KMOD_CTRL) {
if (event->keysym.mod & GUI_MOD) {
switch (event->keysym.sym) {
#if SDL_VERSION_ATLEAST(2, 0, 0)
case SDLK_f:
SDL_SetWindowFullscreen(sdlContext->window, sdlContext->fullscreen ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
sdlContext->fullscreen = !sdlContext->fullscreen;
break;
#endif
case SDLK_p:
GBAThreadTogglePause(context);
break;
@ -123,13 +133,9 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_Ke
case SDLK_F8:
case SDLK_F9:
case SDLK_F10:
if (!isPaused) {
GBAThreadPause(context);
}
GBAThreadInterrupt(context);
GBASaveState(context->gba, event->keysym.sym - SDLK_F1);
if (!isPaused) {
GBAThreadUnpause(context);
}
GBAThreadContinue(context);
break;
default:
break;
@ -146,13 +152,9 @@ static void _GBASDLHandleKeypress(struct GBAThread* context, const struct SDL_Ke
case SDLK_F8:
case SDLK_F9:
case SDLK_F10:
if (!isPaused) {
GBAThreadPause(context);
}
GBAThreadInterrupt(context);
GBALoadState(context->gba, event->keysym.sym - SDLK_F1);
if (!isPaused) {
GBAThreadUnpause(context);
}
GBAThreadContinue(context);
break;
default:
break;
@ -203,7 +205,7 @@ static void _GBASDLHandleJoyHat(struct GBAThread* context, const struct SDL_JoyH
context->activeKeys |= key;
}
void GBASDLHandleEvent(struct GBAThread* context, const union SDL_Event* event) {
void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLEvents* sdlContext, const union SDL_Event* event) {
switch (event->type) {
case SDL_QUIT:
// FIXME: this isn't thread-safe
@ -217,7 +219,7 @@ void GBASDLHandleEvent(struct GBAThread* context, const union SDL_Event* event)
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
_GBASDLHandleKeypress(context, &event->key);
_GBASDLHandleKeypress(context, sdlContext, &event->key);
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:

View File

@ -7,12 +7,18 @@
struct GBASDLEvents {
SDL_Joystick* joystick;
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Window* window;
int fullscreen;
#endif
};
int GBASDLInitEvents(struct GBASDLEvents*);
void GBASDLDeinitEvents(struct GBASDLEvents*);
void GBASDLHandleEvent(struct GBAThread* context, const union SDL_Event* event);
void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLEvents* sdlContext, const union SDL_Event* event);
enum GBAKey GBASDLMapButtonToKey(int button);
enum GBAKey GBASDLMapButtonToKey(int button);

89
src/util/socket.h Normal file
View File

@ -0,0 +1,89 @@
#ifndef SOCKET_H
#define SOCKET_H
#ifdef _WIN32
#include <winsock2.h>
typedef SOCKET Socket;
#else
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
typedef int Socket;
#endif
static inline void SocketSubsystemInitialize() {
#ifdef _WIN32
WSAStartup(MAKEWORD(2, 2), 0);
#endif
}
static inline ssize_t SocketSend(Socket socket, const void* buffer, size_t size) {
return write(socket, buffer, size);
}
static inline ssize_t SocketRecv(Socket socket, void* buffer, size_t size) {
return read(socket, buffer, size);
}
static inline Socket SocketOpenTCP(int port, uint32_t bindAddress) {
Socket sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
return sock;
}
struct sockaddr_in bindInfo = {
.sin_family = AF_INET,
.sin_port = htons(port),
.sin_addr = {
.s_addr = htonl(bindAddress)
}
};
int err = bind(sock, (const struct sockaddr*) &bindInfo, sizeof(struct sockaddr_in));
if (err) {
close(sock);
return -1;
}
return sock;
}
static inline Socket SocketListen(Socket socket, int queueLength) {
return listen(socket, queueLength);
}
static inline Socket SocketAccept(Socket socket, struct sockaddr* restrict address, socklen_t* restrict addressLength) {
return accept(socket, address, addressLength);
}
static inline int SocketClose(Socket socket) {
return close(socket) >= 0;
}
static inline int SocketSetBlocking(Socket socket, int blocking) {
#ifdef _WIN32
blocking = !blocking;
return ioctlsocket(socket, FIONBIO, &blocking) == NO_ERROR;
#else
int flags = fcntl(socket, F_GETFL);
if (flags == -1) {
return 0;
}
if (blocking) {
flags &= ~O_NONBLOCK;
} else {
flags |= O_NONBLOCK;
}
return fcntl(socket, F_SETFL, flags) >= 0;
#endif
}
static inline int SocketSetTCPPush(Socket socket, int push) {
return setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*) &push, sizeof(int)) >= 0;
}
#endif