mirror of
https://github.com/open-goal/jak-project
synced 2026-06-08 20:29:54 -04:00
Add a bunch of #ifdefs to keep things working as expected on linux
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
name: Linux Workflow
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
+6
-6
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
/*!
|
||||
* @file kmemcard.cpp
|
||||
* Memory card interfaces. Very messy code.
|
||||
* Memory card interface. Very messy code.
|
||||
*/
|
||||
|
||||
//#include "ps2/SCE_MC.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* @file kmemcard.h
|
||||
* Memory card interfaces. Very messy code.
|
||||
* Memory card interface. Very messy code.
|
||||
*/
|
||||
|
||||
#ifndef JAK_KMEMCARD_H
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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:
|
||||
|
||||
@@ -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,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
@@ -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
|
||||
|
||||
@@ -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
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+1
-1
@@ -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>>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user