Add a bunch of #ifdefs to keep things working as expected on linux

This commit is contained in:
Tyler Wilding
2020-09-03 22:24:50 -04:00
parent f68f220e5b
commit ef09eb12c8
26 changed files with 336 additions and 419 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
name: Linux Workflow
on: [push]
on: [push, pull_request]
jobs:
build:
+6 -6
View File
@@ -4,10 +4,8 @@ project(jak)
set(CMAKE_CXX_STANDARD 14)
# optimization level can be set here. Note that game/ overwrites this for building game C++ code.
set(CMAKE_CXX_FLAGS "-O3 -ggdb /EHsc")
# Set default compile flags for GCC
# optimization level can be set here. Note that game/ overwrites this for building game C++ code.
if(CMAKE_COMPILER_IS_GNUCXX)
message(STATUS "GCC detected, adding compile flags")
set(CMAKE_CXX_FLAGS
@@ -23,13 +21,15 @@ if(CMAKE_COMPILER_IS_GNUCXX)
-Wredundant-decls
-Wshadow
-Wsign-promo")
else()
set(CMAKE_CXX_FLAGS "/EHsc")
endif(CMAKE_COMPILER_IS_GNUCXX)
IF (WIN32)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
ENDIF()
# includes relative to top level jak-project folder
+3 -3
View File
@@ -1,9 +1,8 @@
# We define our own compilation flags here.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-O3 -ggdb")
# Set default compile flags for GCC
# optimization level can be set here. Note that game/ overwrites this for building game C++ code.
if(CMAKE_COMPILER_IS_GNUCXX)
message(STATUS "GCC detected, adding compile flags")
set(CMAKE_CXX_FLAGS
@@ -19,10 +18,11 @@ if(CMAKE_COMPILER_IS_GNUCXX)
-Wredundant-decls
-Wshadow
-Wsign-promo")
else()
set(CMAKE_CXX_FLAGS "/EHsc")
endif(CMAKE_COMPILER_IS_GNUCXX)
enable_language(ASM_NASM)
#set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS} asm)
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
set_source_files_properties(kernel/asm_funcs.asm PROPERTIES COMPILE_FLAGS "-g")
+15 -2
View File
@@ -4,7 +4,6 @@
* DONE!
*/
#include <io.h>
#include <cstring>
#include "common/common_types.h"
#include "game/sce/libscf.h"
@@ -13,7 +12,14 @@
#include "kscheme.h"
#include "ksocket.h"
#include "klisten.h"
#ifdef _WIN32
#include "Windows.h"
#include <io.h>
#elif __linux__
#include <unistd.h>
#endif
using namespace ee;
// Level to load on boot
@@ -128,14 +134,21 @@ void KernelCheckAndDispatch() {
// dispatch the kernel
//(**kernel_dispatcher)();
call_goal(Ptr<Function>(kernel_dispatcher->value), 0, 0, 0, s7.offset, g_ee_main_mem);
//ClearPending();
// TODO-WINDOWS
#ifdef __linux__
ClearPending();
#endif
// if the listener function changed, it means the kernel ran it, so we should notify compiler.
if (MasterDebug && ListenerFunction->value != old_listener) {
SendAck();
}
#ifdef _WIN32
Sleep(1000); // todo - remove this
#elif __linux__
usleep(1000);
#endif
}
}
+8 -13
View File
@@ -1,6 +1,3 @@
/*
/*!
* @file kdsnetm.cpp
* Low-level DECI2 wrapper for ksocket
@@ -30,10 +27,12 @@ void kdsnetm_init_globals() {
protoBlock.reset();
}
// TODO-WINDOWS
#ifdef __linux__
/*!
* Register GOAL DECI2 Protocol Driver with DECI2 service
* DONE, EXACT
*/
void InitGoalProto() {
protoBlock.socket = sceDeci2Open(DECI2_PROTOCOL, &protoBlock, GoalProtoHandler);
if (protoBlock.socket < 0) {
@@ -49,12 +48,10 @@ void InitGoalProto() {
}
}
*/
/*!
* Close the DECI2 Protocol Driver
* DONE, EXACT
*/
void ShutdownGoalProto() {
if (protoBlock.socket > 0) {
sceDeci2Close(protoBlock.socket);
@@ -65,7 +62,7 @@ void ShutdownGoalProto() {
* Handle a DECI2 Protocol Event for the GOAL Proto.
* Called by the DECI2 Protocol driver
* DONE, added print statements on errors for debugging, EI and SYNC at the end were removed
*/
void GoalProtoHandler(int event, int param, void* opt) {
// verify we got the correct opt pointer. It's not clear why the opt pointer is used
// like this?
@@ -165,7 +162,7 @@ void GoalProtoHandler(int event, int param, void* opt) {
* Will block until send is complete.
* DONE, original version used an uncached address and had a FlushCache call, which were both
* removed
*/
s32 SendFromBufferD(s32 msg_kind, u64 p2, char* data, s32 size) {
// wait for send to finish or error first...
while (protoBlock.send_status > 0) {
@@ -220,11 +217,9 @@ s32 SendFromBufferD(s32 msg_kind, u64 p2, char* data, s32 size) {
/*!
* Print GOAL Protocol status
*/
void GoalProtoStatus() {
Msg(6, "gproto: got %d %d\n", protoBlock.most_recent_event, protoBlock.most_recent_param);
Msg(6, "gproto: %d %d\n", protoBlock.last_receive_size, protoBlock.send_remaining);
}
*/
#endif
+6 -2
View File
@@ -51,17 +51,21 @@ extern GoalProtoBlock protoBlock;
*/
void kdsnetm_init_globals();
// TODO-WINDOWS
#ifdef __linux__
/*!
* Register GOAL DECI2 Protocol Driver with DECI2 service
* DONE, EXACT
*/
//void InitGoalProto();
void InitGoalProto();
/*!
* Close the DECI2 Protocol Driver
* DONE, EXACT
*/
//void ShutdownGoalProto();
void ShutdownGoalProto();
#endif
/*!
* Handle a DECI2 Protocol Event for the GOAL Proto.
+11 -5
View File
@@ -71,7 +71,10 @@ void ClearPending() {
Ptr<char> msg = OutputBufArea.cast<char>() + sizeof(GoalMessageHeader);
auto size = strlen(msg.c());
// note - if size is ever greater than 2^16 this will cause an issue.
// SendFromBuffer(msg.c(), size);
// TODO-WINDOWS
#ifdef __linux__
SendFromBuffer(msg.c(), size);
#endif
clear_output();
}
@@ -84,7 +87,10 @@ void ClearPending() {
if (send_size > 64000) {
send_size = 64000;
}
// SendFromBufferD(2, 0, msg, send_size);
// TODO-WINDOWS
#ifdef __linux__
SendFromBufferD(2, 0, msg, send_size);
#endif
size -= send_size;
msg += send_size;
}
@@ -103,9 +109,9 @@ void ClearPending() {
*/
void SendAck() {
if (MasterDebug) {
// SendFromBufferD(u16(ListenerMessageKind::MSG_ACK), protoBlock.msg_id,
// AckBufArea + sizeof(GoalMessageHeader),
// strlen(AckBufArea + sizeof(GoalMessageHeader)));
#ifdef __linux__
SendFromBufferD(u16(ListenerMessageKind::MSG_ACK), protoBlock.msg_id, AckBufArea + sizeof(GoalMessageHeader), strlen(AckBufArea + sizeof(GoalMessageHeader)));
#endif
}
}
+9 -3
View File
@@ -153,7 +153,7 @@ void InitCD() {
/*!
* Initialize the I/O Processor
* Removed calls to exit(0) if loading modules fails.
* Removed calls to exit(0) if loading modules fails.
*/
void InitIOP() {
// before doing anything with the I/O Processor, we need to set up SIF RPC
@@ -329,7 +329,10 @@ int InitMachine() {
// }
if (MasterDebug) { // connect to GOAL compiler
// InitGoalProto();
// TODO-WINDOWS
#ifdef __linux__
InitGoalProto();
#endif
}
printf("InitSound\n");
@@ -359,7 +362,10 @@ int ShutdownMachine() {
StopIOP();
CloseListener();
ShutdownSound();
// ShutdownGoalProto();
// TODO-WINDOWS
#ifdef __linux__
ShutdownGoalProto();
#endif
Msg(6, "kernel: machine shutdown");
return 0;
}
+1 -1
View File
@@ -1,6 +1,6 @@
/*!
* @file kmemcard.cpp
* Memory card interfaces. Very messy code.
* Memory card interface. Very messy code.
*/
//#include "ps2/SCE_MC.h"
+1 -1
View File
@@ -1,6 +1,6 @@
/*!
* @file kmemcard.h
* Memory card interfaces. Very messy code.
* Memory card interface. Very messy code.
*/
#ifndef JAK_KMEMCARD_H
+4 -6
View File
@@ -13,8 +13,6 @@ constexpr u32 DEBUG_OUTPUT_BUFFER_SIZE = 0x80000;
constexpr u32 DEBUG_PRINT_BUFFER_SIZE = 0x200000;
constexpr u32 PRINT_BUFFER_SIZE = 0x2000;
#define __attribute__(A) /* do nothing */
///////////
// SDATA
///////////
@@ -67,25 +65,25 @@ void output_segment_load(const char* name, Ptr<u8> link_block, u32 flags);
/*!
* Print to the GOAL print buffer from C
*/
void cprintf(const char* format, ...) __attribute__((format(printf, 1, 2)));
void cprintf(const char* format, ...);
/*!
* Print directly to the C stdout
* The "k" parameter is ignored, so this is just like printf
*/
void Msg(s32 k, const char* format, ...) __attribute__((format(printf, 2, 3)));
void Msg(s32 k, const char* format, ...);
/*!
* Print directly to the C stdout
* This is identical to Msg.
*/
void MsgWarn(const char* format, ...) __attribute__((format(printf, 1, 2)));
void MsgWarn(const char* format, ...);
/*!
* Print directly to the C stdout
* This is identical to Msg.
*/
void MsgErr(const char* format, ...) __attribute__((format(printf, 1, 2)));
void MsgErr(const char* format, ...);
/*!
* Reverse string in place.
+1 -3
View File
@@ -318,8 +318,6 @@ u64 make_string_from_c(const char* c_str) {
* creates a function object on the global heap.
*
* The implementation is to create a simple trampoline function which jumps to the C function.
*
*
*/
Ptr<Function> make_function_from_c(void* func) {
// allocate a function object on the global heap
@@ -1804,7 +1802,7 @@ s32 InitHeapAndSymbol() {
// setup deci2count for message counter.
protoBlock.deci2count = intern_from_c("*deci-count*").cast<s32>();
// load stuff for the listener interfaces
// load stuff for the listener interface
InitListener();
// Do final initialization, including loading and initializing the engine.
+6 -3
View File
@@ -52,14 +52,17 @@ u32 ReceiveToBuffer(char* buff) {
return msg_size;
}
// TODO-WINDOWS
#ifdef __linux__
/*!
* Do a DECI2 send and block until it is complete.
* The message type is OUTPUT
* DONE, EXACT
*/
//s32 SendFromBuffer(char* buff, s32 size) {
// return SendFromBufferD(u16(ListenerMessageKind::MSG_OUTPUT), 0, buff, size);
s32 SendFromBuffer(char* buff, s32 size) {
return SendFromBufferD(u16(ListenerMessageKind::MSG_OUTPUT), 0, buff, size);
}
#endif
/*!
* Just prepare the Ack buffer, doesn't actually connect.
+3 -4
View File
@@ -73,6 +73,7 @@ void fake_iso_init_globals() {
//! will hold prefix for the source folder.
static const char* next_dir = nullptr;
static const char* fake_iso_path = nullptr;
/*!
* Initialize the file system.
@@ -98,7 +99,7 @@ int FS_Init(u8* buffer) {
rewind(fp);
char* fakeiso = (char*)malloc(len);
if (fread(fakeiso, len, 1, fp) != 1) {
assert(true);
assert(false);
}
// loop over lines
@@ -192,7 +193,7 @@ FileRecord* FS_FindIN(const char* iso_name) {
static const char* get_file_path(FileRecord* fr) {
assert(fr->location < fake_iso_entry_count);
static char path_buffer[1024];
strcpy(path_buffer, "C:\\Users\\Shalen\\Documents\\GitHub\\jak-project\\");
strcpy(path_buffer, next_dir);
strcat(path_buffer, fake_iso_entries[fr->location].file_path);
return path_buffer;
}
@@ -344,7 +345,6 @@ uint32_t FS_LoadMusic(char* name, void* buffer) {
(void)name;
(void)buffer;
assert(false);
return 0;
}
// TODO FS_LoadSoundBank
@@ -352,5 +352,4 @@ uint32_t FS_LoadSoundBank(char* name, void* buffer) {
(void)name;
(void)buffer;
assert(false);
return 0;
}
+56 -51
View File
@@ -3,10 +3,15 @@
* Setup and launcher for the runtime.
*/
#ifdef __linux__
#include <unistd.h>
#include <sys/mman.h>
#elif _WIN32
#include <io.h>
#include <third-party/mman/mman.h>
#include <cstring>
#include <Windows.h>
#endif
#include <cstring>
#include "runtime.h"
#include "system/SystemThread.h"
@@ -40,8 +45,9 @@
u8* g_ee_main_mem = nullptr;
/*!
* runtime.cpp - Deci2Listener has been disabled for now, pending rewriting for Windows.
*/
* TODO-WINDOWS
* runtime.cpp - Deci2Listener has been disabled for now, pending rewriting for Windows.
*/
namespace {
@@ -49,49 +55,45 @@ namespace {
* SystemThread function for running the DECI2 communication with the GOAL compiler.
*/
void deci2_runner(SystemThreadInterface& interfaces) {
interfaces.initialization_complete();
while (true) {
// TODO-WINDOWS
#ifdef __linux__
// callback function so the server knows when to give up and shutdown
std::function<bool()> shutdown_callback = [&]() { return interface.get_want_exit(); };
// create and register server
Deci2Server server(shutdown_callback);
ee::LIBRARY_sceDeci2_register(&server);
// now its ok to continue with initialization
interface.initialization_complete();
// in our own thread, wait for the EE to register the first protocol driver
printf("[DECI2] waiting for EE to register protos\n");
server.wait_for_protos_ready();
// then allow the server to accept connections
if (!server.init()) {
throw std::runtime_error("DECI2 server init failed");
}
// // callback function so the server knows when to give up and shutdown
// std::function<bool()> shutdown_callback = [&]() { return interfaces.get_want_exit(); };
//
// // create and register server
//// Deci2Server server(shutdown_callback);
//// ee::LIBRARY_sceDeci2_register(&server);
//
// // now its ok to continue with initialization
// interfaces.initialization_complete();
//
// // in our own thread, wait for the EE to register the first protocol driver
// printf("[DECI2] waiting for EE to register protos\n");
// server.wait_for_protos_ready();
// // then allow the server to accept connections
// if (!server.init()) {
// throw std::runtime_error("DECI2 server init failed");
// }
//
// printf("[DECI2] waiting for listener...\n");
// bool saw_listener = false;
// while (!interfaces.get_want_exit()) {
// if (server.check_for_listener()) {
// if (!saw_listener) {
// printf("[DECI2] Connected!\n");
// }
// saw_listener = true;
// // we have a listener, run!
// server.run();
// } else {
// // no connection yet. Do a sleep so we don't spam checking the listener.
// Sleep(1000);
// }
// }
printf("[DECI2] waiting for listener...\n");
bool saw_listener = false;
while (!interface.get_want_exit()) {
if (server.check_for_listener()) {
if (!saw_listener) {
printf("[DECI2] Connected!\n");
}
saw_listener = true;
// we have a listener, run!
server.run();
} else {
// no connection yet. Do a sleep so we don't spam checking the listener.
usleep(50000);
}
}
#endif
}
// EE System
constexpr int EE_MAIN_MEM_SIZE = 128 * (1 << 20); // 128 MB, same as PS2 TOOL
constexpr u64 EE_MAIN_MEM_MAP = 0x2000000000; // intentionally > 32-bit to catch pointer bugs
@@ -108,7 +110,7 @@ constexpr int GOAL_ARGC = 4;
/*!
* SystemThread Function for the EE (PS2 Main CPU)
*/
void ee_runner(SystemThreadInterface& interfaces) {
void ee_runner(SystemThreadInterface& iface) {
// Allocate Main RAM. Must have execute enabled.
if (EE_MEM_LOW_MAP) {
g_ee_main_mem =
@@ -122,7 +124,7 @@ void ee_runner(SystemThreadInterface& interfaces) {
if (g_ee_main_mem == (u8*)(-1)) {
printf(" Failed to initialize main memory! %s\n", strerror(errno));
interfaces.initialization_complete();
iface.initialization_complete();
return;
}
@@ -131,7 +133,7 @@ void ee_runner(SystemThreadInterface& interfaces) {
(double)EE_MAIN_MEM_SIZE / (1 << 20));
printf("[EE] Initialization complete!\n");
interfaces.initialization_complete();
iface.initialization_complete();
printf("[EE] Run!\n");
memset((void*)g_ee_main_mem, 0, EE_MAIN_MEM_SIZE);
@@ -158,13 +160,13 @@ void ee_runner(SystemThreadInterface& interfaces) {
munmap(g_ee_main_mem, EE_MAIN_MEM_SIZE);
// after main returns, trigger a shutdown.
interfaces.trigger_shutdown();
iface.trigger_shutdown();
}
/*!
* SystemThread function for running the IOP (separate I/O Processor)
*/
void iop_runner(SystemThreadInterface& interfaces) {
void iop_runner(SystemThreadInterface& iface) {
IOP iop;
printf("\n\n\n[IOP] Restart!\n");
iop.reset_allocator();
@@ -187,7 +189,7 @@ void iop_runner(SystemThreadInterface& interfaces) {
// ssound
// stream
interfaces.initialization_complete();
iface.initialization_complete();
printf("[IOP] Wait for OVERLORD to be started...\n");
iop.wait_for_overlord_start_cmd();
@@ -208,7 +210,7 @@ void iop_runner(SystemThreadInterface& interfaces) {
iop.signal_overlord_init_finish();
// IOP Kernel loop
while (!interfaces.get_want_exit() && !iop.want_exit) {
while (!iface.get_want_exit() && !iop.want_exit) {
// the IOP kernel just runs at full blast, so we only run the IOP when the EE is waiting on the
// IOP. Each time the EE is waiting on the IOP, it will run an iteration of the IOP kernel.
iop.wait_run_iop();
@@ -233,7 +235,10 @@ void exec_runtime(int argc, char** argv) {
// step 1: sce library prep
iop::LIBRARY_INIT();
ee::LIBRARY_INIT_sceCd();
//ee::LIBRARY_INIT_sceDeci2();
// TODO-WINDOWS
#ifdef __linux__
ee::LIBRARY_INIT_sceDeci2();
#endif
ee::LIBRARY_INIT_sceSif();
// step 2: system prep
@@ -246,7 +251,7 @@ void exec_runtime(int argc, char** argv) {
iop_thread.start(iop_runner);
ee_thread.start(ee_runner);
deci_thread.start(deci2_runner);
// step 4: wait for EE to signal a shutdown, which will cause the DECI thread to join.
deci_thread.join();
// DECI has been killed, shutdown!
@@ -257,4 +262,4 @@ void exec_runtime(int argc, char** argv) {
// join and exit
tm.join();
printf("GOAL Runtime Shutdown\n");
}
}
+96 -69
View File
@@ -12,47 +12,59 @@
namespace ee {
namespace {
// constexpr int MAX_DECI2_PROTOCOLS = 4;
// Deci2Driver protocols[MAX_DECI2_PROTOCOLS]; // info for each deci2 protocol registered
// int protocol_count; // number of registered protocols
// Deci2Driver* sending_driver; // currently sending protocol driver
//::Deci2Server* server; // the server to send data to
// TODO-WINDOWS
#ifdef __linux__
constexpr int MAX_DECI2_PROTOCOLS = 4;
Deci2Driver protocols[MAX_DECI2_PROTOCOLS]; // info for each deci2 protocol registered
int protocol_count; // number of registered protocols
Deci2Driver* sending_driver; // currently sending protocol driver
::Deci2Server* server; // the server to send data to
#endif
} // namespace
/*
* Initialize the library.
*/
void LIBRARY_INIT_sceDeci2() {
// // reset protocols
// for (auto& p : protocols) {
// p = Deci2Driver();
// }
// protocol_count = 0;
// server = nullptr;
// sending_driver = nullptr;
// TODO-WINDOWS
#ifdef __linux__
// reset protocols
for (auto& p : protocols) {
p = Deci2Driver();
}
protocol_count = 0;
server = nullptr;
sending_driver = nullptr;
#endif
}
/*!
* Run any pending requested sends.
*/
void LIBRARY_sceDeci2_run_sends() {
return;
// for (auto& prot : protocols) {
// if (prot.active && prot.pending_send == 'H') {
// sending_driver = &prot;
// (prot.handler)(DECI2_WRITE, 0, prot.opt);
// sending_driver = nullptr;
// prot.pending_send = 0;
// (prot.handler)(DECI2_WRITEDONE, 0, prot.opt);
// }
//}
// TODO-WINDOWS
#ifdef __linux__
for (auto& prot : protocols) {
if (prot.active && prot.pending_send == 'H') {
sending_driver = &prot;
(prot.handler)(DECI2_WRITE, 0, prot.opt);
sending_driver = nullptr;
prot.pending_send = 0;
(prot.handler)(DECI2_WRITEDONE, 0, prot.opt);
}
}
#endif
}
/*!
* Register a Deci2Server with this library.
*/
void LIBRARY_sceDeci2_register(::Deci2Server* s) {
// server = s;
// TODO-WINDOWS
#ifdef __linux__
server = s;
#endif
}
/*!
@@ -61,34 +73,40 @@ void LIBRARY_sceDeci2_register(::Deci2Server* s) {
* I don't know why it's like this.
*/
s32 sceDeci2Open(u16 protocol, void* opt, void (*handler)(s32 event, s32 param, void* opt)) {
// server->lock();
// Deci2Driver drv;
// drv.protocol = protocol;
// drv.opt = opt;
// drv.handler = handler;
// drv.id = protocol_count + 1;
// drv.active = true;
// protocols[protocol_count++] = drv;
// printf("[DECI2] Add new protocol driver %d for 0x%x\n", drv.id, drv.protocol);
// server->unlock();
// TODO-WINDOWS
#ifdef __linux__
server->lock();
Deci2Driver drv;
drv.protocol = protocol;
drv.opt = opt;
drv.handler = handler;
drv.id = protocol_count + 1;
drv.active = true;
protocols[protocol_count++] = drv;
printf("[DECI2] Add new protocol driver %d for 0x%x\n", drv.id, drv.protocol);
server->unlock();
// if (protocol_count == 1) {
// // if we have our first protocol, inform the server we are ready to receive!
// // then the server will accept incoming data.
// server->send_proto_ready(protocols, &protocol_count);
//}
if (protocol_count == 1) {
// if we have our first protocol, inform the server we are ready to receive!
// then the server will accept incoming data.
server->send_proto_ready(protocols, &protocol_count);
}
// return drv.id;
return drv.id;
#elif _WIN32
return 0;
#endif
}
/*!
* Deactivate a DECI2 protocol by socket descriptor.
*/
s32 sceDeci2Close(s32 s) {
// assert(s - 1 < protocol_count);
// protocols[s - 1].active = false;
// return 1;
// TODO-WINDOWS
#ifdef __linux__
assert(s - 1 < protocol_count);
protocols[s - 1].active = false;
#endif
return 1;
}
@@ -96,10 +114,12 @@ s32 sceDeci2Close(s32 s) {
* Start a send.
*/
s32 sceDeci2ReqSend(s32 s, char dest) {
// assert(s - 1 < protocol_count);
// auto& proto = protocols[s - 1];
// proto.pending_send = dest;
// return 0;
// TODO-WINDOWS
#ifdef __linux__
assert(s - 1 < protocol_count);
auto& proto = protocols[s - 1];
proto.pending_send = dest;
#endif
return 0;
}
@@ -108,35 +128,42 @@ s32 sceDeci2ReqSend(s32 s, char dest) {
* Returns after data is copied.
*/
s32 sceDeci2ExRecv(s32 s, void* buf, u16 len) {
// assert(s - 1 < protocol_count);
// protocols[s - 1].recv_size = len;
// auto avail = protocols[s - 1].available_to_receive;
// if (len <= avail) {
// memcpy(buf, protocols[s - 1].recv_buffer, len);
// return len;
//} else {
// printf("[DECI2] Error: ExRecv %d, only %d available!\n", len, avail);
// return -1;
//}
// TODO-WINDOWS
#ifdef __linux__
assert(s - 1 < protocol_count);
protocols[s - 1].recv_size = len;
auto avail = protocols[s - 1].available_to_receive;
if (len <= avail) {
memcpy(buf, protocols[s - 1].recv_buffer, len);
return len;
} else {
printf("[DECI2] Error: ExRecv %d, only %d available!\n", len, avail);
return -1;
}
#elif _WIN32
return 0;
#endif
}
/*!
* Do a send.
*/
s32 sceDeci2ExSend(s32 s, void* buf, u16 len) {
// assert(s - 1 < protocol_count);
// if (!sending_driver) {
// printf("sceDeci2ExSend called at illegal time!\n");
// }
//
// if (&protocols[s - 1] != sending_driver) {
// printf("sceDeci2ExSend called with the wrong socket!\n");
// }
//
// server->send_data(buf, len);
// return len;
return 0;
}
// TODO-WINDOWS
#ifdef __linux__
assert(s - 1 < protocol_count);
if (!sending_driver) {
printf("sceDeci2ExSend called at illegal time!\n");
}
if (&protocols[s - 1] != sending_driver) {
printf("sceDeci2ExSend called with the wrong socket!\n");
}
server->send_data(buf, len);
return len;
#elif _WIN32
return 0;
#endif
}
} // namespace ee
+19 -14
View File
@@ -2,8 +2,14 @@
* @file Deci2Server.cpp
* Basic implementation of a DECI2 server.
* Works with deci2.cpp (sceDeci2) to implement the networking on target
*/
// TODO-WINDOWS
#ifdef __linux__
#include <sys/socket.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <cstdio>
#include <Winsock2.h>
#include <io.h>
@@ -42,7 +48,7 @@ Deci2Server::~Deci2Server() {
/*!
* Start waiting for the Listener to connect
*/
bool Deci2Server::init() {
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
@@ -51,7 +57,7 @@ bool Deci2Server::init() {
}
const char opt = 1;
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST, &opt, sizeof(opt))) {
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
printf("[Deci2Server] Failed to setsockopt 1\n");
close(server_fd);
server_fd = -1;
@@ -59,7 +65,7 @@ bool Deci2Server::init() {
}
const char one = 1;
if (setsockopt(server_fd, SOL_SOCKET, TCP_NODELAY, &one, sizeof(one))) {
if (setsockopt(server_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) {
printf("[Deci2Server] Failed to setsockopt 2\n");
close(server_fd);
server_fd = -1;
@@ -104,7 +110,7 @@ bool Deci2Server::init() {
/*!
* Return true if the listener is connected.
*/
bool Deci2Server::check_for_listener() {
if (server_connected) {
if (accept_thread_running) {
@@ -119,7 +125,7 @@ bool Deci2Server::check_for_listener() {
/*!
* Send data from buffer. User must provide appropriate headers.
*/
void Deci2Server::send_data(void* buf, u16 len) {
lock();
if (!server_connected) {
@@ -140,14 +146,14 @@ void Deci2Server::send_data(void* buf, u16 len) {
/*!
* Lock the DECI mutex. Should be done before modifying protocols.
*/
void Deci2Server::lock() {
deci_mutex.lock();
}
/*!
* Unlock the DECI mutex. Should be done after modifying protocols.
*/
void Deci2Server::unlock() {
deci_mutex.unlock();
}
@@ -155,7 +161,7 @@ void Deci2Server::unlock() {
/*!
* Wait for protocols to become ready.
* This avoids the case where we receive messages before protocol handlers are set up.
*/
void Deci2Server::wait_for_protos_ready() {
if (protocols_ready)
return;
@@ -168,7 +174,7 @@ void Deci2Server::wait_for_protos_ready() {
* Will unblock wait_for_protos_ready and incoming messages will be dispatched to these
* protocols. You can change the protocol handlers, but you should lock the mutex before
* doing so.
*/
void Deci2Server::send_proto_ready(Deci2Driver* drivers, int* driver_count) {
lock();
d2_drivers = drivers;
@@ -250,18 +256,17 @@ void Deci2Server::run() {
/*!
* Background thread for waiting for the listener.
*/
void Deci2Server::accept_thread_func() {
socklen_t l = sizeof(addr);
while (!kill_accept_thread) {
new_sock = accept(server_fd, (sockaddr*)&addr, &l);
if (new_sock >= 0) {
const char versions = {versions::GOAL_VERSION_MAJOR};
u32 versions[2] = {versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR};
send(new_sock, &versions, 8, 0); // todo, check result?
server_connected = true;
return;
}
}
}
*/
#endif
+3 -3
View File
@@ -2,8 +2,9 @@
* @file Deci2Server.h
* Basic implementation of a DECI2 server.
* Works with deci2.cpp (sceDeci2) to implement the networking on target
*/
#ifdef __linux__
#ifndef JAK1_DECI2SERVER_H
#define JAK1_DECI2SERVER_H
@@ -51,5 +52,4 @@ class Deci2Server {
};
#endif // JAK1_DECI2SERVER_H
*/
#endif
+35 -2
View File
@@ -71,8 +71,8 @@ void SystemThreadManager::join() {
*/
void* bootstrap_thread_func(void* x) {
SystemThread* thd = (SystemThread*)x;
SystemThreadInterface interfaces(thd);
thd->function(interfaces);
SystemThreadInterface interface(thd);
thd->function(interface);
printf("[SYSTEM] Thread %s is returning\n", thd->name.c_str());
return nullptr;
}
@@ -135,3 +135,36 @@ bool SystemThreadInterface::get_want_exit() const {
void SystemThreadInterface::trigger_shutdown() {
thread.manager->shutdown();
}
// TODO-Windows
#ifdef __linux__
#include <sys/time.h>
#include <sys/resource.h>
/*!
* Get thread performance statistics and report them.
*/
void SystemThreadInterface::report_perf_stats() {
if (thread.stat_diff_timer.getMs() > 16.f) {
thread.stat_diff_timer.start();
uint64_t current_ns = thread.stats_timer.getNs();
rusage stats;
getrusage(RUSAGE_THREAD, &stats);
uint64_t current_kernel = stats.ru_stime.tv_usec + (1000000 * stats.ru_stime.tv_sec);
uint64_t current_user = stats.ru_utime.tv_usec + (1000000 * stats.ru_utime.tv_sec);
uint64_t ns_dt = current_ns - thread.last_collection_nanoseconds;
uint64_t dt_kernel = current_kernel - thread.last_cpu_kernel;
uint64_t dt_user = current_user - thread.last_cpu_user;
thread.cpu_kernel = dt_kernel * 1000. / (double)ns_dt;
thread.cpu_user = dt_user * 1000. / (double)ns_dt;
thread.last_cpu_kernel = current_kernel;
thread.last_cpu_user = current_user;
thread.last_collection_nanoseconds = current_ns;
}
}
#endif
+2 -2
View File
@@ -20,7 +20,7 @@ class SystemThreadManager;
/*!
* Runs a function in a thread and provides a SystemThreadInterface to that function.
* Once the thread is ready, it should tell the interfaces with intitialization_complete().
* Once the thread is ready, it should tell the interface with intitialization_complete().
* Thread functions should try to return when get_want_exit() returns true.
* Thread functions should also call report_perf_stats every now and then to update performance
* statistics.
@@ -55,7 +55,7 @@ class SystemThread {
};
/*!
* The interfaces used by a thread in the runtime.
* The interface used by a thread in the runtime.
*/
class SystemThreadInterface {
public:
+5 -1
View File
@@ -1,6 +1,10 @@
#include "iop_thread.h"
#ifdef __linux__
#include <unistd.h>
#elif _WIN32
#include <io.h>
#endif
#include "SystemThread.h"
//#include "shared_config.h"
//#include "ps2/SCE_IOP.h"
@@ -117,7 +121,7 @@ IOP::~IOP() {
//
//// SCE_IOP::PS2_RegisterIOP(&iop);
//// PS2_RegisterIOP_EE(&iop);
// interfaces.initialization_complete();
// interface.initialization_complete();
//
// printf("[IOP] Wait for OVERLORD to be started...\n");
// iop.wait_for_overlord_start_cmd();
+6 -3
View File
@@ -6,10 +6,13 @@
* The CodeTester can't be used for tests requiring the full GOAL language/linking.
*/
#include <third-party/mman/mman.h>
#include <cstdio>
#ifdef __linux__
#include <sys/mman.h>
#elif _WIN32
#include <third-party/mman/mman.h>
#endif
#include <cstdio>
#include "CodeTester.h"
#include "IGen.h"
+10 -15
View File
@@ -1,9 +1,15 @@
/*!
* @file Listener.cpp
* The Listener can connect to a Deci2Server for debugging.
*/
// TODO-Windows
#ifdef __linux__
#include <stdexcept>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <Winsock2.h>
#include <io.h>
#include <cassert>
@@ -39,8 +45,6 @@ bool Listener::is_connected() const {
return m_connected;
}
/*
bool Listener::connect_to_target(const std::string& ip, int port) {
if (m_connected) {
throw std::runtime_error("attempted a Listener::connect_to_target when already connected!");
@@ -71,7 +75,7 @@ bool Listener::connect_to_target(const std::string& ip, int port) {
// set nodelay, which makes small rapid messages faster, but large messages slower
const char one = 1;
if (setsockopt(socket_fd, SOL_SOCKET, TCP_NODELAY, &one, sizeof(one))) {
if (setsockopt(socket_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) {
printf("[Listener] failed to TCP_NODELAY\n");
close(socket_fd);
socket_fd = -1;
@@ -141,15 +145,7 @@ bool Listener::connect_to_target(const std::string& ip, int port) {
/*!
* Runs in a separate thread to receive messages.
* Will print messages to stdout, or optionally save them.
/*!
* Attempt to connect to the target. If the target isn't running, this should fail quickly.
* Returns true if successfully connected.
*/
void Listener::receive_func() {
while (m_connected) {
// attempt to receive a ListenerMessageHeader
@@ -244,5 +240,4 @@ void Listener::receive_func() {
}
} // namespace listener
*/
#endif
-180
View File
@@ -1,180 +0,0 @@
#include <windows.h>
#include <errno.h>
#include <io.h>
#include "mman.h"
#ifndef FILE_MAP_EXECUTE
#define FILE_MAP_EXECUTE 0x0020
#endif /* FILE_MAP_EXECUTE */
static int __map_mman_error(const DWORD err, const int deferr)
{
if (err == 0)
return 0;
//TODO: implement
return err;
}
static DWORD __map_mmap_prot_page(const int prot)
{
DWORD protect = 0;
if (prot == PROT_NONE)
return protect;
if ((prot & PROT_EXEC) != 0)
{
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ;
}
else
{
protect = ((prot & PROT_WRITE) != 0) ?
PAGE_READWRITE : PAGE_READONLY;
}
return protect;
}
static DWORD __map_mmap_prot_file(const int prot)
{
DWORD desiredAccess = 0;
if (prot == PROT_NONE)
return desiredAccess;
if ((prot & PROT_READ) != 0)
desiredAccess |= FILE_MAP_READ;
if ((prot & PROT_WRITE) != 0)
desiredAccess |= FILE_MAP_WRITE;
if ((prot & PROT_EXEC) != 0)
desiredAccess |= FILE_MAP_EXECUTE;
return desiredAccess;
}
void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
HANDLE fm, h;
void * map = MAP_FAILED;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4293)
#endif
const DWORD dwFileOffsetLow = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)off : (DWORD)(off & 0xFFFFFFFFL);
const DWORD dwFileOffsetHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL);
const DWORD protect = __map_mmap_prot_page(prot);
const DWORD desiredAccess = __map_mmap_prot_file(prot);
const off_t maxSize = off + (off_t)len;
const DWORD dwMaxSizeLow = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL);
const DWORD dwMaxSizeHigh = (sizeof(off_t) <= sizeof(DWORD)) ?
(DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL);
#ifdef _MSC_VER
#pragma warning(pop)
#endif
errno = 0;
if (len == 0
/* Unsupported flag combinations */
|| (flags & MAP_FIXED) != 0
/* Usupported protection combinations */
|| prot == PROT_EXEC)
{
errno = EINVAL;
return MAP_FAILED;
}
h = ((flags & MAP_ANONYMOUS) == 0) ?
(HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE;
if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE)
{
errno = EBADF;
return MAP_FAILED;
}
fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL);
if (fm == NULL)
{
errno = __map_mman_error(GetLastError(), EPERM);
return MAP_FAILED;
}
map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len);
CloseHandle(fm);
if (map == NULL)
{
errno = __map_mman_error(GetLastError(), EPERM);
return MAP_FAILED;
}
return map;
}
int munmap(void *addr, size_t len)
{
if (UnmapViewOfFile(addr))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int mprotect(void *addr, size_t len, int prot)
{
DWORD newProtect = __map_mmap_prot_page(prot);
DWORD oldProtect = 0;
if (VirtualProtect(addr, len, newProtect, &oldProtect))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int msync(void *addr, size_t len, int flags)
{
if (FlushViewOfFile(addr, len))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int mlock(const void *addr, size_t len)
{
if (VirtualLock((LPVOID)addr, len))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
int munlock(const void *addr, size_t len)
{
if (VirtualUnlock((LPVOID)addr, len))
return 0;
errno = __map_mman_error(GetLastError(), EPERM);
return -1;
}
+28 -25
View File
@@ -942,30 +942,33 @@ TEST(GoosObject, char_to_string) {
EXPECT_EQ("#\\{17}", goos::fixed_to_string(char(17)));
}
///*!
// * Test the EmptyListObject
// */
//TEST(GoosObject, EmptyList) {
// // create two empty lists
// Object nil = EmptyListObject::make_new();
// Object nil2 = EmptyListObject::make_new();
//
// // check type is set
// EXPECT_TRUE(nil.is_empty_list());
//
// // check equality operator
// EXPECT_TRUE(nil == nil2);
//
// // check we get the same heap allocated object
// auto elo = std::dynamic_pointer_cast<EmptyListObject>(nil.heap_obj);
// auto elo2 = std::dynamic_pointer_cast<EmptyListObject>(nil2.heap_obj);
// EXPECT_TRUE(elo);
// EXPECT_TRUE(elo == elo2);
//
// // check print and inspect
// EXPECT_EQ(nil.print(), "()");
// EXPECT_EQ(nil.inspect(), "[empty list] ()\n");
//}
/*!
* Test the EmptyListObject
*/
TEST(GoosObject, EmptyList) {
// TODO-Windows
#ifdef __linux__
// create two empty lists
Object nil = EmptyListObject::make_new();
Object nil2 = EmptyListObject::make_new();
// check type is set
EXPECT_TRUE(nil.is_empty_list());
// check equality operator
EXPECT_TRUE(nil == nil2);
// check we get the same heap allocated object
auto elo = std::dynamic_pointer_cast<EmptyListObject>(nil.heap_obj);
auto elo2 = std::dynamic_pointer_cast<EmptyListObject>(nil2.heap_obj);
EXPECT_TRUE(elo);
EXPECT_TRUE(elo == elo2);
// check print and inspect
EXPECT_EQ(nil.print(), "()");
EXPECT_EQ(nil.inspect(), "[empty list] ()\n");
#endif
}
/*!
* Test IntegerObject
@@ -1286,4 +1289,4 @@ TEST(GoosSpecialForms, And) {
for (auto x : {"(and)"}) {
EXPECT_ANY_THROW(e(i, x));
}
}
}
+1 -1
View File
@@ -12636,7 +12636,7 @@ template<typename CharType> struct output_adapter_protocol
virtual ~output_adapter_protocol() = default;
};
/// a type to simplify interface
/// a type to simplify interfaces
template<typename CharType>
using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;