From 6e54bd61b1dee8a117ba23224e2b17dea409f234 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 26 Aug 2020 19:40:26 -0400 Subject: [PATCH 01/32] Format and start adding Windows steps --- .gitignore | 1 + CMakeLists.txt | 23 +++- README.md | 196 ++++++++++++++++++++++----------- doc/imgs/cmake-target-view.png | Bin 0 -> 15721 bytes doc/imgs/open-cmake-vs.png | Bin 0 -> 24424 bytes 5 files changed, 151 insertions(+), 69 deletions(-) create mode 100644 doc/imgs/cmake-target-view.png create mode 100644 doc/imgs/open-cmake-vs.png diff --git a/.gitignore b/.gitignore index 9a5df39548..d722b67441 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ cmake-build-debug/* .idea/* build/* +/.vs \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 45706cfa7f..ce4228908f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,10 +5,25 @@ 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 "-O0 -ggdb -Wall \ --Wextra -Wcast-align -Wcast-qual -Wdisabled-optimization -Wformat=2 \ --Winit-self -Wmissing-include-dirs -Woverloaded-virtual \ --Wredundant-decls -Wshadow -Wsign-promo ") +set(CMAKE_CXX_FLAGS "-O3 -ggdb") + +# Set default compile flags for GCC +if(CMAKE_COMPILER_IS_GNUCXX) + message(STATUS "GCC detected, adding compile flags") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} + -Wall-Winit-self + -Wextra + -Wcast-align + -Wcast-qual + -Wdisabled-optimization + -Wformat=2 + -Wmissing-include-dirs + -Woverloaded-virtual + -Wredundant-decls + -Wshadow + -Wsign-promo") +endif(CMAKE_COMPILER_IS_GNUCXX) # includes relative to top level jak-project folder include_directories(./) diff --git a/README.md b/README.md index 556a7f5924..47dc3c4de1 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,77 @@ -Project Structure ----------------------- -Requirements: +# Jak Project + +## Table of Contents + + + +- [Jak Project](#jak-project) + - [Table of Contents](#table-of-contents) + - [Requirements](#requirements) + - [Getting Started - Linux (Ubuntu)](#getting-started---linux-ubuntu) + - [Getting Started - Windows](#getting-started---windows) + - [Project Layout](#project-layout) + - [Design](#design) + - [Current State](#current-state) + - [Coding Guidelines](#coding-guidelines) + - [TODOs](#todos) + - [Project Description](#project-description) + - [GOAL Decompiler](#goal-decompiler) + - [GOAL Runtime](#goal-runtime) + - [GOAL Compiler](#goal-compiler) + - [Asset Extraction Tool](#asset-extraction-tool) + - [Asset Packing Tool](#asset-packing-tool) + + + +## Requirements + - `cmake` for build system - `clang-format` for formatting code (there is already a `.clang-format` provided) - `gtest` for testing. (Run `git submodule update --init --recursive` to check out the repository) -- `nasm` for assembling x86. There isn't much x86 assembly so if there's a better way to do this for windows, we can change. +- `nasm` for assembling x86 - Third party libraries (`nlohmann/json`, `minilzo`, and `linenoise`) are provided in the `third-party` folder -Setup (for Ubuntu): -``` +## Getting Started - Linux (Ubuntu) + +Install Packages and Init Repository + +```bash sudo apt install gcc make cmake build-essential g++ nasm clang-format +git submodule update --init --recursive ``` -Layout: +Compile + +```bash +mkdir build && cd build && cmake .. && make -j +``` + +Run Tests + +```bash +./test.sh +``` + +## Getting Started - Windows + +Install Visual Studio 2019 and get the C++ and CMake tools via the Visual Studio Installer + +On Windows, it's recommended to get Scoop to use as a package manager, making the follow steps _much_ easier. Follow the steps on the bottom of the homepage here https://scoop.sh/ + +Once Scoop is installed, run the following command: + +```ps +scoop install llvm nasm +``` + +Open the project as a CMake project, browse for the root level `CMakeLists.txt`: + +![](./doc/imgs/open-cmake-vs.png) + +TODO - more steps to follow as we actually figure it out! + +## Project Layout + - `goalc` is the GOAL compiler - `gs` contains GOOS code for parts of GOOS implemented in GOOS - `gc` contains GOAL code for parts of GOAL implemented in GOAL (must generate no machine code, just defining macros) @@ -29,8 +88,10 @@ Layout: - `tests` will contain all tests - `asset_tool` will contain the asset packer/unpacker -Design: +## Design + (if anybody has better ideas, feel free to suggest improvements! This is just a rough plan for now) + - All C++ code should build from the top-level `cmake`. - All C++ applications (GOAL compiler, asset extractor, asset packer, runtime, test) should have a script in the top level which launches them. - All file paths should be relative to the `jak` folder. @@ -48,11 +109,13 @@ Design: - `./gc.sh` : run the compiler in interactive mode - `./gs.sh` : run a goos interpreter in interactive mode - `./decomp.sh : run the decompiler - -Current state: + +## Current State + - GOAL compiler just implements the GOOS Scheme Macro Language. Running `./gc.sh` just loads the GOOS library (`goalc/gs/goos-lib.gs`) and then goes into an interactive mode. Use `(exit)` to exit. - `./test.sh` runs tests for some game C++ code, for GOOS, for the reader, for the listener connection, and for some early emitter stuff. -- The runtime boots in `fakeiso` mode which will load some dummy files. Then the C Kernel (`game/kernel`) will load the `KERNEL.CGO` and `GAME.CGO` files, which are from the "proof of concept" GOAL compiler. If you run `./gk.sh`, you should see it load stuff, then print: +- The runtime boots in `fakeiso` mode which will load some dummy files. Then the C Kernel (`game/kernel`) will load the `KERNEL.CGO` and `GAME.CGO` files, which are from the "proof of concept" GOAL compiler. If you run `./gk.sh`, you should see it load stuff, then print: + ``` calling play! ~~ HACK ~~ : fake play has been called @@ -61,13 +124,16 @@ InitCheckListener kernel: machine started ``` + where the `~~ HACK ~~` message is from code in `KERNEL.CGO`. -Code Guidelines: +## Coding Guidelines + - Avoid warnings - Use asserts over throwing exceptions in game code (throwing exceptions from C code called by GOAL code is sketchy) -TODOS: +## TODOs + - Build on Windows! - Networking - File paths @@ -82,8 +148,8 @@ TODOS: - Clean up possible duplicate code in compiler/decompiler `util` folder, consider a common utility library - Clean up header guard names (or just use `#pragma once`?) - Investigate a better config format - - The current JSON library seems to have issues with comments, which I really like -- Clean up use of namespaces + - The current JSON library seems to have issues with comments, which I really like +- Clean up use of namespaces - Clean up the print message when `gk` starts. - Finish commenting runtime stuff - Runtime document @@ -95,11 +161,10 @@ TODOS: - Clean up decompiler print spam, finish up the CFG stuff - Decompiler document - -Project Description ------------------------ +## Project Description This project is to port Jak 1 (NTSC, "black label" version) to PC. The strategy is to: + - recompile for x86 to get much better performance than emulation - create human-reabable GOAL source code that can be modified - create a GOAL compiler for x86-64 which supports live patching of code like the original @@ -107,6 +172,7 @@ This project is to port Jak 1 (NTSC, "black label" version) to PC. The strategy - unpack assets in a format that can be modified There are 6 components to this project + - GOAL decompiler. The result will be manually cleaned up for running on a PC. - GOAL compiler for x86-64. - Game source code, made from cleaning up the result of the GOAL decompiler. @@ -115,25 +181,27 @@ There are 6 components to this project - Asset packing tool. The process to build the port will be + - Build data extraction tool, GOAL compiler, and GOAL runtime library (all written in C++) - Run the GOAL compiler on the game source code to build the game engine - Run asset extraction on the game disc to get level data, textures, geometry data, music... - Run the asset packing tool to combine the unpacked assets with the compiled game engine to create the game! Some statistics: + - Estimated ~500k lines of GOAL code - 10410 functions - 5451 functions with no control flow (no branching, loops, if/else, short-circuiting boolean operators, gotos, etc) -The rough timeline is to finish sometime in 2022. If it looks like this is impossible, the project will be abandoned. But I have already spent about 4 months preparing to start this and seems doable. I also have some background in compilers, and familiarity with PS2 (worked on DobieStation PS2 emulator) / MIPS in general (wrote a PS1 emulator). I think the trick will be making good automated tools - the approach taken for SM64 and other N64 decompilations is way too labor-intensive to work. +The rough timeline is to finish sometime in 2022. If it looks like this is impossible, the project will be abandoned. But I have already spent about 4 months preparing to start this and seems doable. I also have some background in compilers, and familiarity with PS2 (worked on DobieStation PS2 emulator) / MIPS in general (wrote a PS1 emulator). I think the trick will be making good automated tools - the approach taken for SM64 and other N64 decompilations is way too labor-intensive to work. +### GOAL Decompiler -GOAL Decompiler ------------------- -The decompiler is in progress, at +The decompiler is in progress, at https://github.com/water111/jak-disassembler Here is the plan for writing the decompiler: + - [x] Decode the CGO/DGO format. - [x] Decode the linking data format. - [x] Identify all code and disassemble @@ -147,10 +215,10 @@ Here is the plan for writing the decompiler: - [ ] Variable map and scoping - [ ] S-expression construction (expression stack) +### GOAL Runtime + +The "runtime" will be a replacement for all of the C/C++ code of the original game. There is C/C++ code that runs on the main processor (EE) and the separate I/O processor (IOP). -GOAL Runtime --------------- -The "runtime" will be a replacement for all of the C/C++ code of the original game. There is C/C++ code that runs on the main processor (EE) and the separate I/O processor (IOP). - The "C Kernel", which runs on the EE and contains - [ ] File I/O (for debugging, not used by retail game) - [x] Initialization to boostrap the GOAL Kernel and start the game engine @@ -180,17 +248,18 @@ The "Sony libraries" are a simple wrapper around my `system` library, which impl Likely there will be sound/graphics code in here at some point, but this part is not fully planned yet. -GOAL Compiler ---------------- +### GOAL Compiler + The GOAL compiler will target x86-64. At first just Linux. There is a macro language called GOOS which is basically just Scheme but with a few bonus features. -The compiler will reuse a significant amount of code from my existing LISP compiler for x86-64. I have a very bad WIP combination which is capable of building a modified `gkernel.gc` for x86 as a proof of concept. It can create and run functions in threads. +The compiler will reuse a significant amount of code from my existing LISP compiler for x86-64. I have a very bad WIP combination which is capable of building a modified `gkernel.gc` for x86 as a proof of concept. It can create and run functions in threads. -An important part of the compiler is the test suite. Without tests the compiler will be full of bugs. So every feature should have a good set of tests. +An important part of the compiler is the test suite. Without tests the compiler will be full of bugs. So every feature should have a good set of tests. The major components are - [ ] GOAL-IR, a typed linear intermediate representation for GOAL code + - [ ] "Environment" - [ ] "Ref" - [ ] Constant propagation of integers/floats @@ -198,6 +267,7 @@ The major components are - [ ] Ref `in_gpr` - [ ] The type system + - [ ] Type inheritance - [ ] Integer/float/pointer types (value semantics) - [ ] Reference types @@ -216,41 +286,41 @@ The major components are - [ ] Built-in types in the GOAL runtime/C Kernel - [x] The GOOS Macro Language + - [x] S-expression parser (the "Reader") - [x] Reader text db (for error messages that point to a specific line) - [x] Scheme interpreter - + - [ ] Front-end (convert s-expressions (a tree structure) to GOAL-IR (a linear representation)) - - [ ] Parsing helpers - - [ ] Macro expansion - - [ ] Control flow/block forms - - [ ] Type definitions - - [ ] Inline assembly forms - - [ ] Function/method call - - [ ] Math forms - - [ ] Lexical scoping (immediate application of `lambda`) - - [ ] Function inlining (slightly different scoping rules of immediate `lambda`) - - [ ] Function/macro definition - - [ ] Static Objects +- [ ] Parsing helpers +- [ ] Macro expansion +- [ ] Control flow/block forms +- [ ] Type definitions +- [ ] Inline assembly forms +- [ ] Function/method call +- [ ] Math forms +- [ ] Lexical scoping (immediate application of `lambda`) +- [ ] Function inlining (slightly different scoping rules of immediate `lambda`) +- [ ] Function/macro definition +- [ ] Static Objects - [ ] Regsiter allocation - - [ ] Analysis - - [ ] Allocation - - [ ] Stack spilling - - [ ] `xmm` and `gpr` promotion/demotions for EE 128-bit register usage - +- [ ] Analysis +- [ ] Allocation +- [ ] Stack spilling +- [ ] `xmm` and `gpr` promotion/demotions for EE 128-bit register usage - [ ] Codegen / Emitter (convert GOAL-IR + register allocations to x86 object file format) - - [ ] Emitter (convert GOAL-IR to instructions) - - [ ] x86-64 instruction generation (actually generate the machine code) - - [ ] Linking data - - [ ] 64-bit GPR - - [ ] 32-bit float - - [ ] 128-bit GPR - - [ ] 32-bit float x4 vector register - - [ ] function prologue/epilogue - - [ ] stack spilling - - [ ] static object and static object links +- [ ] Emitter (convert GOAL-IR to instructions) +- [ ] x86-64 instruction generation (actually generate the machine code) +- [ ] Linking data +- [ ] 64-bit GPR +- [ ] 32-bit float +- [ ] 128-bit GPR +- [ ] 32-bit float x4 vector register +- [ ] function prologue/epilogue +- [ ] stack spilling +- [ ] static object and static object links - [ ] Listener/REPL - [ ] Network connection @@ -260,14 +330,14 @@ The major components are - [ ] Expand single macro debugging feature - [ ] Interface for running gtests +### Asset Extraction Tool -Asset Extraction Tool ------------------------ -Not started yet. The simplest version of this tool is just to use the decompiler logic to turn the level/art-group/texture/TXT files into GOAL source code, and copy all STR/sound/visibility files, as these don't need to be modified. +Not started yet. The simplest version of this tool is just to use the decompiler logic to turn the level/art-group/texture/TXT files into GOAL source code, and copy all STR/sound/visibility files, as these don't need to be modified. Eventually this should export to a more useful format. File formats: + - [ ] Art group (a GOAL object format) - There may be more formats related to art groups. - [ ] Texture page (a GOAL object format) @@ -282,12 +352,8 @@ File formats: - [ ] Loading screen image - [ ] save game icon (I do not care about this) +### Asset Packing Tool -Asset Packing Tool ------------------------ -Packs together all assets/compiled code/runtime into a format that can be played. The simplest version to go with the simplest extraction tool will just pass the level/art-group/texture/TXT files to the compiler, and copy STR/sound/visbility files into the fakeiso. Then pack in CGOs/DGOs. +Packs together all assets/compiled code/runtime into a format that can be played. The simplest version to go with the simplest extraction tool will just pass the level/art-group/texture/TXT files to the compiler, and copy STR/sound/visbility files into the fakeiso. Then pack in CGOs/DGOs. It's important that the asset extraction/packing can be automated so we can avoid distributing the assets, which are large and probably not supposed to be distributed. - - - diff --git a/doc/imgs/cmake-target-view.png b/doc/imgs/cmake-target-view.png new file mode 100644 index 0000000000000000000000000000000000000000..2a69df167af2bb6b5b3e01a5c29b7f511ef719b0 GIT binary patch literal 15721 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 a1lfp6jh|F8EFi)dATO;XRV85(`o91*%c-~k literal 0 HcmV?d00001 diff --git a/doc/imgs/open-cmake-vs.png b/doc/imgs/open-cmake-vs.png new file mode 100644 index 0000000000000000000000000000000000000000..914a2ff7fa152bf32166f9502d950a2cd17dda75 GIT binary patch literal 24424 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 literal 0 HcmV?d00001 From 5a2b39641fec6127da1945c8c679103d8a853019 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 26 Aug 2020 20:02:44 -0400 Subject: [PATCH 02/32] CMake adjustments, leave edits that didn't change file paths --- CMakeSettings.json | 16 ++++++++++++++++ game/CMakeLists.txt | 24 ++++++++++++++++++++---- game/kernel/kprint.h | 2 ++ game/system/Deci2Server.h | 3 ++- game/system/SystemThread.h | 3 +-- game/system/Timer.h | 2 -- 6 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 CMakeSettings.json diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 0000000000..99b611bdd9 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,16 @@ +{ + // See https://go.microsoft.com/fwlink/?linkid=834763 for more information about this file. + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 05e0d99744..5e79e3eb31 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -1,9 +1,25 @@ # We define our own compilation flags here. set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_FLAGS "-O0 -ggdb -Wall \ --Wextra -Wcast-align -Wcast-qual -Wdisabled-optimization -Wformat=2 \ --Winit-self -Wmissing-include-dirs -Woverloaded-virtual \ --Wredundant-decls -Wshadow -Wsign-promo ") + +set(CMAKE_CXX_FLAGS "-O3 -ggdb") + +# Set default compile flags for GCC +if(CMAKE_COMPILER_IS_GNUCXX) + message(STATUS "GCC detected, adding compile flags") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} + -Wall-Winit-self + -Wextra + -Wcast-align + -Wcast-qual + -Wdisabled-optimization + -Wformat=2 + -Wmissing-include-dirs + -Woverloaded-virtual + -Wredundant-decls + -Wshadow + -Wsign-promo") +endif(CMAKE_COMPILER_IS_GNUCXX) enable_language(ASM_NASM) set(RUNTIME_SOURCE diff --git a/game/kernel/kprint.h b/game/kernel/kprint.h index d26fea7bc3..ae95925154 100644 --- a/game/kernel/kprint.h +++ b/game/kernel/kprint.h @@ -25,6 +25,8 @@ extern Ptr MessBufArea; extern Ptr OutputBufArea; extern Ptr PrintBufArea; +#define __attribute__(A) /* do nothing */ + /*! * Initialize global variables for kprint */ diff --git a/game/system/Deci2Server.h b/game/system/Deci2Server.h index b53547a10c..c9e0542795 100644 --- a/game/system/Deci2Server.h +++ b/game/system/Deci2Server.h @@ -7,7 +7,8 @@ #ifndef JAK1_DECI2SERVER_H #define JAK1_DECI2SERVER_H -#include +#include + #include #include #include diff --git a/game/system/SystemThread.h b/game/system/SystemThread.h index 0d0bafac0d..5f89929dc2 100644 --- a/game/system/SystemThread.h +++ b/game/system/SystemThread.h @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -40,7 +39,7 @@ private: friend void* bootstrap_thread_func(void* thd); std::string name = "invalid"; - pthread_t thread; + std::thread thread; SystemThreadManager* manager; std::function function; bool initialization_complete = false; diff --git a/game/system/Timer.h b/game/system/Timer.h index 21bfbce8ce..fd2b1667dd 100644 --- a/game/system/Timer.h +++ b/game/system/Timer.h @@ -12,7 +12,6 @@ public: } void start() { - clock_gettime(CLOCK_MONOTONIC, &_startTime); } double getMs() { @@ -21,7 +20,6 @@ public: int64_t getNs() { struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); return (int64_t)(now.tv_nsec - _startTime.tv_nsec) + 1000000000 * (now.tv_sec - _startTime.tv_sec); } From fc433222f4ff3c17549eaed3f5b247e95f912930 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 26 Aug 2020 20:06:18 -0400 Subject: [PATCH 03/32] Some last things added to the README --- README.md | 20 +++++++++++++++++++- doc/imgs/cmake-build-vs.png | Bin 0 -> 41733 bytes 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 doc/imgs/cmake-build-vs.png diff --git a/README.md b/README.md index 47dc3c4de1..5295f677c1 100644 --- a/README.md +++ b/README.md @@ -64,11 +64,29 @@ Once Scoop is installed, run the following command: scoop install llvm nasm ``` +Initialize the repository's third-party dependencies: + +```bash +git submodule update --init --recursive +``` + Open the project as a CMake project, browse for the root level `CMakeLists.txt`: ![](./doc/imgs/open-cmake-vs.png) -TODO - more steps to follow as we actually figure it out! +In the toolbar, you should be able to select an individual component to compile, or combine within the root CMakeLists.txt. In the future we will pre-define configurations to make this easier. + +![](./doc/imgs/cmake-build-vs.png) + +You may also wish to view the files that pertain to each CMake target, rather than the project as it is normally: + +![](./doc/imgs/cmake-target-view.png) + +TODO + +- more steps to follow as we actually figure it out! +- running tests +- etc ## Project Layout diff --git a/doc/imgs/cmake-build-vs.png b/doc/imgs/cmake-build-vs.png new file mode 100644 index 0000000000000000000000000000000000000000..23f6a4ccb8b6509459e2e204405236fab7ca3cd5 GIT binary patch literal 41733 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

PUymS-qAXQrN!EoKku_e4d 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� zyNu^mO4gahw;_Wo@t`d7(E3s*Vmk4VA<$Ziu*s&EiZF4}Qy86%{8)@??iZ6Y812oD zOB0Sm$;!FM@XJyhqXiV65Wy^DSki@8Vp!IWMbo?%ogChT{X~z^v$`+p1Ccv6Y>`(C%kU5LHD^} zAPyNBA1BIAg*&2x^zHszS9_N>8a&#?Bqn87gM7a~F7hCJapW(IlwNADg{HG9w-;Eq z04o)Pr+uC&DrC2fD9woZqoG;$3}s@&U2YpJU4`J+aCH%=QC52eYI%WTtPS*Hmi zD(J;m2M?hmVdxWUvJ4Olg;KPeYiQFr>IKA}FS@;8P z^%!S3*Oh~KtHw^}0PIdOa0d!(dAKX+I zQF58=yRYgLmDB(G<@aYoY=gxXl6{J8UygV?^Cf9AlKq%9^hk>!gxbbYrXBe-BTT`v z-^pNgXG0>_hQfe3uWAka1K=ezF7Wsg!(wPo1m1h%Ls5p1n!9!Ux{FTOkjM2lI2 z5(pteMD<5my;kIqe)6o~P6Kq?m#ZZB7ads^0SyDw2sySQoC=-bj)Au|#c)qSM5ruY z(HuH1z-_q2t~`9Rb1f`pt_+&SuJv_oc#T0I%Sz77gIhl>C1-uSh;~Tu?P?dZ;0@`3CLWFIpi&@B-oZg~Py`hG* zY--(E+w-)4U-`)k-(%+KYIsc&&{Cpj)5#UxfnpGwY-PMZ0;tQ#T zLpg8qsK{d)nQ9q1yIZzTZd{#ilQ}JZWhuQxQE$azrB1xeeYNICBf)+X zq^Y}ynL-MslSBg2A1bF2s_N+zhqe1&g^s1T08lPR#^JHx?QqWZ#;Su)YbkUi!c^fa zT`X3Uc;LY0L7{wYfw%9(Sc0z6@xWFaw+EXO>0y!2)lC^(#Hh^yX;F-rBC$+VxyM^9 zJg*yksU_=Kf7dy*}oGOZKE{bn{&P{t}Al(}^!0uK-t?H6S_G<6VL zM&v#pQLIvU&ThDwK-lpx!Cg7>t7_e+%Z^VX>gwN*?Zj%K+4@v;lO*B$fE* z1NJmp*&U)gGUos^ScsIFg%eL^q)>fV;aNjnmF=&-XyVm1`3>v6*5~cOWD|WDPg<+B zO7MjUy1eX>lFosd8Hq-TzCZCt5_S}XFgevzS{}aov`eqXrnC($61TvJp*;F zL`KlVj}iVB9?8g!zByu=O}ULCW6&@lWc(GsR(W&($DR>M%u8 zjmw(@7Y?`Jm+u4!2@nY|xs5>(B{RA?w~zS!>|$T>%h69hQlF#aE{$t-j=1VFan$Ev zibQfRr5MrY>WI%Do)7@L-q`Z#$CeKZkAi#-p#y+(?sxwd^0FVp+Pwieo+RwZlV{>* z#)GiL?Z0<}wdUPwoWpTNtlnA)_LKA-n-A-Ej3--QHo<-=PA-G~U zHRr0O=}gC(iEv)zat{`%pvtFX1!Bh7INEc&NhCHozNW^5R8}4ku|Ue7cC`k2hK*S% zp!bO9v-0kklQm~Kr%!w-N*)_~*JLSfEY8vF+ERY>t2P(O#)tM_!(l9y=XcYoEtZ8wCZSbBYX`8cioVuf0KoBt2R5!#z*Ol zfxm9F3TrkTo>w~m?!W9QcY|NTDS8B=G7SGp+kY~}D1fe$NS_$Yo&UK*Uo@jK@*&~i zJl0yMSpN>Lg_?HR5cPsOHqDJYO9x5%H9DFXOoN{0=D+gLV1_kuAI(8jgQVIbzRAz) sL@kMxVfV1#UgA$5I^D#6`=NY#Biw!+qBRrfg#E23rz%@6Z5sIh0K%=zQ~&?~ literal 0 HcmV?d00001 From c4bd9eaf696e27ec594123b7111837e516fe8714 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 26 Aug 2020 20:38:42 -0400 Subject: [PATCH 04/32] __attribute__ is technically not required. We can probably replace this in a cross platform way like with clang-tidy? --- game/kernel/kprint.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/game/kernel/kprint.h b/game/kernel/kprint.h index ae95925154..049a66d35c 100644 --- a/game/kernel/kprint.h +++ b/game/kernel/kprint.h @@ -25,8 +25,6 @@ extern Ptr MessBufArea; extern Ptr OutputBufArea; extern Ptr PrintBufArea; -#define __attribute__(A) /* do nothing */ - /*! * Initialize global variables for kprint */ @@ -67,25 +65,25 @@ void output_segment_load(const char* name, Ptr 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. From 33e522ea528cb1231694dd1fbaa796564436a06f Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Wed, 26 Aug 2020 18:59:06 -0600 Subject: [PATCH 05/32] Windows fixes More Windows fixes --- CMakeLists.txt | 5 +- CMakeSettings.json | 16 ++ README.md | 4 +- common/type_system/Type.cpp | 16 +- common/type_system/TypeSystem.cpp | 26 +-- common/type_system/TypeSystem.h | 2 +- decompiler/ObjectFile/LinkedObjectFile.cpp | 2 +- .../ObjectFile/LinkedObjectFileCreation.cpp | 4 +- decompiler/util/FileIO.cpp | 6 +- decompiler/util/LispPrint.cpp | 4 +- decompiler/util/LispPrint.h | 2 +- decompiler/util/Timer.cpp | 4 +- decompiler/util/Timer.h | 4 +- game/CMakeLists.txt | 6 +- game/kernel/Ptr.h | 4 +- game/kernel/kboot.cpp | 6 +- game/kernel/klink.cpp | 2 +- game/kernel/kmemcard.cpp | 2 +- game/kernel/kmemcard.h | 2 +- game/kernel/kprint.cpp | 32 ++-- game/kernel/kprint.h | 2 + game/kernel/kscheme.cpp | 12 +- game/overlord/fake_iso.cpp | 2 + game/runtime.cpp | 45 +++-- game/sce/deci2.cpp | 24 +-- game/sce/iop.cpp | 4 +- game/sce/stubs.cpp | 10 +- game/system/Deci2Server.cpp | 39 ++-- game/system/Deci2Server.h | 6 +- game/system/IOP_Kernel.cpp | 18 +- game/system/IOP_Kernel.h | 6 +- game/system/SystemThread.cpp | 40 +--- game/system/SystemThread.h | 7 +- game/system/Timer.h | 2 - game/system/deci_common.h | 1 + game/system/iop_thread.cpp | 8 +- goalc/emitter/CodeTester.cpp | 2 +- goalc/goos/Interpreter.cpp | 6 +- goalc/goos/InterpreterEval.cpp | 8 +- goalc/goos/Object.cpp | 4 +- goalc/goos/Object.h | 36 ++-- goalc/goos/Reader.cpp | 10 +- goalc/listener/Deci2Server.cpp | 2 +- goalc/listener/Deci2Server.h | 4 +- goalc/listener/Listener.cpp | 31 +-- goalc/util/file_io.cpp | 2 +- mman.c | 180 ++++++++++++++++++ test/all_jak1_symbols.cpp | 2 +- third-party/fmt/format-inl.h | 8 +- third-party/fmt/format.cc | 2 +- third-party/fmt/format.h | 18 +- third-party/json.hpp | 34 ++-- third-party/minilzo/lzoconf.h | 2 +- third-party/mman.h | 57 ++++++ 54 files changed, 513 insertions(+), 270 deletions(-) create mode 100644 CMakeSettings.json create mode 100644 mman.c create mode 100644 third-party/mman.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 45706cfa7f..1b94d91c09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,10 +5,7 @@ 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 "-O0 -ggdb -Wall \ --Wextra -Wcast-align -Wcast-qual -Wdisabled-optimization -Wformat=2 \ --Winit-self -Wmissing-include-dirs -Woverloaded-virtual \ --Wredundant-decls -Wshadow -Wsign-promo ") +set(CMAKE_CXX_FLAGS "") # includes relative to top level jak-project folder include_directories(./) diff --git a/CMakeSettings.json b/CMakeSettings.json new file mode 100644 index 0000000000..08c8f8af93 --- /dev/null +++ b/CMakeSettings.json @@ -0,0 +1,16 @@ +{ + // See https://go.microsoft.com/fwlink/?linkid=834763 for more information about this file. + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 556a7f5924..bd52e0af94 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ The "runtime" will be a replacement for all of the C/C++ code of the original ga - [x] GOAL Linker - [ ] PS2-specific hardware initialization as required by Sony libraries - [x] GOAL "kheap" allocator - - [ ] Memory card interface + - [ ] Memory card interfaces - [x] GOAL printf (called `format`) implementation - [x] GOAL hash/symbol table implementation - [x] Implementation of some built-in GOAL methods/functions @@ -172,7 +172,7 @@ The "runtime" will be a replacement for all of the C/C++ code of the original ga - [ ] Ramdisk stuff (implemented but totally untested) - The "989_snd" sound driver (no progress has been made here, the rough plan is to do a high level emulation of the sound system) - Sony libraries - - [x] SIF (interface between EE/IOP for sending data, receiving data, and making remote procedure calls) + - [x] SIF (interfaces between EE/IOP for sending data, receiving data, and making remote procedure calls) - [x] IOP Kernel (single-processor non-preemptive multitasking) - [x] stubs for stuff that doesn't really matter diff --git a/common/type_system/Type.cpp b/common/type_system/Type.cpp index 3dd0fe1a80..160af24e3e 100644 --- a/common/type_system/Type.cpp +++ b/common/type_system/Type.cpp @@ -227,35 +227,35 @@ std::string Type::print_method_info() const { NoneType::NoneType() : Type("", "none", false) {} bool NoneType::is_reference() const { - throw std::runtime_error("is_reference called on NoneType"); + throw std::exception("is_reference called on NoneType"); } int NoneType::get_load_size() const { - throw std::runtime_error("get_load_size called on NoneType"); + throw std::exception("get_load_size called on NoneType"); } bool NoneType::get_load_signed() const { - throw std::runtime_error("get_load_size called on NoneType"); + throw std::exception("get_load_size called on NoneType"); } int NoneType::get_size_in_memory() const { - throw std::runtime_error("get_size_in_memory called on NoneType"); + throw std::exception("get_size_in_memory called on NoneType"); } RegKind NoneType::get_preferred_reg_kind() const { - throw std::runtime_error("get_preferred_reg_kind called on NoneType"); + throw std::exception("get_preferred_reg_kind called on NoneType"); } int NoneType::get_offset() const { - throw std::runtime_error("get_offset called on NoneType"); + throw std::exception("get_offset called on NoneType"); } int NoneType::get_in_memory_alignment() const { - throw std::runtime_error("get_in_memory_alignment called on NoneType"); + throw std::exception("get_in_memory_alignment called on NoneType"); } int NoneType::get_inline_array_alignment() const { - throw std::runtime_error("get_inline_array_alignment called on NoneType"); + throw std::exception("get_inline_array_alignment called on NoneType"); } std::string NoneType::print() const { diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index 76e4005c59..9cbabfd54a 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -32,7 +32,7 @@ Type* TypeSystem::add_type(const std::string& name, std::unique_ptr type) // update the type m_types[name] = std::move(type); } else { - throw std::runtime_error("Type was redefined with throw_on_redefine set."); + throw std::exception("Type was redefined with throw_on_redefine set."); } } } else { @@ -43,13 +43,13 @@ Type* TypeSystem::add_type(const std::string& name, std::unique_ptr type) if (m_forward_declared_types.find(type->get_parent()) != m_forward_declared_types.end()) { fmt::print("[TypeSystem] Type {} has incompletely defined parent {}\n", type->get_name(), type->get_parent()); - throw std::runtime_error("add_type failed"); + throw std::exception("add_type failed"); } if (m_types.find(type->get_parent()) == m_types.end()) { fmt::print("[TypeSystem] Type {} has undefined parent {}\n", type->get_name(), type->get_parent()); - throw std::runtime_error("add_type failed"); + throw std::exception("add_type failed"); } } @@ -135,7 +135,7 @@ TypeSpec TypeSystem::make_typespec(const std::string& name) { return TypeSpec(name); } else { fmt::print("[TypeSystem] The type {} is unknown.\n", name); - throw std::runtime_error("make_typespec failed"); + throw std::exception("make_typespec failed"); } } @@ -199,7 +199,7 @@ Type* TypeSystem::lookup_type(const std::string& name) { fmt::print("[TypeSystem] The type {} is not defined.\n", name); } - throw std::runtime_error("lookup_type failed"); + throw std::exception("lookup_type failed"); } /*! @@ -254,7 +254,7 @@ MethodInfo TypeSystem::add_method(Type* type, const std::string& method_name, co method_name, type->get_name(), existing_info.type.print(), ts.print()); // unlike type re-definition, method re-definition is almost certain to go wrong. // probably better to give up. - throw std::runtime_error("method redefinition"); + throw std::exception("method redefinition"); } return existing_info; @@ -278,7 +278,7 @@ MethodInfo TypeSystem::add_new_method(Type* type, const TypeSpec& ts) { "[TypeSystem] The new method of {} was originally defined as {}, but has been redefined " "as {}\n", type->get_name(), existing.type.print(), ts.print()); - throw std::runtime_error("add_new_method failed"); + throw std::exception("add_new_method failed"); } return existing; @@ -317,7 +317,7 @@ MethodInfo TypeSystem::lookup_method(const std::string& type_name, const std::st } fmt::print("[TypeSystem] The method {} of type {} could not be found.\n", method_name, type_name); - throw std::runtime_error("lookup_method failed"); + throw std::exception("lookup_method failed"); } /*! @@ -345,7 +345,7 @@ MethodInfo TypeSystem::lookup_new_method(const std::string& type_name) { } fmt::print("[TypeSystem] The new method of type {} could not be found.\n", type_name); - throw std::runtime_error("lookup_new_method failed"); + throw std::exception("lookup_new_method failed"); } /*! @@ -420,7 +420,7 @@ void TypeSystem::assert_field_offset(const std::string& type_name, if (field.offset() != offset) { fmt::print("[TypeSystem] assert_field_offset({}, {}, {}) failed - got {}\n", type_name, field_name, offset); - throw std::runtime_error("assert_field_offset failed"); + throw std::exception("assert_field_offset failed"); } } @@ -436,7 +436,7 @@ int TypeSystem::add_field_to_type(StructureType* type, int offset_override) { if (type->lookup_field(field_name, nullptr)) { fmt::print("[TypeSystem] Type {} already has a field named {}\n", type->get_name(), field_name); - throw std::runtime_error("add_field_to_type duplicate field names"); + throw std::exception("add_field_to_type duplicate field names"); } // first, construct the field @@ -467,7 +467,7 @@ int TypeSystem::add_field_to_type(StructureType* type, "[TypeSystem] Tried to overwrite offset of field to be {}, but it is not aligned " "correctly\n", offset); - throw std::runtime_error("add_field_to_type bad offset_override"); + throw std::exception("add_field_to_type bad offset_override"); } } @@ -649,7 +649,7 @@ Field TypeSystem::lookup_field(const std::string& type_name, const std::string& Field field; if (!type->lookup_field(field_name, &field)) { fmt::print("[TypeSystem] Type {} has no field named {}\n", type_name, field_name); - throw std::runtime_error("lookup_field failed"); + throw std::exception("lookup_field failed"); } return field; } diff --git a/common/type_system/TypeSystem.h b/common/type_system/TypeSystem.h index 71a865588b..e290c13f06 100644 --- a/common/type_system/TypeSystem.h +++ b/common/type_system/TypeSystem.h @@ -76,7 +76,7 @@ class TypeSystem { auto x = lookup_type(type_name); T* result = dynamic_cast(x); if (!result) { - throw std::runtime_error("Failed to get " + type_name + " as the right type"); + throw std::exception("Failed to get the right type"); } return result; } diff --git a/decompiler/ObjectFile/LinkedObjectFile.cpp b/decompiler/ObjectFile/LinkedObjectFile.cpp index d02fc3bf31..263144d4b1 100644 --- a/decompiler/ObjectFile/LinkedObjectFile.cpp +++ b/decompiler/ObjectFile/LinkedObjectFile.cpp @@ -272,7 +272,7 @@ void LinkedObjectFile::append_word_to_string(std::string& dest, const LinkedWord sprintf(buff, " .sym-off 0x%x %s\n", word.data >> 16, word.symbol_name.c_str()); break; default: - throw std::runtime_error("nyi"); + throw std::exception("nyi"); } dest += buff; diff --git a/decompiler/ObjectFile/LinkedObjectFileCreation.cpp b/decompiler/ObjectFile/LinkedObjectFileCreation.cpp index d61b515224..a4d99849d1 100644 --- a/decompiler/ObjectFile/LinkedObjectFileCreation.cpp +++ b/decompiler/ObjectFile/LinkedObjectFileCreation.cpp @@ -134,7 +134,7 @@ static uint32_t c_symlink2(LinkedObjectFile& f, word_kind = LinkedWord::TYPE_PTR; break; default: - throw std::runtime_error("unhandled SymbolLinkKind"); + throw std::exception("unhandled SymbolLinkKind"); } f.symbol_link_word(seg_id, code_ptr_offset - initial_offset, name, word_kind); @@ -191,7 +191,7 @@ static uint32_t c_symlink3(LinkedObjectFile& f, word_kind = LinkedWord::TYPE_PTR; break; default: - throw std::runtime_error("unhandled SymbolLinkKind"); + throw std::exception("unhandled SymbolLinkKind"); } f.symbol_link_word(seg, code_ptr - initial_offset, name, word_kind); diff --git a/decompiler/util/FileIO.cpp b/decompiler/util/FileIO.cpp index 914d647d59..b3f63d16fa 100644 --- a/decompiler/util/FileIO.cpp +++ b/decompiler/util/FileIO.cpp @@ -16,7 +16,7 @@ std::string combine_path(const std::string& parent, const std::string& child) { std::vector read_binary_file(const std::string& filename) { auto fp = fopen(filename.c_str(), "rb"); - if(!fp) throw std::runtime_error("File " + filename + " cannot be opened"); + if(!fp) throw std::exception("File cannot be opened"); fseek(fp, 0, SEEK_END); auto len = ftell(fp); rewind(fp); @@ -25,7 +25,7 @@ std::vector read_binary_file(const std::string& filename) { data.resize(len); if(fread(data.data(), len, 1, fp) != 1) { - throw std::runtime_error("File " + filename + " cannot be read"); + throw std::exception("File cannot be read"); } return data; @@ -75,7 +75,7 @@ void write_text_file(const std::string& file_name, const std::string& text) { FILE* fp = fopen(file_name.c_str(), "w"); if(!fp) { printf("Failed to fopen %s\n", file_name.c_str()); - throw std::runtime_error("Failed to open file"); + throw std::exception("Failed to open file"); } fprintf(fp, "%s\n", text.c_str()); fclose(fp); diff --git a/decompiler/util/LispPrint.cpp b/decompiler/util/LispPrint.cpp index 103fa42f5a..a2a0877950 100644 --- a/decompiler/util/LispPrint.cpp +++ b/decompiler/util/LispPrint.cpp @@ -72,7 +72,7 @@ void Form::buildStringSimple(std::string &str) { str.append(*token.str); break; default: - throw std::runtime_error("buildStringSimple unknown token kind"); + throw std::exception("buildStringSimple unknown token kind"); } } } @@ -110,7 +110,7 @@ void Form::toTokenList(std::vector &tokens) { tokens.emplace_back(TokenKind::EMPTY_PAIR); break; default: - throw std::runtime_error("unhandled form type in buildSimpleString"); + throw std::exception("unhandled form type in buildSimpleString"); break; } } diff --git a/decompiler/util/LispPrint.h b/decompiler/util/LispPrint.h index 28eaf1f5db..5a537b3021 100644 --- a/decompiler/util/LispPrint.h +++ b/decompiler/util/LispPrint.h @@ -70,7 +70,7 @@ struct FormToken { s.append(*str); break; default: - throw std::runtime_error("toString unknown token kind"); + throw std::exception("toString unknown token kind"); } return s; } diff --git a/decompiler/util/Timer.cpp b/decompiler/util/Timer.cpp index 4ac44ab25c..0a5d895064 100644 --- a/decompiler/util/Timer.cpp +++ b/decompiler/util/Timer.cpp @@ -48,7 +48,7 @@ int64_t Timer::getNs() { clock_gettime(CLOCK_MONOTONIC, &now); #elif _WIN32 clock_gettime_monotonic(&now); -#endif +#endif; return (int64_t)(now.tv_nsec - _startTime.tv_nsec) + 1000000000 * (now.tv_sec - _startTime.tv_sec); -} +} \ No newline at end of file diff --git a/decompiler/util/Timer.h b/decompiler/util/Timer.h index 5972020339..c589657a00 100644 --- a/decompiler/util/Timer.h +++ b/decompiler/util/Timer.h @@ -19,6 +19,8 @@ class Timer { int clock_gettime_monotonic(struct timespec* tv); #endif + + /*! * Start the timer */ @@ -27,7 +29,7 @@ class Timer { /*! * Get milliseconds elapsed */ - double getMs() { return (double)getNs() / 1.e6; } + double getMs() { return (double)getNs() / 1.e6; } double getUs() { return (double)getNs() / 1.e3; } diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 05e0d99744..87e92b9bc4 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -1,9 +1,6 @@ # We define our own compilation flags here. set(CMAKE_CXX_STANDARD 11) -set(CMAKE_CXX_FLAGS "-O0 -ggdb -Wall \ --Wextra -Wcast-align -Wcast-qual -Wdisabled-optimization -Wformat=2 \ --Winit-self -Wmissing-include-dirs -Woverloaded-virtual \ --Wredundant-decls -Wshadow -Wsign-promo ") +set(CMAKE_CXX_FLAGS " ") enable_language(ASM_NASM) set(RUNTIME_SOURCE @@ -55,4 +52,3 @@ add_executable(gk ${RUNTIME_SOURCE}) # can be used to test other things. add_library(runtime ${RUNTIME_SOURCE}) -target_link_libraries(gk pthread) \ No newline at end of file diff --git a/game/kernel/Ptr.h b/game/kernel/Ptr.h index 9764de9fb4..0f9c7811a8 100644 --- a/game/kernel/Ptr.h +++ b/game/kernel/Ptr.h @@ -40,7 +40,7 @@ struct Ptr { if (offset) { return (T*)(g_ee_main_mem + offset); } else { - throw std::runtime_error("Ptr null dereference!"); + throw std::exception("Ptr null dereference!"); } } @@ -51,7 +51,7 @@ struct Ptr { if (offset) { return *(T*)(g_ee_main_mem + offset); } else { - throw std::runtime_error("Ptr null dereference!"); + throw std::exception("Ptr null dereference!"); } } diff --git a/game/kernel/kboot.cpp b/game/kernel/kboot.cpp index 0d06dcf659..e6d53fa857 100644 --- a/game/kernel/kboot.cpp +++ b/game/kernel/kboot.cpp @@ -4,7 +4,7 @@ * DONE! */ -#include +#include #include #include "common/common_types.h" #include "game/sce/libscf.h" @@ -13,7 +13,7 @@ #include "kscheme.h" #include "ksocket.h" #include "klisten.h" - +#include "Windows.h" using namespace ee; // Level to load on boot @@ -135,7 +135,7 @@ void KernelCheckAndDispatch() { SendAck(); } - usleep(1000); // todo - remove this + Sleep(1000); // todo - remove this } } diff --git a/game/kernel/klink.cpp b/game/kernel/klink.cpp index 38eba8ee74..3326b64ba5 100644 --- a/game/kernel/klink.cpp +++ b/game/kernel/klink.cpp @@ -264,7 +264,7 @@ uint32_t cross_seg_dist_link_v3(Ptr link, } else if (size == 8) { *Ptr(offset_of_patch).c() = diff; } else { - throw std::runtime_error("unknown size in cross_seg_dist_link_v3"); + throw std::exception("unknown size in cross_seg_dist_link_v3"); } return 1 + 3 * 4; diff --git a/game/kernel/kmemcard.cpp b/game/kernel/kmemcard.cpp index e8279830dd..111a6d24e7 100644 --- a/game/kernel/kmemcard.cpp +++ b/game/kernel/kmemcard.cpp @@ -1,6 +1,6 @@ /*! * @file kmemcard.cpp - * Memory card interface. Very messy code. + * Memory card interfaces. Very messy code. */ //#include "ps2/SCE_MC.h" diff --git a/game/kernel/kmemcard.h b/game/kernel/kmemcard.h index 3805724d4a..59738a098e 100644 --- a/game/kernel/kmemcard.h +++ b/game/kernel/kmemcard.h @@ -1,6 +1,6 @@ /*! * @file kmemcard.h - * Memory card interface. Very messy code. + * Memory card interfaces. Very messy code. */ diff --git a/game/kernel/kprint.cpp b/game/kernel/kprint.cpp index 59b086a667..f57f5af5c3 100644 --- a/game/kernel/kprint.cpp +++ b/game/kernel/kprint.cpp @@ -338,10 +338,10 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu value = (char)rounder; } else if (!(ru32 >> 31)) { // sign bit value = 0; - throw std::runtime_error("got very large exponent in rounding calculation"); + throw std::exception("got very large exponent in rounding calculation"); } else { value = -1; // happens on NaN's - // throw std::runtime_error("got negative sign bit in rounding calculation"); + // throw std::exception("got negative sign bit in rounding calculation"); } // place number at the end of the buffer and move pointer back @@ -386,10 +386,10 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu value = (char)next_int; } else if (!(ru32 >> 0x1f)) { value = 0; - throw std::runtime_error("got very large exponent in rounding calculation"); + throw std::exception("got very large exponent in rounding calculation"); } else { value = -1; // happens on NaN's - // throw std::runtime_error("got negative sign bit in rounding calculation"); + // throw std::exception("got negative sign bit in rounding calculation"); } *count_chrp = value + '0'; count_chrp++; @@ -401,7 +401,7 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu // however, the rounding flag is always disabled and the rounding code doesn't work. if ((fraction_part != 0.f) && ((flags & 1) != 0)) { start_ptr = round(fraction_part, nullptr, start_ptr, count_chrp - 1, 0, lead_char); - throw std::runtime_error("cvt_float called round!"); + throw std::exception("cvt_float called round!"); } } @@ -553,7 +553,7 @@ char* kitoa(char* buffer, s64 value, u64 base, s32 length, char pad, u32 flag) { * uses C varags, but 128-bit varags don't work, so "format" always passes 0 for quadword printing. */ void kqtoa() { - throw std::runtime_error("kqtoa not implemented"); + throw std::exception("kqtoa not implemented"); } struct format_struct { @@ -791,7 +791,7 @@ s32 format_impl(uint64_t* args) { } kstrinsert(output_ptr, pad, desired_length - print_len); } else { - throw std::runtime_error("unsupported justify in format"); + throw std::exception("unsupported justify in format"); // output_ptr = strend(output_ptr); // while(0 < (desired_length - print_len)) { // char pad = ' '; @@ -842,7 +842,7 @@ s32 format_impl(uint64_t* args) { kstrinsert(output_ptr, pad, desired_length - print_len); } else { - throw std::runtime_error("unsupported justify in format"); + throw std::exception("unsupported justify in format"); // output_ptr = strend(output_ptr); // u32 l140 = 0; // while(l140 < (desired_length - print_len)) { @@ -883,7 +883,7 @@ s32 format_impl(uint64_t* args) { call_method_of_type(in, type, GOAL_PRINT_FUNC); } } else { - throw std::runtime_error("failed to find symbol in format!"); + throw std::exception("failed to find symbol in format!"); } } output_ptr = strend(output_ptr); @@ -904,7 +904,7 @@ s32 format_impl(uint64_t* args) { call_method_of_type(in, type, GOAL_INSPECT_FUNC); } } else { - throw std::runtime_error("failed to find symbol in format!"); + throw std::exception("failed to find symbol in format!"); } } output_ptr = strend(output_ptr); @@ -912,7 +912,7 @@ s32 format_impl(uint64_t* args) { case 'Q': // not yet implemented. hopefully andy gavin finishes this one soon. case 'q': - throw std::runtime_error("nyi q format string"); + throw std::exception("nyi q format string"); break; case 'X': // hex, 64 bit, pad padchar @@ -1009,7 +1009,7 @@ s32 format_impl(uint64_t* args) { precision = 4; float value; if (in < 0) { - throw std::runtime_error("time seconds format error negative.\n"); + throw std::exception("time seconds format error negative.\n"); } else { value = in; } @@ -1025,7 +1025,7 @@ s32 format_impl(uint64_t* args) { default: MsgErr("format: unknown code 0x%02x\n", format_ptr[1]); - throw std::runtime_error("format error"); + throw std::exception("format error"); break; } format_ptr++; @@ -1067,13 +1067,13 @@ s32 format_impl(uint64_t* args) { *PrintPendingLocal3 = 0; return 0; } else if (type == *Ptr>(s7.offset + FIX_SYM_FILE_STREAM_TYPE)) { - throw std::runtime_error("FORMAT into a file stream not supported"); + throw std::exception("FORMAT into a file stream not supported"); } } - throw std::runtime_error("unknown format destination"); + throw std::exception("unknown format destination"); return 0; } - throw std::runtime_error("how did we get here?"); + throw std::exception("how did we get here?"); return 7; } \ No newline at end of file diff --git a/game/kernel/kprint.h b/game/kernel/kprint.h index d26fea7bc3..b7995d7a4d 100644 --- a/game/kernel/kprint.h +++ b/game/kernel/kprint.h @@ -13,6 +13,8 @@ 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 /////////// diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index eff441ee01..6e69334ad8 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -124,7 +124,7 @@ u64 goal_malloc(u32 heap, u32 size, u32 flags, u32 name) { */ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { if (size <= 0) { - throw std::runtime_error("got <= 0 size allocation in alloc_from_heap!"); + throw std::exception("got <= 0 size allocation in alloc_from_heap!"); } // align to 16 bytes (part one) @@ -162,7 +162,7 @@ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { return kmalloc(*Ptr>(heapSymbol), size, KMALLOC_MEMSET, gstr->data()).offset; } else if (heapOffset == FIX_SYM_PROCESS_TYPE) { - throw std::runtime_error("this type of process allocation is not supported yet!\n"); + throw std::exception("this type of process allocation is not supported yet!\n"); // allocate on current process heap // Ptr start = *ptr(getS6() + 0x4c + 8); // Ptr heapEnd = *ptr(getS6() + 0x4c + 4); @@ -178,7 +178,7 @@ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { // alignedSize); return 0; // } } else if (heapOffset == FIX_SYM_SCRATCH) { - throw std::runtime_error("this type of scratchpad allocation is not used!\n"); + throw std::exception("this type of scratchpad allocation is not used!\n"); } else { memset(Ptr(heapSymbol).c(), 0, (size_t)alignedSize); // treat it as a stack address return heapSymbol; @@ -920,7 +920,7 @@ u64 call_method_of_type(u32 arg, Ptr type, u32 method_id) { (*type_tag).offset); } } - // throw std::runtime_error("call_method_of_type failed!\n"); + // throw std::exception("call_method_of_type failed!\n"); printf("[ERROR] call_method_of_type failed!\n"); printf("type is %s\n", info(type->symbol)->str->data()); return arg; @@ -958,7 +958,7 @@ u64 call_method_of_type_arg2(u32 arg, Ptr type, u32 method_id, u32 a1, u32 (*type_tag).offset); } } - throw std::runtime_error("call_method_of_type failed!\n"); + throw std::exception("call_method_of_type failed!\n"); return arg; } @@ -1779,7 +1779,7 @@ s32 InitHeapAndSymbol() { // setup deci2count for message counter. protoBlock.deci2count = intern_from_c("*deci-count*").cast(); - // load stuff for the listener interface + // load stuff for the listener interfaces InitListener(); // Do final initialization, including loading and initializing the engine. diff --git a/game/overlord/fake_iso.cpp b/game/overlord/fake_iso.cpp index 6219f69de7..0f44fca108 100644 --- a/game/overlord/fake_iso.cpp +++ b/game/overlord/fake_iso.cpp @@ -343,6 +343,7 @@ uint32_t FS_LoadMusic(char* name, void* buffer) { (void)name; (void)buffer; assert(false); + return 0; } // TODO FS_LoadSoundBank @@ -350,4 +351,5 @@ uint32_t FS_LoadSoundBank(char* name, void* buffer) { (void)name; (void)buffer; assert(false); + return 0; } \ No newline at end of file diff --git a/game/runtime.cpp b/game/runtime.cpp index 14af11cb9b..5f8cb3b7a3 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -3,9 +3,10 @@ * Setup and launcher for the runtime. */ -#include -#include +#include +#include #include +#include #include "runtime.h" #include "system/SystemThread.h" @@ -43,28 +44,32 @@ namespace { /*! * SystemThread function for running the DECI2 communication with the GOAL compiler. */ -void deci2_runner(SystemThreadInterface& interface) { + + +/* + +void deci2_runner(SystemThreadInterface& interfaces) { // callback function so the server knows when to give up and shutdown - std::function shutdown_callback = [&]() { return interface.get_want_exit(); }; + std::function shutdown_callback = [&]() { return interfaces.get_want_exit(); }; // create and register server - Deci2Server server(shutdown_callback); - ee::LIBRARY_sceDeci2_register(&server); +// Deci2Server server(shutdown_callback); +// ee::LIBRARY_sceDeci2_register(&server); // now its ok to continue with initialization - interface.initialization_complete(); + 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"); + throw std::exception("DECI2 server init failed"); } printf("[DECI2] waiting for listener...\n"); bool saw_listener = false; - while (!interface.get_want_exit()) { + while (!interfaces.get_want_exit()) { if (server.check_for_listener()) { if (!saw_listener) { printf("[DECI2] Connected!\n"); @@ -74,10 +79,12 @@ void deci2_runner(SystemThreadInterface& interface) { server.run(); } else { // no connection yet. Do a sleep so we don't spam checking the listener. - usleep(50000); + Sleep(1000); } } } +*/ + // EE System constexpr int EE_MAIN_MEM_SIZE = 128 * (1 << 20); // 128 MB, same as PS2 TOOL @@ -95,7 +102,7 @@ constexpr int GOAL_ARGC = 4; /*! * SystemThread Function for the EE (PS2 Main CPU) */ -void ee_runner(SystemThreadInterface& interface) { +void ee_runner(SystemThreadInterface& interfaces) { // Allocate Main RAM. Must have execute enabled. if (EE_MEM_LOW_MAP) { g_ee_main_mem = @@ -109,7 +116,7 @@ void ee_runner(SystemThreadInterface& interface) { if (g_ee_main_mem == (u8*)(-1)) { printf(" Failed to initialize main memory! %s\n", strerror(errno)); - interface.initialization_complete(); + interfaces.initialization_complete(); return; } @@ -118,7 +125,7 @@ void ee_runner(SystemThreadInterface& interface) { (double)EE_MAIN_MEM_SIZE / (1 << 20)); printf("[EE] Initialization complete!\n"); - interface.initialization_complete(); + interfaces.initialization_complete(); printf("[EE] Run!\n"); memset((void*)g_ee_main_mem, 0, EE_MAIN_MEM_SIZE); @@ -145,13 +152,13 @@ void ee_runner(SystemThreadInterface& interface) { munmap(g_ee_main_mem, EE_MAIN_MEM_SIZE); // after main returns, trigger a shutdown. - interface.trigger_shutdown(); + interfaces.trigger_shutdown(); } /*! * SystemThread function for running the IOP (separate I/O Processor) */ -void iop_runner(SystemThreadInterface& interface) { +void iop_runner(SystemThreadInterface& interfaces) { IOP iop; printf("\n\n\n[IOP] Restart!\n"); iop.reset_allocator(); @@ -174,7 +181,7 @@ void iop_runner(SystemThreadInterface& interface) { // ssound // stream - interface.initialization_complete(); + interfaces.initialization_complete(); printf("[IOP] Wait for OVERLORD to be started...\n"); iop.wait_for_overlord_start_cmd(); @@ -195,7 +202,7 @@ void iop_runner(SystemThreadInterface& interface) { iop.signal_overlord_init_finish(); // IOP Kernel loop - while (!interface.get_want_exit() && !iop.want_exit) { + while (!interfaces.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(); @@ -232,8 +239,8 @@ void exec_runtime(int argc, char** argv) { // step 3: start the EE! iop_thread.start(iop_runner); ee_thread.start(ee_runner); - deci_thread.start(deci2_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! diff --git a/game/sce/deci2.cpp b/game/sce/deci2.cpp index 03c2f7c39a..75b7a076d5 100644 --- a/game/sce/deci2.cpp +++ b/game/sce/deci2.cpp @@ -1,7 +1,7 @@ /*! * @file deci2.cpp * Implementation of SCE DECI2 library. - */ + #include #include @@ -19,9 +19,9 @@ Deci2Driver* sending_driver; // currently sending protocol drive ::Deci2Server* server; // the server to send data to } // namespace -/*! + * Initialize the library. - */ + void LIBRARY_INIT_sceDeci2() { // reset protocols for (auto& p : protocols) { @@ -34,7 +34,7 @@ void LIBRARY_INIT_sceDeci2() { /*! * Run any pending requested sends. - */ + void LIBRARY_sceDeci2_run_sends() { for (auto& prot : protocols) { if (prot.active && prot.pending_send == 'H') { @@ -49,7 +49,7 @@ void LIBRARY_sceDeci2_run_sends() { /*! * Register a Deci2Server with this library. - */ + void LIBRARY_sceDeci2_register(::Deci2Server* s) { server = s; } @@ -58,7 +58,7 @@ void LIBRARY_sceDeci2_register(::Deci2Server* s) { * Open a new socket with given protocol number and handler. * The "opt" pointer is passed to the handler function. * 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; @@ -82,7 +82,7 @@ s32 sceDeci2Open(u16 protocol, void* opt, void (*handler)(s32 event, s32 param, /*! * Deactivate a DECI2 protocol by socket descriptor. - */ + s32 sceDeci2Close(s32 s) { assert(s - 1 < protocol_count); protocols[s - 1].active = false; @@ -91,7 +91,7 @@ s32 sceDeci2Close(s32 s) { /*! * Start a send. - */ + s32 sceDeci2ReqSend(s32 s, char dest) { assert(s - 1 < protocol_count); auto& proto = protocols[s - 1]; @@ -102,7 +102,7 @@ s32 sceDeci2ReqSend(s32 s, char dest) { /*! * Do a receive from socket s into buf of size len. * Returns after data is copied. - */ + s32 sceDeci2ExRecv(s32 s, void* buf, u16 len) { assert(s - 1 < protocol_count); protocols[s - 1].recv_size = len; @@ -118,7 +118,7 @@ s32 sceDeci2ExRecv(s32 s, void* buf, u16 len) { /*! * Do a send. - */ + s32 sceDeci2ExSend(s32 s, void* buf, u16 len) { assert(s - 1 < protocol_count); if (!sending_driver) { @@ -133,4 +133,6 @@ s32 sceDeci2ExSend(s32 s, void* buf, u16 len) { return len; } -} // namespace ee \ No newline at end of file +} // namespace ee + +*/ \ No newline at end of file diff --git a/game/sce/iop.cpp b/game/sce/iop.cpp index 6f954a0183..002d8b8179 100644 --- a/game/sce/iop.cpp +++ b/game/sce/iop.cpp @@ -201,12 +201,12 @@ s32 CreateSema(SemaParam* param) { s32 WaitSema(s32 sema) { (void)sema; - throw std::runtime_error("NYI"); + throw std::exception("NYI"); } s32 SignalSema(s32 sema) { (void)sema; - throw std::runtime_error("NYI"); + throw std::exception("NYI"); } s32 WakeupThread(s32 thid) { diff --git a/game/sce/stubs.cpp b/game/sce/stubs.cpp index 4e218a4739..7f92ade562 100644 --- a/game/sce/stubs.cpp +++ b/game/sce/stubs.cpp @@ -6,33 +6,33 @@ namespace ee { s32 sceOpen(const char *filename, s32 flag) { (void)filename; (void)flag; - throw std::runtime_error("sceOpen NYI"); + throw std::exception("sceOpen NYI"); } s32 sceClose(s32 fd) { (void)fd; - throw std::runtime_error("sceClose NYI"); + throw std::exception("sceClose NYI"); } s32 sceRead(s32 fd, void *buf, s32 nbyte) { (void)fd; (void)buf; (void)nbyte; - throw std::runtime_error("sceRead NYI"); + throw std::exception("sceRead NYI"); } s32 sceWrite(s32 fd, const void *buf, s32 nbyte) { (void)fd; (void)buf; (void)nbyte; - throw std::runtime_error("sceWrite NYI"); + throw std::exception("sceWrite NYI"); } s32 sceLseek(s32 fd, s32 offset, s32 where) { (void)fd; (void)offset; (void)where; - throw std::runtime_error("sceLseek NYI"); + throw std::exception("sceLseek NYI"); } int scePadPortOpen(int port, int slot, void* data) { diff --git a/game/system/Deci2Server.cpp b/game/system/Deci2Server.cpp index 9b2a29f942..21b9e89bba 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -2,12 +2,11 @@ * @file Deci2Server.cpp * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target - */ + #include -#include -#include -#include +#include +#include #include #include @@ -15,6 +14,8 @@ #include "common/versions.h" #include "Deci2Server.h" +typedef int socklen_t; + Deci2Server::Deci2Server(std::function shutdown_callback) { buffer = new char[BUFFER_SIZE]; want_exit = std::move(shutdown_callback); @@ -41,7 +42,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) { @@ -49,16 +50,16 @@ bool Deci2Server::init() { return false; } - int opt = 1; - if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + const char opt = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST, &opt, sizeof(opt))) { printf("[Deci2Server] Failed to setsockopt 1\n"); close(server_fd); server_fd = -1; return false; } - int one = 1; - if (setsockopt(server_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { + const char one = 1; + if (setsockopt(server_fd, SOL_SOCKET, TCP_NODELAY, &one, sizeof(one))) { printf("[Deci2Server] Failed to setsockopt 2\n"); close(server_fd); server_fd = -1; @@ -103,7 +104,7 @@ bool Deci2Server::init() { /*! * Return true if the listener is connected. - */ + bool Deci2Server::check_for_listener() { if (server_connected) { if (accept_thread_running) { @@ -118,7 +119,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) { @@ -139,14 +140,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(); } @@ -154,7 +155,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; @@ -167,7 +168,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; @@ -214,7 +215,7 @@ void Deci2Server::run() { printf("[DECI2] Warning: no handler for this message, ignoring...\n"); unlock(); return; - // throw std::runtime_error("no handler!"); + // throw std::exception("no handler!"); } auto& driver = d2_drivers[handler]; @@ -249,16 +250,18 @@ 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) { - u32 versions[2] = {versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR}; + const char versions = {versions::GOAL_VERSION_MAJOR}; send(new_sock, &versions, 8, 0); // todo, check result? server_connected = true; return; } } } + +*/ \ No newline at end of file diff --git a/game/system/Deci2Server.h b/game/system/Deci2Server.h index b53547a10c..5b5808e678 100644 --- a/game/system/Deci2Server.h +++ b/game/system/Deci2Server.h @@ -2,12 +2,12 @@ * @file Deci2Server.h * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target - */ + #ifndef JAK1_DECI2SERVER_H #define JAK1_DECI2SERVER_H -#include +#include #include #include #include @@ -54,3 +54,5 @@ class Deci2Server { #endif // JAK1_DECI2SERVER_H + +*/ \ No newline at end of file diff --git a/game/system/IOP_Kernel.cpp b/game/system/IOP_Kernel.cpp index ffa2a9cbad..291aaa3381 100644 --- a/game/system/IOP_Kernel.cpp +++ b/game/system/IOP_Kernel.cpp @@ -7,9 +7,9 @@ * Create a new thread. Will not run the thread. */ s32 IOP_Kernel::CreateThread(std::string name, u32 (*func)()) { - if(_currentThread != -1) throw std::runtime_error("tried to create thread from thread"); + if(_currentThread != -1) throw std::exception("tried to create thread from thread"); u32 ID = (u32)_nextThID++; - if(threads.size() != ID) throw std::runtime_error("thread number error?"); + if(threads.size() != ID) throw std::exception("thread number error?"); // add entry threads.emplace_back(name, func, ID, this); // setup the thread! @@ -19,7 +19,7 @@ s32 IOP_Kernel::CreateThread(std::string name, u32 (*func)()) { if(func) { _currentThread = ID; // create OS thread, will run the setupThread function - threads.back().thread = new std::thread(&IOP_Kernel::setupThread, this, ID); + //threads.back().thread = new std::thread(&IOP_Kernel::setupThread, this, ID); --- quick hack to make the build // wait for thread to finish setup. threads.back().waitForReturnToKernel(); // ensure we are back in the kernel. @@ -47,7 +47,7 @@ void IOP_Kernel::setupThread(s32 id) { threads.at(id).waitForDispatch(); // printf("[IOP Kernel] Thread %s first dispatch!\n", threads.at(id).name.c_str()); if(_currentThread != id) { - throw std::runtime_error("the wrong thread has run!\n"); + throw std::exception("the wrong thread has run!\n"); } (threads.at(id).function)(); printf("Thread %s has returned!\n", threads.at(id).name.c_str()); @@ -59,7 +59,7 @@ void IOP_Kernel::setupThread(s32 id) { * Run a thread (call from kernel) */ void IOP_Kernel::runThread(s32 id) { - if(_currentThread != -1) throw std::runtime_error("tried to runThread in a thread"); + if(_currentThread != -1) throw std::exception("tried to runThread in a thread"); _currentThread = id; threads.at(id).dispatch(); threads.at(id).waitForReturnToKernel(); @@ -76,7 +76,7 @@ void IOP_Kernel::SuspendThread() { threads.at(oldThread).returnToKernel(); threads.at(oldThread).waitForDispatch(); if(_currentThread != oldThread) { - throw std::runtime_error("bad resume"); + throw std::exception("bad resume"); } } @@ -128,7 +128,7 @@ void IOP_Kernel::dispatchAll() { */ void IopThreadRecord::returnToKernel() { runThreadReady = false; - if(kernel->getCurrentThread() != thID) throw std::runtime_error("tried to sleep the wrong thread!"); + if(kernel->getCurrentThread() != thID) throw std::exception("tried to sleep the wrong thread!"); { std::lock_guard lck(*threadToKernelMutex); @@ -142,7 +142,7 @@ void IopThreadRecord::returnToKernel() { */ void IopThreadRecord::dispatch() { syscallReady = false; - if(kernel->getCurrentThread() != thID) throw std::runtime_error("tried to dispatch the wrong thread!"); + if(kernel->getCurrentThread() != thID) throw std::exception("tried to dispatch the wrong thread!"); { std::lock_guard lck(*kernelToThreadMutex); runThreadReady = true; @@ -163,7 +163,7 @@ void IopThreadRecord::waitForReturnToKernel() { * Thread waits for kernel to dispatch it. */ void IopThreadRecord::waitForDispatch() { - //if(kernel->getCurrentThread() == -1) throw std::runtime_error("tried to suspend main!\n"); + //if(kernel->getCurrentThread() == -1) throw std::exception("tried to suspend main!\n"); std::unique_lock lck(*kernelToThreadMutex); kernelToThreadCV->wait(lck, [this]{return runThreadReady;}); //runThreadReady = false; diff --git a/game/system/IOP_Kernel.h b/game/system/IOP_Kernel.h index d05083dbc8..c811770be5 100644 --- a/game/system/IOP_Kernel.h +++ b/game/system/IOP_Kernel.h @@ -98,7 +98,7 @@ public: * Resume the kernel. */ void returnToKernel() { - if(_currentThread < 0) throw std::runtime_error("tried to return to kernel not in a thread"); + if(_currentThread < 0) throw std::exception("tried to return to kernel not in a thread"); threads[_currentThread].returnToKernel(); } @@ -129,7 +129,7 @@ public: return -0x1a9; } // printf("poll %d %ld\n", mbx, mbxs.size()); - if(mbx >= (s32) mbxs.size()) throw std::runtime_error("invalid PollMbx"); + if(mbx >= (s32) mbxs.size()) throw std::exception("invalid PollMbx"); s32 gotSomething = mbxs[mbx].empty() ? 0 : 1; if(gotSomething) { void* thing = mbxs[mbx].front(); @@ -146,7 +146,7 @@ public: * Push something into a mbx */ s32 SendMbx(s32 mbx, void* value) { - if(mbx >= (s32) mbxs.size()) throw std::runtime_error("invalid SendMbx"); + if(mbx >= (s32) mbxs.size()) throw std::exception("invalid SendMbx"); mbxs[mbx].push(value); // printf("push into messagebox %d %p\n", mbx, value); // printf("mbx size %ld\n", mbxs.size()); diff --git a/game/system/SystemThread.cpp b/game/system/SystemThread.cpp index aa49932491..1860f59507 100644 --- a/game/system/SystemThread.cpp +++ b/game/system/SystemThread.cpp @@ -13,7 +13,7 @@ */ SystemThread& SystemThreadManager::create_thread(const std::string& name) { if (thread_count >= MAX_SYSTEM_THREADS) { - throw std::runtime_error("Out of System Threads! Please increase MAX_SYSTEM_THREADS"); + throw std::exception("Out of System Threads! Please increase MAX_SYSTEM_THREADS"); } auto& thread = threads[thread_count]; @@ -71,8 +71,8 @@ void SystemThreadManager::join() { */ void* bootstrap_thread_func(void* x) { SystemThread* thd = (SystemThread*)x; - SystemThreadInterface interface(thd); - thd->function(interface); + SystemThreadInterface interfaces(thd); + thd->function(interfaces); printf("[SYSTEM] Thread %s is returning\n", thd->name.c_str()); return nullptr; } @@ -83,7 +83,7 @@ void* bootstrap_thread_func(void* x) { void SystemThread::start(std::function f) { printf("# Initialize %s...\n", name.c_str()); function = f; - pthread_create(&thread, nullptr, bootstrap_thread_func, this); + std::thread(thread); running = true; // and wait for initialization @@ -100,7 +100,7 @@ void SystemThread::start(std::function f) { */ void SystemThread::join() { void* x; - pthread_join(thread, &x); + thread.join(); running = false; } @@ -135,33 +135,3 @@ bool SystemThreadInterface::get_want_exit() const { void SystemThreadInterface::trigger_shutdown() { thread.manager->shutdown(); } - -#include -#include - -/*! - * 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; - } -} \ No newline at end of file diff --git a/game/system/SystemThread.h b/game/system/SystemThread.h index 0d0bafac0d..7744c0afb7 100644 --- a/game/system/SystemThread.h +++ b/game/system/SystemThread.h @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -22,7 +21,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 interface with intitialization_complete(). + * Once the thread is ready, it should tell the interfaces 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. @@ -40,7 +39,7 @@ private: friend void* bootstrap_thread_func(void* thd); std::string name = "invalid"; - pthread_t thread; + std::thread thread; SystemThreadManager* manager; std::function function; bool initialization_complete = false; @@ -57,7 +56,7 @@ private: }; /*! - * The interface used by a thread in the runtime. + * The interfaces used by a thread in the runtime. */ class SystemThreadInterface { public: diff --git a/game/system/Timer.h b/game/system/Timer.h index 21bfbce8ce..fd2b1667dd 100644 --- a/game/system/Timer.h +++ b/game/system/Timer.h @@ -12,7 +12,6 @@ public: } void start() { - clock_gettime(CLOCK_MONOTONIC, &_startTime); } double getMs() { @@ -21,7 +20,6 @@ public: int64_t getNs() { struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); return (int64_t)(now.tv_nsec - _startTime.tv_nsec) + 1000000000 * (now.tv_sec - _startTime.tv_sec); } diff --git a/game/system/deci_common.h b/game/system/deci_common.h index b3f7248064..c8a73cceee 100644 --- a/game/system/deci_common.h +++ b/game/system/deci_common.h @@ -1,6 +1,7 @@ #ifndef JAK_DECIM_COMMON_H #define JAK_DECIM_COMMON_H #include "common/common_types.h" + struct Deci2Driver { u16 protocol = 0; void* opt = nullptr; diff --git a/game/system/iop_thread.cpp b/game/system/iop_thread.cpp index 1a07a5b1b5..1dd81d1e01 100644 --- a/game/system/iop_thread.cpp +++ b/game/system/iop_thread.cpp @@ -1,6 +1,6 @@ #include "iop_thread.h" -#include +#include #include "SystemThread.h" //#include "shared_config.h" //#include "ps2/SCE_IOP.h" @@ -95,7 +95,7 @@ IOP::~IOP() { reset_allocator(); } -//void launch_iop(SystemThreadInterface& interface) { +//void launch_iop(SystemThreadInterface& interfaces) { // IOP iop; // // printf("\n\n\n[IOP] Restart!\n"); @@ -118,7 +118,7 @@ IOP::~IOP() { // //// SCE_IOP::PS2_RegisterIOP(&iop); //// PS2_RegisterIOP_EE(&iop); -// interface.initialization_complete(); +// interfaces.initialization_complete(); // // printf("[IOP] Wait for OVERLORD to be started...\n"); // iop.wait_for_overlord_start_cmd(); @@ -140,7 +140,7 @@ IOP::~IOP() { // iop.signal_overlord_init_finish(); // // // IOP Kernel loop -// while(!interface.get_want_exit() && !iop.want_exit) { +// while(!interfaces.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(); diff --git a/goalc/emitter/CodeTester.cpp b/goalc/emitter/CodeTester.cpp index 6a9a9a6e6f..676841797f 100644 --- a/goalc/emitter/CodeTester.cpp +++ b/goalc/emitter/CodeTester.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "CodeTester.h" #include "Instruction.h" diff --git a/goalc/goos/Interpreter.cpp b/goalc/goos/Interpreter.cpp index 26bbc94852..64bb0ffc57 100644 --- a/goalc/goos/Interpreter.cpp +++ b/goalc/goos/Interpreter.cpp @@ -137,8 +137,8 @@ void Interpreter::execute_repl() { * for debugging. */ void Interpreter::throw_eval_error(const Object& o, const std::string& err) { - throw std::runtime_error("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + - reader.db.get_info_for(o)); + // throw std::exception("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + + // reader.db.get_info_for(o)); } /*! @@ -151,7 +151,7 @@ Object Interpreter::eval_with_rewind(const Object& obj, Object result = EmptyListObject::make_new(); try { result = eval(obj, env); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { if (!disable_printing) { printf("-----------------------------------------\n"); printf("From object %s\nat %s\n", obj.inspect().c_str(), reader.db.get_info_for(obj).c_str()); diff --git a/goalc/goos/InterpreterEval.cpp b/goalc/goos/InterpreterEval.cpp index 8f73c46052..183566402c 100644 --- a/goalc/goos/InterpreterEval.cpp +++ b/goalc/goos/InterpreterEval.cpp @@ -49,7 +49,7 @@ Object Interpreter::eval_read(const Object& form, try { return reader.read_from_string(args.unnamed.at(0).as_string()->data); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("reader error inside of read:\n") + e.what()); } @@ -67,7 +67,7 @@ Object Interpreter::eval_read_file(const Object& form, try { return reader.read_from_file(args.unnamed.at(0).as_string()->data); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("reader error inside of read-file:\n") + e.what()); } return EmptyListObject::make_new(); @@ -85,13 +85,13 @@ Object Interpreter::eval_load_file(const Object& form, Object o; try { o = reader.read_from_file(args.unnamed.at(0).as_string()->data); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("reader error inside of load-file:\n") + e.what()); } try { return eval_with_rewind(o, global_environment.as_env()); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("eval error inside of load-file:\n") + e.what()); } return EmptyListObject::make_new(); diff --git a/goalc/goos/Object.cpp b/goalc/goos/Object.cpp index 1023ff3581..649947d1f5 100644 --- a/goalc/goos/Object.cpp +++ b/goalc/goos/Object.cpp @@ -33,7 +33,7 @@ std::string object_type_to_string(ObjectType type) { case ObjectType::ENVIRONMENT: return "[environment]"; default: - throw std::runtime_error("unknown object type in object_type_to_string"); + throw std::exception("unknown object type in object_type_to_string"); } } @@ -151,7 +151,7 @@ bool Object::operator==(const Object& other) const { } default: - throw std::runtime_error("equality not implemented for " + print()); + //throw std::exception("equality not implemented for " + print()); } } diff --git a/goalc/goos/Object.h b/goalc/goos/Object.h index 926014bc6e..bf45ba384d 100644 --- a/goalc/goos/Object.h +++ b/goalc/goos/Object.h @@ -222,78 +222,78 @@ class Object { std::shared_ptr as_pair() const { if (type != ObjectType::PAIR) { - throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_pair called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_env() const { if (type != ObjectType::ENVIRONMENT) { - throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print()); + // throw std::exception("as_env called on a " + object_type_to_string(type) + " " + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_symbol() const { if (type != ObjectType::SYMBOL) { - throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_symbol called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_string() const { if (type != ObjectType::STRING) { - throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_string called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_lambda() const { if (type != ObjectType::LAMBDA) { - throw std::runtime_error("as_lambda called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_lambda called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_macro() const { if (type != ObjectType::MACRO) { - throw std::runtime_error("as_macro called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_macro called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_array() const { if (type != ObjectType::ARRAY) { - throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_array called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } IntType& as_int() { if (type != ObjectType::INTEGER) { - throw std::runtime_error("as_int called on a " + object_type_to_string(type) + " " + print()); + // throw std::exception("as_int called on a " + object_type_to_string(type) + " " + print()); } return integer_obj.value; } FloatType& as_float() { if (type != ObjectType::FLOAT) { - throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_float called on a " + object_type_to_string(type) + " " + + // print()); } return float_obj.value; } char& as_char() { if (type != ObjectType::CHAR) { - throw std::runtime_error("as_char called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_char called on a " + object_type_to_string(type) + " " + + // print()); } return char_obj.value; } diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index 7e195a73cc..33f1182d7b 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -102,7 +102,7 @@ Reader::Reader() { // find the source directory auto result = std::getenv("NEXT_DIR"); if (!result) { - throw std::runtime_error( + throw std::exception( "Environment variable NEXT_DIR is not set. Please set this to point to next/"); } @@ -588,7 +588,7 @@ bool Reader::try_token_as_binary(const Token& tok, Object& obj) { for (uint32_t i = 2; i < tok.text.size(); i++) { if (value & (0x8000000000000000)) { - throw std::runtime_error("overflow in binary constant: " + tok.text); + throw std::exception("overflow in binary constant: " + tok.text); } value <<= 1u; @@ -628,7 +628,7 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::runtime_error("The number " + tok.text + " cannot be a hexadecimal constant"); + throw std::exception("The number " + tok.text + " cannot be a hexadecimal constant"); } } return false; @@ -662,7 +662,7 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::runtime_error("The number " + tok.text + " cannot be an integer constant"); + throw std::exception("The number " + tok.text + " cannot be an integer constant"); } } return false; @@ -697,7 +697,7 @@ bool Reader::try_token_as_char(const Token& tok, Object& obj) { * Used for reader errors, like "missing close paren" or similar. */ void Reader::throw_reader_error(TextStream& here, const std::string& err, int seek_offset) { - throw std::runtime_error("Reader error:\n" + err + "\nat " + + throw std::exception("Reader error:\n" + err + "\nat " + db.get_info_for(here.text, here.seek + seek_offset)); } diff --git a/goalc/listener/Deci2Server.cpp b/goalc/listener/Deci2Server.cpp index 9b2a29f942..d4d8eafb31 100644 --- a/goalc/listener/Deci2Server.cpp +++ b/goalc/listener/Deci2Server.cpp @@ -214,7 +214,7 @@ void Deci2Server::run() { printf("[DECI2] Warning: no handler for this message, ignoring...\n"); unlock(); return; - // throw std::runtime_error("no handler!"); + // throw std::exception("no handler!"); } auto& driver = d2_drivers[handler]; diff --git a/goalc/listener/Deci2Server.h b/goalc/listener/Deci2Server.h index 45e3727851..c07e649711 100644 --- a/goalc/listener/Deci2Server.h +++ b/goalc/listener/Deci2Server.h @@ -2,7 +2,7 @@ * @file Deci2Server.h * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target - */ + #ifndef JAK1_DECI2SERVER_H #define JAK1_DECI2SERVER_H @@ -55,3 +55,5 @@ class Deci2Server { #endif // JAK1_DECI2SERVER_H + +*/ diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 72265faaba..8ab1c4563a 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -1,12 +1,11 @@ /*! * @file Listener.cpp * The Listener can connect to a Deci2Server for debugging. - */ + #include -#include -#include -#include +#include +#include #include #include "Listener.h" #include "common/versions.h" @@ -40,13 +39,11 @@ bool Listener::is_connected() const { return m_connected; } -/*! - * Attempt to connect to the target. If the target isn't running, this should fail quickly. - * Returns true if successfully 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!"); + throw std::exception("attempted a Listener::connect_to_target when already connected!"); } if (socket_fd >= 0) { @@ -73,8 +70,8 @@ bool Listener::connect_to_target(const std::string& ip, int port) { } // set nodelay, which makes small rapid messages faster, but large messages slower - int one = 1; - if (setsockopt(socket_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { + const char one = 1; + if (setsockopt(socket_fd, SOL_SOCKET, TCP_NODELAY, &one, sizeof(one))) { printf("[Listener] failed to TCP_NODELAY\n"); close(socket_fd); socket_fd = -1; @@ -144,7 +141,15 @@ 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 @@ -239,3 +244,5 @@ void Listener::receive_func() { } } // namespace listener + +*/ diff --git a/goalc/util/file_io.cpp b/goalc/util/file_io.cpp index d6b35e1735..44b93035c5 100644 --- a/goalc/util/file_io.cpp +++ b/goalc/util/file_io.cpp @@ -7,7 +7,7 @@ namespace util { std::string read_text_file(const std::string& path) { std::ifstream file(path); if (!file.good()) { - throw std::runtime_error("couldn't open " + path); + throw std::exception("couldn't open "); } std::stringstream ss; ss << file.rdbuf(); diff --git a/mman.c b/mman.c new file mode 100644 index 0000000000..486ed94d88 --- /dev/null +++ b/mman.c @@ -0,0 +1,180 @@ + +#include +#include +#include + +#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; +} diff --git a/test/all_jak1_symbols.cpp b/test/all_jak1_symbols.cpp index 9004c70890..e0089acc88 100644 --- a/test/all_jak1_symbols.cpp +++ b/test/all_jak1_symbols.cpp @@ -7748,7 +7748,7 @@ const char* all_syms[7941] = {"ripple-for-lava", "list-control", "sunken-pipegame-idle", "anim-test-edit-seq-insert-item", - "anim-tester-interface", + "anim-tester-interfaces", "anim-tester-adjust-frame", "extra-radius", "*volume-descriptor*", diff --git a/third-party/fmt/format-inl.h b/third-party/fmt/format-inl.h index d8c9c8a5ee..db590a275e 100644 --- a/third-party/fmt/format-inl.h +++ b/third-party/fmt/format-inl.h @@ -226,8 +226,8 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str, error_code_ = err_code; memory_buffer buffer; format_system_error(buffer, err_code, vformat(format_str, args)); - std::runtime_error& base = *this; - base = std::runtime_error(to_string(buffer)); + std::exception& base = *this; +// base = std::exception(to_string(buffer)); } namespace detail { @@ -1175,7 +1175,7 @@ int snprintf_float(T value, int precision, float_specs specs, auto capacity = buf.capacity() - offset; #ifdef FMT_FUZZ if (precision > 100000) - throw std::runtime_error( + throw std::exception( "fuzz mode - avoid large allocation inside snprintf"); #endif // Suppress the warning about a nonliteral format string. @@ -1327,7 +1327,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { auto cp = uint32_t(); auto error = 0; p = utf8_decode(p, &cp, &error); - if (error != 0) FMT_THROW(std::runtime_error("invalid utf8")); + if (error != 0) FMT_THROW(std::exception("invalid utf8")); if (cp <= 0xFFFF) { buffer_.push_back(static_cast(cp)); } else { diff --git a/third-party/fmt/format.cc b/third-party/fmt/format.cc index a64a1f3893..42ea06ed74 100644 --- a/third-party/fmt/format.cc +++ b/third-party/fmt/format.cc @@ -15,7 +15,7 @@ int format_float(char* buf, std::size_t size, const char* format, int precision, T value) { #ifdef FMT_FUZZ if (precision > 100000) - throw std::runtime_error( + throw std::exception( "fuzz mode - avoid large allocation inside snprintf"); #endif // Suppress the warning about nonliteral format string. diff --git a/third-party/fmt/format.h b/third-party/fmt/format.h index 17509b7b45..b312bb4bee 100644 --- a/third-party/fmt/format.h +++ b/third-party/fmt/format.h @@ -683,7 +683,7 @@ class basic_memory_buffer : public detail::buffer { template void basic_memory_buffer::grow(size_t size) { #ifdef FMT_FUZZ - if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much"); + if (size > 5000) throw std::exception("fuzz mode - won't grow that much"); #endif size_t old_capacity = this->capacity(); size_t new_capacity = old_capacity + old_capacity / 2; @@ -710,11 +710,11 @@ struct is_contiguous> : std::true_type { /** A formatting error such as invalid format string. */ FMT_CLASS_API -class FMT_API format_error : public std::runtime_error { +class FMT_API format_error : public std::exception { public: - explicit format_error(const char* message) : std::runtime_error(message) {} - explicit format_error(const std::string& message) - : std::runtime_error(message) {} + explicit format_error(const char* message) : std::exception(message) {} + explicit format_error(const std::string& message); + // : std::exception(message) {} format_error(const format_error&) = default; format_error& operator=(const format_error&) = default; format_error(format_error&&) = default; @@ -1145,7 +1145,7 @@ template class float_writer { } #ifdef FMT_FUZZ if (num_zeros > 5000) - throw std::runtime_error("fuzz mode - avoiding excessive cpu use"); + throw std::exception("fuzz mode - avoiding excessive cpu use"); #endif it = std::fill_n(it, num_zeros, static_cast('0')); } @@ -2952,14 +2952,14 @@ using arg_formatter FMT_DEPRECATED_ALIAS = for example a file opening error. */ FMT_CLASS_API -class FMT_API system_error : public std::runtime_error { +class FMT_API system_error : public std::exception { private: void init(int err_code, string_view format_str, format_args args); protected: int error_code_; - system_error() : std::runtime_error(""), error_code_(0) {} + system_error() : std::exception(""), error_code_(0) {} public: /** @@ -2982,7 +2982,7 @@ class FMT_API system_error : public std::runtime_error { */ template system_error(int error_code, string_view message, const Args&... args) - : std::runtime_error("") { + : std::exception("") { init(error_code, message, make_format_args(args...)); } system_error(const system_error&) = default; diff --git a/third-party/json.hpp b/third-party/json.hpp index 9c66a8457f..54e5f75365 100644 --- a/third-party/json.hpp +++ b/third-party/json.hpp @@ -70,7 +70,7 @@ SOFTWARE. #include // exception -#include // runtime_error +#include // exception #include // to_string // #include @@ -92,7 +92,7 @@ struct position_t /// the number of lines read std::size_t lines_read = 0; - /// conversion to size_t to preserve SAX interface + /// conversion to size_t to preserve SAX interfaces constexpr operator size_t() const { return chars_read_total; @@ -2339,7 +2339,7 @@ Subclasses: @internal @note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. + `std::exception` which can cope with arbitrary-length error messages. Intermediate strings are built with static functions and then passed to the actual constructor. @endinternal @@ -2373,7 +2373,7 @@ class exception : public std::exception private: /// an exception object as storage for error messages - std::runtime_error m; + std::exception m; }; /*! @@ -4823,7 +4823,7 @@ class input_stream_adapter std::char_traits::int_type get_character() { auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interface. + // set eof manually, as we don't use the istream interfaces. if (JSON_HEDLEY_UNLIKELY(res == EOF)) { is->clear(is->rdstate() | std::ios::eofbit); @@ -5191,9 +5191,9 @@ namespace nlohmann { /*! -@brief SAX interface +@brief SAX interfaces -This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +This class describes the SAX interfaces used by @ref nlohmann::json::sax_parse. Each function is called in different situations while the input is parsed. The boolean return value informs the parser whether to continue processing the input. @@ -5314,7 +5314,7 @@ namespace detail /*! @brief SAX implementation to create a JSON value from SAX events -This class implements the @ref json_sax interface and processes the SAX events +This class implements the @ref json_sax interfaces and processes the SAX events to create a JSON value which makes it basically a DOM parser. The structure or hierarchy of the JSON value is managed by the stack `ref_stack` which contains a pointer to the respective array or object for each recursion depth. @@ -7198,7 +7198,7 @@ scan_number_done: /* @brief get next character from the input - This function provides the interface to the used input adapter. It does + This function provides the interfaces to the used input adapter. It does not throw in case the input reached EOF, but returns a `std::char_traits::eof()` in that case. Stores the scanned characters for use in error messages. @@ -9881,7 +9881,7 @@ class binary_reader /*! @brief get next character from the input - This function provides the interface to the used input adapter. It does + This function provides the interfaces to the used input adapter. It does not throw in case the input reached EOF, but returns a -'ve valued `std::char_traits::eof()` in that case. @@ -10184,7 +10184,7 @@ class parser } /*! - @brief public parser interface + @brief public parser interfaces @param[in] strict whether to expect the last token to be EOF @param[in,out] result parsed JSON value @@ -10249,7 +10249,7 @@ class parser } /*! - @brief public accept interface + @brief public accept interfaces @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text @@ -12628,7 +12628,7 @@ namespace nlohmann { namespace detail { -/// abstract output adapter interface +/// abstract output adapter interfaces template struct output_adapter_protocol { virtual void write_character(CharType c) = 0; @@ -16724,7 +16724,7 @@ class basic_json using initializer_list_t = std::initializer_list>; using input_format_t = detail::input_format_t; - /// SAX interface type, see @ref nlohmann::json_sax + /// SAX interfaces type, see @ref nlohmann::json_sax using json_sax_t = json_sax; //////////////// @@ -21253,7 +21253,7 @@ class basic_json element as string (see example). @param[in] ref reference to a JSON value - @return iteration proxy object wrapping @a ref with an interface to use in + @return iteration proxy object wrapping @a ref with an interfaces to use in range-based for loops @liveexample{The following code shows how the wrapper is used,iterator_wrapper} @@ -21341,7 +21341,7 @@ class basic_json for more information. - @return iteration proxy object wrapping @a ref with an interface to use in + @return iteration proxy object wrapping @a ref with an interfaces to use in range-based for loops @liveexample{The following code shows how the function is used.,items} @@ -23249,7 +23249,7 @@ class basic_json /*! @brief generate SAX events - The SAX event lister must follow the interface of @ref json_sax. + The SAX event lister must follow the interfaces of @ref json_sax. This function reads from a compatible input. Examples are: - an std::istream object diff --git a/third-party/minilzo/lzoconf.h b/third-party/minilzo/lzoconf.h index f9a8bdbee7..a8ffb99ef8 100644 --- a/third-party/minilzo/lzoconf.h +++ b/third-party/minilzo/lzoconf.h @@ -264,7 +264,7 @@ typedef int const lzo_bytep dict, lzo_uint dict_len ); -/* Callback interface. Currently only the progress indicator ("nprogress") +/* Callback interfaces. Currently only the progress indicator ("nprogress") * is used, but this may change in a future release. */ struct lzo_callback_t; diff --git a/third-party/mman.h b/third-party/mman.h new file mode 100644 index 0000000000..220b37ddec --- /dev/null +++ b/third-party/mman.h @@ -0,0 +1,57 @@ +/* + * sys/mman.h + * mman-win32 + */ + +#ifndef _SYS_MMAN_H_ +#define _SYS_MMAN_H_ + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +/* All the headers include this file. */ +#ifndef _MSC_VER +#include <_mingw.h> +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_TYPE 0xf +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */ +#define MAP_ANON MAP_ANONYMOUS + +#define MAP_FAILED ((void *)-1) + +/* Flags for msync. */ +#define MS_ASYNC 1 +#define MS_SYNC 2 +#define MS_INVALIDATE 4 +#define MAP_POPULATE 0x08000 + +void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); +int munmap(void *addr, size_t len); +int mprotect(void *addr, size_t len, int prot); +int msync(void *addr, size_t len, int flags); +int mlock(const void *addr, size_t len); +int munlock(const void *addr, size_t len); + +#ifdef __cplusplus +}; +#endif + +#endif /* _SYS_MMAN_H_ */ From e6e96400c8c1fbb21285aa6f33aeedd570de849c Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 26 Aug 2020 21:02:24 -0400 Subject: [PATCH 06/32] commit doctor's latest changes --- CMakeSettings.json | 28 +-- common/type_system/Type.cpp | 16 +- common/type_system/TypeSystem.cpp | 26 +-- common/type_system/TypeSystem.h | 2 +- decompiler/ObjectFile/LinkedObjectFile.cpp | 2 +- .../ObjectFile/LinkedObjectFileCreation.cpp | 4 +- decompiler/util/FileIO.cpp | 6 +- decompiler/util/LispPrint.cpp | 4 +- decompiler/util/LispPrint.h | 2 +- decompiler/util/Timer.cpp | 4 +- decompiler/util/Timer.h | 4 +- game/kernel/Ptr.h | 4 +- game/kernel/kboot.cpp | 6 +- game/kernel/klink.cpp | 2 +- game/kernel/kmemcard.cpp | 2 +- game/kernel/kmemcard.h | 2 +- game/kernel/kprint.cpp | 32 ++-- game/kernel/kprint.h | 10 +- game/kernel/kscheme.cpp | 12 +- game/overlord/fake_iso.cpp | 2 + game/runtime.cpp | 45 +++-- game/sce/deci2.cpp | 24 +-- game/sce/iop.cpp | 4 +- game/sce/stubs.cpp | 10 +- game/system/Deci2Server.cpp | 39 ++-- game/system/Deci2Server.h | 5 +- game/system/IOP_Kernel.cpp | 18 +- game/system/IOP_Kernel.h | 6 +- game/system/SystemThread.cpp | 40 +--- game/system/SystemThread.h | 4 +- game/system/deci_common.h | 1 + game/system/iop_thread.cpp | 8 +- goalc/emitter/CodeTester.cpp | 2 +- goalc/goos/Interpreter.cpp | 6 +- goalc/goos/InterpreterEval.cpp | 8 +- goalc/goos/Object.cpp | 4 +- goalc/goos/Object.h | 36 ++-- goalc/goos/Reader.cpp | 10 +- goalc/listener/Deci2Server.cpp | 2 +- goalc/listener/Deci2Server.h | 4 +- goalc/listener/Listener.cpp | 31 +-- goalc/util/file_io.cpp | 2 +- mman.c | 180 ++++++++++++++++++ test/all_jak1_symbols.cpp | 2 +- third-party/fmt/format-inl.h | 8 +- third-party/fmt/format.cc | 2 +- third-party/fmt/format.h | 18 +- third-party/json.hpp | 34 ++-- third-party/minilzo/lzoconf.h | 2 +- third-party/mman.h | 57 ++++++ 50 files changed, 509 insertions(+), 273 deletions(-) create mode 100644 mman.c create mode 100644 third-party/mman.h diff --git a/CMakeSettings.json b/CMakeSettings.json index 99b611bdd9..08c8f8af93 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,16 +1,16 @@ { - // See https://go.microsoft.com/fwlink/?linkid=834763 for more information about this file. - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - } - ] + // See https://go.microsoft.com/fwlink/?linkid=834763 for more information about this file. + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + } + ] } \ No newline at end of file diff --git a/common/type_system/Type.cpp b/common/type_system/Type.cpp index 3dd0fe1a80..160af24e3e 100644 --- a/common/type_system/Type.cpp +++ b/common/type_system/Type.cpp @@ -227,35 +227,35 @@ std::string Type::print_method_info() const { NoneType::NoneType() : Type("", "none", false) {} bool NoneType::is_reference() const { - throw std::runtime_error("is_reference called on NoneType"); + throw std::exception("is_reference called on NoneType"); } int NoneType::get_load_size() const { - throw std::runtime_error("get_load_size called on NoneType"); + throw std::exception("get_load_size called on NoneType"); } bool NoneType::get_load_signed() const { - throw std::runtime_error("get_load_size called on NoneType"); + throw std::exception("get_load_size called on NoneType"); } int NoneType::get_size_in_memory() const { - throw std::runtime_error("get_size_in_memory called on NoneType"); + throw std::exception("get_size_in_memory called on NoneType"); } RegKind NoneType::get_preferred_reg_kind() const { - throw std::runtime_error("get_preferred_reg_kind called on NoneType"); + throw std::exception("get_preferred_reg_kind called on NoneType"); } int NoneType::get_offset() const { - throw std::runtime_error("get_offset called on NoneType"); + throw std::exception("get_offset called on NoneType"); } int NoneType::get_in_memory_alignment() const { - throw std::runtime_error("get_in_memory_alignment called on NoneType"); + throw std::exception("get_in_memory_alignment called on NoneType"); } int NoneType::get_inline_array_alignment() const { - throw std::runtime_error("get_inline_array_alignment called on NoneType"); + throw std::exception("get_inline_array_alignment called on NoneType"); } std::string NoneType::print() const { diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index 76e4005c59..9cbabfd54a 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -32,7 +32,7 @@ Type* TypeSystem::add_type(const std::string& name, std::unique_ptr type) // update the type m_types[name] = std::move(type); } else { - throw std::runtime_error("Type was redefined with throw_on_redefine set."); + throw std::exception("Type was redefined with throw_on_redefine set."); } } } else { @@ -43,13 +43,13 @@ Type* TypeSystem::add_type(const std::string& name, std::unique_ptr type) if (m_forward_declared_types.find(type->get_parent()) != m_forward_declared_types.end()) { fmt::print("[TypeSystem] Type {} has incompletely defined parent {}\n", type->get_name(), type->get_parent()); - throw std::runtime_error("add_type failed"); + throw std::exception("add_type failed"); } if (m_types.find(type->get_parent()) == m_types.end()) { fmt::print("[TypeSystem] Type {} has undefined parent {}\n", type->get_name(), type->get_parent()); - throw std::runtime_error("add_type failed"); + throw std::exception("add_type failed"); } } @@ -135,7 +135,7 @@ TypeSpec TypeSystem::make_typespec(const std::string& name) { return TypeSpec(name); } else { fmt::print("[TypeSystem] The type {} is unknown.\n", name); - throw std::runtime_error("make_typespec failed"); + throw std::exception("make_typespec failed"); } } @@ -199,7 +199,7 @@ Type* TypeSystem::lookup_type(const std::string& name) { fmt::print("[TypeSystem] The type {} is not defined.\n", name); } - throw std::runtime_error("lookup_type failed"); + throw std::exception("lookup_type failed"); } /*! @@ -254,7 +254,7 @@ MethodInfo TypeSystem::add_method(Type* type, const std::string& method_name, co method_name, type->get_name(), existing_info.type.print(), ts.print()); // unlike type re-definition, method re-definition is almost certain to go wrong. // probably better to give up. - throw std::runtime_error("method redefinition"); + throw std::exception("method redefinition"); } return existing_info; @@ -278,7 +278,7 @@ MethodInfo TypeSystem::add_new_method(Type* type, const TypeSpec& ts) { "[TypeSystem] The new method of {} was originally defined as {}, but has been redefined " "as {}\n", type->get_name(), existing.type.print(), ts.print()); - throw std::runtime_error("add_new_method failed"); + throw std::exception("add_new_method failed"); } return existing; @@ -317,7 +317,7 @@ MethodInfo TypeSystem::lookup_method(const std::string& type_name, const std::st } fmt::print("[TypeSystem] The method {} of type {} could not be found.\n", method_name, type_name); - throw std::runtime_error("lookup_method failed"); + throw std::exception("lookup_method failed"); } /*! @@ -345,7 +345,7 @@ MethodInfo TypeSystem::lookup_new_method(const std::string& type_name) { } fmt::print("[TypeSystem] The new method of type {} could not be found.\n", type_name); - throw std::runtime_error("lookup_new_method failed"); + throw std::exception("lookup_new_method failed"); } /*! @@ -420,7 +420,7 @@ void TypeSystem::assert_field_offset(const std::string& type_name, if (field.offset() != offset) { fmt::print("[TypeSystem] assert_field_offset({}, {}, {}) failed - got {}\n", type_name, field_name, offset); - throw std::runtime_error("assert_field_offset failed"); + throw std::exception("assert_field_offset failed"); } } @@ -436,7 +436,7 @@ int TypeSystem::add_field_to_type(StructureType* type, int offset_override) { if (type->lookup_field(field_name, nullptr)) { fmt::print("[TypeSystem] Type {} already has a field named {}\n", type->get_name(), field_name); - throw std::runtime_error("add_field_to_type duplicate field names"); + throw std::exception("add_field_to_type duplicate field names"); } // first, construct the field @@ -467,7 +467,7 @@ int TypeSystem::add_field_to_type(StructureType* type, "[TypeSystem] Tried to overwrite offset of field to be {}, but it is not aligned " "correctly\n", offset); - throw std::runtime_error("add_field_to_type bad offset_override"); + throw std::exception("add_field_to_type bad offset_override"); } } @@ -649,7 +649,7 @@ Field TypeSystem::lookup_field(const std::string& type_name, const std::string& Field field; if (!type->lookup_field(field_name, &field)) { fmt::print("[TypeSystem] Type {} has no field named {}\n", type_name, field_name); - throw std::runtime_error("lookup_field failed"); + throw std::exception("lookup_field failed"); } return field; } diff --git a/common/type_system/TypeSystem.h b/common/type_system/TypeSystem.h index 71a865588b..e290c13f06 100644 --- a/common/type_system/TypeSystem.h +++ b/common/type_system/TypeSystem.h @@ -76,7 +76,7 @@ class TypeSystem { auto x = lookup_type(type_name); T* result = dynamic_cast(x); if (!result) { - throw std::runtime_error("Failed to get " + type_name + " as the right type"); + throw std::exception("Failed to get the right type"); } return result; } diff --git a/decompiler/ObjectFile/LinkedObjectFile.cpp b/decompiler/ObjectFile/LinkedObjectFile.cpp index d02fc3bf31..263144d4b1 100644 --- a/decompiler/ObjectFile/LinkedObjectFile.cpp +++ b/decompiler/ObjectFile/LinkedObjectFile.cpp @@ -272,7 +272,7 @@ void LinkedObjectFile::append_word_to_string(std::string& dest, const LinkedWord sprintf(buff, " .sym-off 0x%x %s\n", word.data >> 16, word.symbol_name.c_str()); break; default: - throw std::runtime_error("nyi"); + throw std::exception("nyi"); } dest += buff; diff --git a/decompiler/ObjectFile/LinkedObjectFileCreation.cpp b/decompiler/ObjectFile/LinkedObjectFileCreation.cpp index d61b515224..a4d99849d1 100644 --- a/decompiler/ObjectFile/LinkedObjectFileCreation.cpp +++ b/decompiler/ObjectFile/LinkedObjectFileCreation.cpp @@ -134,7 +134,7 @@ static uint32_t c_symlink2(LinkedObjectFile& f, word_kind = LinkedWord::TYPE_PTR; break; default: - throw std::runtime_error("unhandled SymbolLinkKind"); + throw std::exception("unhandled SymbolLinkKind"); } f.symbol_link_word(seg_id, code_ptr_offset - initial_offset, name, word_kind); @@ -191,7 +191,7 @@ static uint32_t c_symlink3(LinkedObjectFile& f, word_kind = LinkedWord::TYPE_PTR; break; default: - throw std::runtime_error("unhandled SymbolLinkKind"); + throw std::exception("unhandled SymbolLinkKind"); } f.symbol_link_word(seg, code_ptr - initial_offset, name, word_kind); diff --git a/decompiler/util/FileIO.cpp b/decompiler/util/FileIO.cpp index 914d647d59..b3f63d16fa 100644 --- a/decompiler/util/FileIO.cpp +++ b/decompiler/util/FileIO.cpp @@ -16,7 +16,7 @@ std::string combine_path(const std::string& parent, const std::string& child) { std::vector read_binary_file(const std::string& filename) { auto fp = fopen(filename.c_str(), "rb"); - if(!fp) throw std::runtime_error("File " + filename + " cannot be opened"); + if(!fp) throw std::exception("File cannot be opened"); fseek(fp, 0, SEEK_END); auto len = ftell(fp); rewind(fp); @@ -25,7 +25,7 @@ std::vector read_binary_file(const std::string& filename) { data.resize(len); if(fread(data.data(), len, 1, fp) != 1) { - throw std::runtime_error("File " + filename + " cannot be read"); + throw std::exception("File cannot be read"); } return data; @@ -75,7 +75,7 @@ void write_text_file(const std::string& file_name, const std::string& text) { FILE* fp = fopen(file_name.c_str(), "w"); if(!fp) { printf("Failed to fopen %s\n", file_name.c_str()); - throw std::runtime_error("Failed to open file"); + throw std::exception("Failed to open file"); } fprintf(fp, "%s\n", text.c_str()); fclose(fp); diff --git a/decompiler/util/LispPrint.cpp b/decompiler/util/LispPrint.cpp index 103fa42f5a..a2a0877950 100644 --- a/decompiler/util/LispPrint.cpp +++ b/decompiler/util/LispPrint.cpp @@ -72,7 +72,7 @@ void Form::buildStringSimple(std::string &str) { str.append(*token.str); break; default: - throw std::runtime_error("buildStringSimple unknown token kind"); + throw std::exception("buildStringSimple unknown token kind"); } } } @@ -110,7 +110,7 @@ void Form::toTokenList(std::vector &tokens) { tokens.emplace_back(TokenKind::EMPTY_PAIR); break; default: - throw std::runtime_error("unhandled form type in buildSimpleString"); + throw std::exception("unhandled form type in buildSimpleString"); break; } } diff --git a/decompiler/util/LispPrint.h b/decompiler/util/LispPrint.h index 28eaf1f5db..5a537b3021 100644 --- a/decompiler/util/LispPrint.h +++ b/decompiler/util/LispPrint.h @@ -70,7 +70,7 @@ struct FormToken { s.append(*str); break; default: - throw std::runtime_error("toString unknown token kind"); + throw std::exception("toString unknown token kind"); } return s; } diff --git a/decompiler/util/Timer.cpp b/decompiler/util/Timer.cpp index 4ac44ab25c..0a5d895064 100644 --- a/decompiler/util/Timer.cpp +++ b/decompiler/util/Timer.cpp @@ -48,7 +48,7 @@ int64_t Timer::getNs() { clock_gettime(CLOCK_MONOTONIC, &now); #elif _WIN32 clock_gettime_monotonic(&now); -#endif +#endif; return (int64_t)(now.tv_nsec - _startTime.tv_nsec) + 1000000000 * (now.tv_sec - _startTime.tv_sec); -} +} \ No newline at end of file diff --git a/decompiler/util/Timer.h b/decompiler/util/Timer.h index 5972020339..c589657a00 100644 --- a/decompiler/util/Timer.h +++ b/decompiler/util/Timer.h @@ -19,6 +19,8 @@ class Timer { int clock_gettime_monotonic(struct timespec* tv); #endif + + /*! * Start the timer */ @@ -27,7 +29,7 @@ class Timer { /*! * Get milliseconds elapsed */ - double getMs() { return (double)getNs() / 1.e6; } + double getMs() { return (double)getNs() / 1.e6; } double getUs() { return (double)getNs() / 1.e3; } diff --git a/game/kernel/Ptr.h b/game/kernel/Ptr.h index 9764de9fb4..0f9c7811a8 100644 --- a/game/kernel/Ptr.h +++ b/game/kernel/Ptr.h @@ -40,7 +40,7 @@ struct Ptr { if (offset) { return (T*)(g_ee_main_mem + offset); } else { - throw std::runtime_error("Ptr null dereference!"); + throw std::exception("Ptr null dereference!"); } } @@ -51,7 +51,7 @@ struct Ptr { if (offset) { return *(T*)(g_ee_main_mem + offset); } else { - throw std::runtime_error("Ptr null dereference!"); + throw std::exception("Ptr null dereference!"); } } diff --git a/game/kernel/kboot.cpp b/game/kernel/kboot.cpp index 0d06dcf659..e6d53fa857 100644 --- a/game/kernel/kboot.cpp +++ b/game/kernel/kboot.cpp @@ -4,7 +4,7 @@ * DONE! */ -#include +#include #include #include "common/common_types.h" #include "game/sce/libscf.h" @@ -13,7 +13,7 @@ #include "kscheme.h" #include "ksocket.h" #include "klisten.h" - +#include "Windows.h" using namespace ee; // Level to load on boot @@ -135,7 +135,7 @@ void KernelCheckAndDispatch() { SendAck(); } - usleep(1000); // todo - remove this + Sleep(1000); // todo - remove this } } diff --git a/game/kernel/klink.cpp b/game/kernel/klink.cpp index 38eba8ee74..3326b64ba5 100644 --- a/game/kernel/klink.cpp +++ b/game/kernel/klink.cpp @@ -264,7 +264,7 @@ uint32_t cross_seg_dist_link_v3(Ptr link, } else if (size == 8) { *Ptr(offset_of_patch).c() = diff; } else { - throw std::runtime_error("unknown size in cross_seg_dist_link_v3"); + throw std::exception("unknown size in cross_seg_dist_link_v3"); } return 1 + 3 * 4; diff --git a/game/kernel/kmemcard.cpp b/game/kernel/kmemcard.cpp index e8279830dd..111a6d24e7 100644 --- a/game/kernel/kmemcard.cpp +++ b/game/kernel/kmemcard.cpp @@ -1,6 +1,6 @@ /*! * @file kmemcard.cpp - * Memory card interface. Very messy code. + * Memory card interfaces. Very messy code. */ //#include "ps2/SCE_MC.h" diff --git a/game/kernel/kmemcard.h b/game/kernel/kmemcard.h index 3805724d4a..59738a098e 100644 --- a/game/kernel/kmemcard.h +++ b/game/kernel/kmemcard.h @@ -1,6 +1,6 @@ /*! * @file kmemcard.h - * Memory card interface. Very messy code. + * Memory card interfaces. Very messy code. */ diff --git a/game/kernel/kprint.cpp b/game/kernel/kprint.cpp index 59b086a667..f57f5af5c3 100644 --- a/game/kernel/kprint.cpp +++ b/game/kernel/kprint.cpp @@ -338,10 +338,10 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu value = (char)rounder; } else if (!(ru32 >> 31)) { // sign bit value = 0; - throw std::runtime_error("got very large exponent in rounding calculation"); + throw std::exception("got very large exponent in rounding calculation"); } else { value = -1; // happens on NaN's - // throw std::runtime_error("got negative sign bit in rounding calculation"); + // throw std::exception("got negative sign bit in rounding calculation"); } // place number at the end of the buffer and move pointer back @@ -386,10 +386,10 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu value = (char)next_int; } else if (!(ru32 >> 0x1f)) { value = 0; - throw std::runtime_error("got very large exponent in rounding calculation"); + throw std::exception("got very large exponent in rounding calculation"); } else { value = -1; // happens on NaN's - // throw std::runtime_error("got negative sign bit in rounding calculation"); + // throw std::exception("got negative sign bit in rounding calculation"); } *count_chrp = value + '0'; count_chrp++; @@ -401,7 +401,7 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu // however, the rounding flag is always disabled and the rounding code doesn't work. if ((fraction_part != 0.f) && ((flags & 1) != 0)) { start_ptr = round(fraction_part, nullptr, start_ptr, count_chrp - 1, 0, lead_char); - throw std::runtime_error("cvt_float called round!"); + throw std::exception("cvt_float called round!"); } } @@ -553,7 +553,7 @@ char* kitoa(char* buffer, s64 value, u64 base, s32 length, char pad, u32 flag) { * uses C varags, but 128-bit varags don't work, so "format" always passes 0 for quadword printing. */ void kqtoa() { - throw std::runtime_error("kqtoa not implemented"); + throw std::exception("kqtoa not implemented"); } struct format_struct { @@ -791,7 +791,7 @@ s32 format_impl(uint64_t* args) { } kstrinsert(output_ptr, pad, desired_length - print_len); } else { - throw std::runtime_error("unsupported justify in format"); + throw std::exception("unsupported justify in format"); // output_ptr = strend(output_ptr); // while(0 < (desired_length - print_len)) { // char pad = ' '; @@ -842,7 +842,7 @@ s32 format_impl(uint64_t* args) { kstrinsert(output_ptr, pad, desired_length - print_len); } else { - throw std::runtime_error("unsupported justify in format"); + throw std::exception("unsupported justify in format"); // output_ptr = strend(output_ptr); // u32 l140 = 0; // while(l140 < (desired_length - print_len)) { @@ -883,7 +883,7 @@ s32 format_impl(uint64_t* args) { call_method_of_type(in, type, GOAL_PRINT_FUNC); } } else { - throw std::runtime_error("failed to find symbol in format!"); + throw std::exception("failed to find symbol in format!"); } } output_ptr = strend(output_ptr); @@ -904,7 +904,7 @@ s32 format_impl(uint64_t* args) { call_method_of_type(in, type, GOAL_INSPECT_FUNC); } } else { - throw std::runtime_error("failed to find symbol in format!"); + throw std::exception("failed to find symbol in format!"); } } output_ptr = strend(output_ptr); @@ -912,7 +912,7 @@ s32 format_impl(uint64_t* args) { case 'Q': // not yet implemented. hopefully andy gavin finishes this one soon. case 'q': - throw std::runtime_error("nyi q format string"); + throw std::exception("nyi q format string"); break; case 'X': // hex, 64 bit, pad padchar @@ -1009,7 +1009,7 @@ s32 format_impl(uint64_t* args) { precision = 4; float value; if (in < 0) { - throw std::runtime_error("time seconds format error negative.\n"); + throw std::exception("time seconds format error negative.\n"); } else { value = in; } @@ -1025,7 +1025,7 @@ s32 format_impl(uint64_t* args) { default: MsgErr("format: unknown code 0x%02x\n", format_ptr[1]); - throw std::runtime_error("format error"); + throw std::exception("format error"); break; } format_ptr++; @@ -1067,13 +1067,13 @@ s32 format_impl(uint64_t* args) { *PrintPendingLocal3 = 0; return 0; } else if (type == *Ptr>(s7.offset + FIX_SYM_FILE_STREAM_TYPE)) { - throw std::runtime_error("FORMAT into a file stream not supported"); + throw std::exception("FORMAT into a file stream not supported"); } } - throw std::runtime_error("unknown format destination"); + throw std::exception("unknown format destination"); return 0; } - throw std::runtime_error("how did we get here?"); + throw std::exception("how did we get here?"); return 7; } \ No newline at end of file diff --git a/game/kernel/kprint.h b/game/kernel/kprint.h index 049a66d35c..b7995d7a4d 100644 --- a/game/kernel/kprint.h +++ b/game/kernel/kprint.h @@ -13,6 +13,8 @@ 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 /////////// @@ -65,25 +67,25 @@ void output_segment_load(const char* name, Ptr link_block, u32 flags); /*! * Print to the GOAL print buffer from C */ -void cprintf(const char* format, ...); +void cprintf(const char* format, ...) __attribute__((format(printf, 1, 2))); /*! * Print directly to the C stdout * The "k" parameter is ignored, so this is just like printf */ -void Msg(s32 k, const char* format, ...); +void Msg(s32 k, const char* format, ...) __attribute__((format(printf, 2, 3))); /*! * Print directly to the C stdout * This is identical to Msg. */ -void MsgWarn(const char* format, ...); +void MsgWarn(const char* format, ...) __attribute__((format(printf, 1, 2))); /*! * Print directly to the C stdout * This is identical to Msg. */ -void MsgErr(const char* format, ...); +void MsgErr(const char* format, ...) __attribute__((format(printf, 1, 2))); /*! * Reverse string in place. diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index eff441ee01..6e69334ad8 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -124,7 +124,7 @@ u64 goal_malloc(u32 heap, u32 size, u32 flags, u32 name) { */ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { if (size <= 0) { - throw std::runtime_error("got <= 0 size allocation in alloc_from_heap!"); + throw std::exception("got <= 0 size allocation in alloc_from_heap!"); } // align to 16 bytes (part one) @@ -162,7 +162,7 @@ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { return kmalloc(*Ptr>(heapSymbol), size, KMALLOC_MEMSET, gstr->data()).offset; } else if (heapOffset == FIX_SYM_PROCESS_TYPE) { - throw std::runtime_error("this type of process allocation is not supported yet!\n"); + throw std::exception("this type of process allocation is not supported yet!\n"); // allocate on current process heap // Ptr start = *ptr(getS6() + 0x4c + 8); // Ptr heapEnd = *ptr(getS6() + 0x4c + 4); @@ -178,7 +178,7 @@ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { // alignedSize); return 0; // } } else if (heapOffset == FIX_SYM_SCRATCH) { - throw std::runtime_error("this type of scratchpad allocation is not used!\n"); + throw std::exception("this type of scratchpad allocation is not used!\n"); } else { memset(Ptr(heapSymbol).c(), 0, (size_t)alignedSize); // treat it as a stack address return heapSymbol; @@ -920,7 +920,7 @@ u64 call_method_of_type(u32 arg, Ptr type, u32 method_id) { (*type_tag).offset); } } - // throw std::runtime_error("call_method_of_type failed!\n"); + // throw std::exception("call_method_of_type failed!\n"); printf("[ERROR] call_method_of_type failed!\n"); printf("type is %s\n", info(type->symbol)->str->data()); return arg; @@ -958,7 +958,7 @@ u64 call_method_of_type_arg2(u32 arg, Ptr type, u32 method_id, u32 a1, u32 (*type_tag).offset); } } - throw std::runtime_error("call_method_of_type failed!\n"); + throw std::exception("call_method_of_type failed!\n"); return arg; } @@ -1779,7 +1779,7 @@ s32 InitHeapAndSymbol() { // setup deci2count for message counter. protoBlock.deci2count = intern_from_c("*deci-count*").cast(); - // load stuff for the listener interface + // load stuff for the listener interfaces InitListener(); // Do final initialization, including loading and initializing the engine. diff --git a/game/overlord/fake_iso.cpp b/game/overlord/fake_iso.cpp index 6219f69de7..0f44fca108 100644 --- a/game/overlord/fake_iso.cpp +++ b/game/overlord/fake_iso.cpp @@ -343,6 +343,7 @@ uint32_t FS_LoadMusic(char* name, void* buffer) { (void)name; (void)buffer; assert(false); + return 0; } // TODO FS_LoadSoundBank @@ -350,4 +351,5 @@ uint32_t FS_LoadSoundBank(char* name, void* buffer) { (void)name; (void)buffer; assert(false); + return 0; } \ No newline at end of file diff --git a/game/runtime.cpp b/game/runtime.cpp index 14af11cb9b..5f8cb3b7a3 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -3,9 +3,10 @@ * Setup and launcher for the runtime. */ -#include -#include +#include +#include #include +#include #include "runtime.h" #include "system/SystemThread.h" @@ -43,28 +44,32 @@ namespace { /*! * SystemThread function for running the DECI2 communication with the GOAL compiler. */ -void deci2_runner(SystemThreadInterface& interface) { + + +/* + +void deci2_runner(SystemThreadInterface& interfaces) { // callback function so the server knows when to give up and shutdown - std::function shutdown_callback = [&]() { return interface.get_want_exit(); }; + std::function shutdown_callback = [&]() { return interfaces.get_want_exit(); }; // create and register server - Deci2Server server(shutdown_callback); - ee::LIBRARY_sceDeci2_register(&server); +// Deci2Server server(shutdown_callback); +// ee::LIBRARY_sceDeci2_register(&server); // now its ok to continue with initialization - interface.initialization_complete(); + 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"); + throw std::exception("DECI2 server init failed"); } printf("[DECI2] waiting for listener...\n"); bool saw_listener = false; - while (!interface.get_want_exit()) { + while (!interfaces.get_want_exit()) { if (server.check_for_listener()) { if (!saw_listener) { printf("[DECI2] Connected!\n"); @@ -74,10 +79,12 @@ void deci2_runner(SystemThreadInterface& interface) { server.run(); } else { // no connection yet. Do a sleep so we don't spam checking the listener. - usleep(50000); + Sleep(1000); } } } +*/ + // EE System constexpr int EE_MAIN_MEM_SIZE = 128 * (1 << 20); // 128 MB, same as PS2 TOOL @@ -95,7 +102,7 @@ constexpr int GOAL_ARGC = 4; /*! * SystemThread Function for the EE (PS2 Main CPU) */ -void ee_runner(SystemThreadInterface& interface) { +void ee_runner(SystemThreadInterface& interfaces) { // Allocate Main RAM. Must have execute enabled. if (EE_MEM_LOW_MAP) { g_ee_main_mem = @@ -109,7 +116,7 @@ void ee_runner(SystemThreadInterface& interface) { if (g_ee_main_mem == (u8*)(-1)) { printf(" Failed to initialize main memory! %s\n", strerror(errno)); - interface.initialization_complete(); + interfaces.initialization_complete(); return; } @@ -118,7 +125,7 @@ void ee_runner(SystemThreadInterface& interface) { (double)EE_MAIN_MEM_SIZE / (1 << 20)); printf("[EE] Initialization complete!\n"); - interface.initialization_complete(); + interfaces.initialization_complete(); printf("[EE] Run!\n"); memset((void*)g_ee_main_mem, 0, EE_MAIN_MEM_SIZE); @@ -145,13 +152,13 @@ void ee_runner(SystemThreadInterface& interface) { munmap(g_ee_main_mem, EE_MAIN_MEM_SIZE); // after main returns, trigger a shutdown. - interface.trigger_shutdown(); + interfaces.trigger_shutdown(); } /*! * SystemThread function for running the IOP (separate I/O Processor) */ -void iop_runner(SystemThreadInterface& interface) { +void iop_runner(SystemThreadInterface& interfaces) { IOP iop; printf("\n\n\n[IOP] Restart!\n"); iop.reset_allocator(); @@ -174,7 +181,7 @@ void iop_runner(SystemThreadInterface& interface) { // ssound // stream - interface.initialization_complete(); + interfaces.initialization_complete(); printf("[IOP] Wait for OVERLORD to be started...\n"); iop.wait_for_overlord_start_cmd(); @@ -195,7 +202,7 @@ void iop_runner(SystemThreadInterface& interface) { iop.signal_overlord_init_finish(); // IOP Kernel loop - while (!interface.get_want_exit() && !iop.want_exit) { + while (!interfaces.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(); @@ -232,8 +239,8 @@ void exec_runtime(int argc, char** argv) { // step 3: start the EE! iop_thread.start(iop_runner); ee_thread.start(ee_runner); - deci_thread.start(deci2_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! diff --git a/game/sce/deci2.cpp b/game/sce/deci2.cpp index 03c2f7c39a..75b7a076d5 100644 --- a/game/sce/deci2.cpp +++ b/game/sce/deci2.cpp @@ -1,7 +1,7 @@ /*! * @file deci2.cpp * Implementation of SCE DECI2 library. - */ + #include #include @@ -19,9 +19,9 @@ Deci2Driver* sending_driver; // currently sending protocol drive ::Deci2Server* server; // the server to send data to } // namespace -/*! + * Initialize the library. - */ + void LIBRARY_INIT_sceDeci2() { // reset protocols for (auto& p : protocols) { @@ -34,7 +34,7 @@ void LIBRARY_INIT_sceDeci2() { /*! * Run any pending requested sends. - */ + void LIBRARY_sceDeci2_run_sends() { for (auto& prot : protocols) { if (prot.active && prot.pending_send == 'H') { @@ -49,7 +49,7 @@ void LIBRARY_sceDeci2_run_sends() { /*! * Register a Deci2Server with this library. - */ + void LIBRARY_sceDeci2_register(::Deci2Server* s) { server = s; } @@ -58,7 +58,7 @@ void LIBRARY_sceDeci2_register(::Deci2Server* s) { * Open a new socket with given protocol number and handler. * The "opt" pointer is passed to the handler function. * 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; @@ -82,7 +82,7 @@ s32 sceDeci2Open(u16 protocol, void* opt, void (*handler)(s32 event, s32 param, /*! * Deactivate a DECI2 protocol by socket descriptor. - */ + s32 sceDeci2Close(s32 s) { assert(s - 1 < protocol_count); protocols[s - 1].active = false; @@ -91,7 +91,7 @@ s32 sceDeci2Close(s32 s) { /*! * Start a send. - */ + s32 sceDeci2ReqSend(s32 s, char dest) { assert(s - 1 < protocol_count); auto& proto = protocols[s - 1]; @@ -102,7 +102,7 @@ s32 sceDeci2ReqSend(s32 s, char dest) { /*! * Do a receive from socket s into buf of size len. * Returns after data is copied. - */ + s32 sceDeci2ExRecv(s32 s, void* buf, u16 len) { assert(s - 1 < protocol_count); protocols[s - 1].recv_size = len; @@ -118,7 +118,7 @@ s32 sceDeci2ExRecv(s32 s, void* buf, u16 len) { /*! * Do a send. - */ + s32 sceDeci2ExSend(s32 s, void* buf, u16 len) { assert(s - 1 < protocol_count); if (!sending_driver) { @@ -133,4 +133,6 @@ s32 sceDeci2ExSend(s32 s, void* buf, u16 len) { return len; } -} // namespace ee \ No newline at end of file +} // namespace ee + +*/ \ No newline at end of file diff --git a/game/sce/iop.cpp b/game/sce/iop.cpp index 6f954a0183..002d8b8179 100644 --- a/game/sce/iop.cpp +++ b/game/sce/iop.cpp @@ -201,12 +201,12 @@ s32 CreateSema(SemaParam* param) { s32 WaitSema(s32 sema) { (void)sema; - throw std::runtime_error("NYI"); + throw std::exception("NYI"); } s32 SignalSema(s32 sema) { (void)sema; - throw std::runtime_error("NYI"); + throw std::exception("NYI"); } s32 WakeupThread(s32 thid) { diff --git a/game/sce/stubs.cpp b/game/sce/stubs.cpp index 4e218a4739..7f92ade562 100644 --- a/game/sce/stubs.cpp +++ b/game/sce/stubs.cpp @@ -6,33 +6,33 @@ namespace ee { s32 sceOpen(const char *filename, s32 flag) { (void)filename; (void)flag; - throw std::runtime_error("sceOpen NYI"); + throw std::exception("sceOpen NYI"); } s32 sceClose(s32 fd) { (void)fd; - throw std::runtime_error("sceClose NYI"); + throw std::exception("sceClose NYI"); } s32 sceRead(s32 fd, void *buf, s32 nbyte) { (void)fd; (void)buf; (void)nbyte; - throw std::runtime_error("sceRead NYI"); + throw std::exception("sceRead NYI"); } s32 sceWrite(s32 fd, const void *buf, s32 nbyte) { (void)fd; (void)buf; (void)nbyte; - throw std::runtime_error("sceWrite NYI"); + throw std::exception("sceWrite NYI"); } s32 sceLseek(s32 fd, s32 offset, s32 where) { (void)fd; (void)offset; (void)where; - throw std::runtime_error("sceLseek NYI"); + throw std::exception("sceLseek NYI"); } int scePadPortOpen(int port, int slot, void* data) { diff --git a/game/system/Deci2Server.cpp b/game/system/Deci2Server.cpp index 9b2a29f942..21b9e89bba 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -2,12 +2,11 @@ * @file Deci2Server.cpp * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target - */ + #include -#include -#include -#include +#include +#include #include #include @@ -15,6 +14,8 @@ #include "common/versions.h" #include "Deci2Server.h" +typedef int socklen_t; + Deci2Server::Deci2Server(std::function shutdown_callback) { buffer = new char[BUFFER_SIZE]; want_exit = std::move(shutdown_callback); @@ -41,7 +42,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) { @@ -49,16 +50,16 @@ bool Deci2Server::init() { return false; } - int opt = 1; - if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + const char opt = 1; + if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_BROADCAST, &opt, sizeof(opt))) { printf("[Deci2Server] Failed to setsockopt 1\n"); close(server_fd); server_fd = -1; return false; } - int one = 1; - if (setsockopt(server_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { + const char one = 1; + if (setsockopt(server_fd, SOL_SOCKET, TCP_NODELAY, &one, sizeof(one))) { printf("[Deci2Server] Failed to setsockopt 2\n"); close(server_fd); server_fd = -1; @@ -103,7 +104,7 @@ bool Deci2Server::init() { /*! * Return true if the listener is connected. - */ + bool Deci2Server::check_for_listener() { if (server_connected) { if (accept_thread_running) { @@ -118,7 +119,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) { @@ -139,14 +140,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(); } @@ -154,7 +155,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; @@ -167,7 +168,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; @@ -214,7 +215,7 @@ void Deci2Server::run() { printf("[DECI2] Warning: no handler for this message, ignoring...\n"); unlock(); return; - // throw std::runtime_error("no handler!"); + // throw std::exception("no handler!"); } auto& driver = d2_drivers[handler]; @@ -249,16 +250,18 @@ 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) { - u32 versions[2] = {versions::GOAL_VERSION_MAJOR, versions::GOAL_VERSION_MINOR}; + const char versions = {versions::GOAL_VERSION_MAJOR}; send(new_sock, &versions, 8, 0); // todo, check result? server_connected = true; return; } } } + +*/ \ No newline at end of file diff --git a/game/system/Deci2Server.h b/game/system/Deci2Server.h index c9e0542795..5b5808e678 100644 --- a/game/system/Deci2Server.h +++ b/game/system/Deci2Server.h @@ -2,13 +2,12 @@ * @file Deci2Server.h * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target - */ + #ifndef JAK1_DECI2SERVER_H #define JAK1_DECI2SERVER_H #include - #include #include #include @@ -55,3 +54,5 @@ class Deci2Server { #endif // JAK1_DECI2SERVER_H + +*/ \ No newline at end of file diff --git a/game/system/IOP_Kernel.cpp b/game/system/IOP_Kernel.cpp index ffa2a9cbad..291aaa3381 100644 --- a/game/system/IOP_Kernel.cpp +++ b/game/system/IOP_Kernel.cpp @@ -7,9 +7,9 @@ * Create a new thread. Will not run the thread. */ s32 IOP_Kernel::CreateThread(std::string name, u32 (*func)()) { - if(_currentThread != -1) throw std::runtime_error("tried to create thread from thread"); + if(_currentThread != -1) throw std::exception("tried to create thread from thread"); u32 ID = (u32)_nextThID++; - if(threads.size() != ID) throw std::runtime_error("thread number error?"); + if(threads.size() != ID) throw std::exception("thread number error?"); // add entry threads.emplace_back(name, func, ID, this); // setup the thread! @@ -19,7 +19,7 @@ s32 IOP_Kernel::CreateThread(std::string name, u32 (*func)()) { if(func) { _currentThread = ID; // create OS thread, will run the setupThread function - threads.back().thread = new std::thread(&IOP_Kernel::setupThread, this, ID); + //threads.back().thread = new std::thread(&IOP_Kernel::setupThread, this, ID); --- quick hack to make the build // wait for thread to finish setup. threads.back().waitForReturnToKernel(); // ensure we are back in the kernel. @@ -47,7 +47,7 @@ void IOP_Kernel::setupThread(s32 id) { threads.at(id).waitForDispatch(); // printf("[IOP Kernel] Thread %s first dispatch!\n", threads.at(id).name.c_str()); if(_currentThread != id) { - throw std::runtime_error("the wrong thread has run!\n"); + throw std::exception("the wrong thread has run!\n"); } (threads.at(id).function)(); printf("Thread %s has returned!\n", threads.at(id).name.c_str()); @@ -59,7 +59,7 @@ void IOP_Kernel::setupThread(s32 id) { * Run a thread (call from kernel) */ void IOP_Kernel::runThread(s32 id) { - if(_currentThread != -1) throw std::runtime_error("tried to runThread in a thread"); + if(_currentThread != -1) throw std::exception("tried to runThread in a thread"); _currentThread = id; threads.at(id).dispatch(); threads.at(id).waitForReturnToKernel(); @@ -76,7 +76,7 @@ void IOP_Kernel::SuspendThread() { threads.at(oldThread).returnToKernel(); threads.at(oldThread).waitForDispatch(); if(_currentThread != oldThread) { - throw std::runtime_error("bad resume"); + throw std::exception("bad resume"); } } @@ -128,7 +128,7 @@ void IOP_Kernel::dispatchAll() { */ void IopThreadRecord::returnToKernel() { runThreadReady = false; - if(kernel->getCurrentThread() != thID) throw std::runtime_error("tried to sleep the wrong thread!"); + if(kernel->getCurrentThread() != thID) throw std::exception("tried to sleep the wrong thread!"); { std::lock_guard lck(*threadToKernelMutex); @@ -142,7 +142,7 @@ void IopThreadRecord::returnToKernel() { */ void IopThreadRecord::dispatch() { syscallReady = false; - if(kernel->getCurrentThread() != thID) throw std::runtime_error("tried to dispatch the wrong thread!"); + if(kernel->getCurrentThread() != thID) throw std::exception("tried to dispatch the wrong thread!"); { std::lock_guard lck(*kernelToThreadMutex); runThreadReady = true; @@ -163,7 +163,7 @@ void IopThreadRecord::waitForReturnToKernel() { * Thread waits for kernel to dispatch it. */ void IopThreadRecord::waitForDispatch() { - //if(kernel->getCurrentThread() == -1) throw std::runtime_error("tried to suspend main!\n"); + //if(kernel->getCurrentThread() == -1) throw std::exception("tried to suspend main!\n"); std::unique_lock lck(*kernelToThreadMutex); kernelToThreadCV->wait(lck, [this]{return runThreadReady;}); //runThreadReady = false; diff --git a/game/system/IOP_Kernel.h b/game/system/IOP_Kernel.h index d05083dbc8..c811770be5 100644 --- a/game/system/IOP_Kernel.h +++ b/game/system/IOP_Kernel.h @@ -98,7 +98,7 @@ public: * Resume the kernel. */ void returnToKernel() { - if(_currentThread < 0) throw std::runtime_error("tried to return to kernel not in a thread"); + if(_currentThread < 0) throw std::exception("tried to return to kernel not in a thread"); threads[_currentThread].returnToKernel(); } @@ -129,7 +129,7 @@ public: return -0x1a9; } // printf("poll %d %ld\n", mbx, mbxs.size()); - if(mbx >= (s32) mbxs.size()) throw std::runtime_error("invalid PollMbx"); + if(mbx >= (s32) mbxs.size()) throw std::exception("invalid PollMbx"); s32 gotSomething = mbxs[mbx].empty() ? 0 : 1; if(gotSomething) { void* thing = mbxs[mbx].front(); @@ -146,7 +146,7 @@ public: * Push something into a mbx */ s32 SendMbx(s32 mbx, void* value) { - if(mbx >= (s32) mbxs.size()) throw std::runtime_error("invalid SendMbx"); + if(mbx >= (s32) mbxs.size()) throw std::exception("invalid SendMbx"); mbxs[mbx].push(value); // printf("push into messagebox %d %p\n", mbx, value); // printf("mbx size %ld\n", mbxs.size()); diff --git a/game/system/SystemThread.cpp b/game/system/SystemThread.cpp index aa49932491..1860f59507 100644 --- a/game/system/SystemThread.cpp +++ b/game/system/SystemThread.cpp @@ -13,7 +13,7 @@ */ SystemThread& SystemThreadManager::create_thread(const std::string& name) { if (thread_count >= MAX_SYSTEM_THREADS) { - throw std::runtime_error("Out of System Threads! Please increase MAX_SYSTEM_THREADS"); + throw std::exception("Out of System Threads! Please increase MAX_SYSTEM_THREADS"); } auto& thread = threads[thread_count]; @@ -71,8 +71,8 @@ void SystemThreadManager::join() { */ void* bootstrap_thread_func(void* x) { SystemThread* thd = (SystemThread*)x; - SystemThreadInterface interface(thd); - thd->function(interface); + SystemThreadInterface interfaces(thd); + thd->function(interfaces); printf("[SYSTEM] Thread %s is returning\n", thd->name.c_str()); return nullptr; } @@ -83,7 +83,7 @@ void* bootstrap_thread_func(void* x) { void SystemThread::start(std::function f) { printf("# Initialize %s...\n", name.c_str()); function = f; - pthread_create(&thread, nullptr, bootstrap_thread_func, this); + std::thread(thread); running = true; // and wait for initialization @@ -100,7 +100,7 @@ void SystemThread::start(std::function f) { */ void SystemThread::join() { void* x; - pthread_join(thread, &x); + thread.join(); running = false; } @@ -135,33 +135,3 @@ bool SystemThreadInterface::get_want_exit() const { void SystemThreadInterface::trigger_shutdown() { thread.manager->shutdown(); } - -#include -#include - -/*! - * 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; - } -} \ No newline at end of file diff --git a/game/system/SystemThread.h b/game/system/SystemThread.h index 5f89929dc2..7744c0afb7 100644 --- a/game/system/SystemThread.h +++ b/game/system/SystemThread.h @@ -21,7 +21,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 interface with intitialization_complete(). + * Once the thread is ready, it should tell the interfaces 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. @@ -56,7 +56,7 @@ private: }; /*! - * The interface used by a thread in the runtime. + * The interfaces used by a thread in the runtime. */ class SystemThreadInterface { public: diff --git a/game/system/deci_common.h b/game/system/deci_common.h index b3f7248064..c8a73cceee 100644 --- a/game/system/deci_common.h +++ b/game/system/deci_common.h @@ -1,6 +1,7 @@ #ifndef JAK_DECIM_COMMON_H #define JAK_DECIM_COMMON_H #include "common/common_types.h" + struct Deci2Driver { u16 protocol = 0; void* opt = nullptr; diff --git a/game/system/iop_thread.cpp b/game/system/iop_thread.cpp index 1a07a5b1b5..1dd81d1e01 100644 --- a/game/system/iop_thread.cpp +++ b/game/system/iop_thread.cpp @@ -1,6 +1,6 @@ #include "iop_thread.h" -#include +#include #include "SystemThread.h" //#include "shared_config.h" //#include "ps2/SCE_IOP.h" @@ -95,7 +95,7 @@ IOP::~IOP() { reset_allocator(); } -//void launch_iop(SystemThreadInterface& interface) { +//void launch_iop(SystemThreadInterface& interfaces) { // IOP iop; // // printf("\n\n\n[IOP] Restart!\n"); @@ -118,7 +118,7 @@ IOP::~IOP() { // //// SCE_IOP::PS2_RegisterIOP(&iop); //// PS2_RegisterIOP_EE(&iop); -// interface.initialization_complete(); +// interfaces.initialization_complete(); // // printf("[IOP] Wait for OVERLORD to be started...\n"); // iop.wait_for_overlord_start_cmd(); @@ -140,7 +140,7 @@ IOP::~IOP() { // iop.signal_overlord_init_finish(); // // // IOP Kernel loop -// while(!interface.get_want_exit() && !iop.want_exit) { +// while(!interfaces.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(); diff --git a/goalc/emitter/CodeTester.cpp b/goalc/emitter/CodeTester.cpp index 6a9a9a6e6f..676841797f 100644 --- a/goalc/emitter/CodeTester.cpp +++ b/goalc/emitter/CodeTester.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "CodeTester.h" #include "Instruction.h" diff --git a/goalc/goos/Interpreter.cpp b/goalc/goos/Interpreter.cpp index 26bbc94852..64bb0ffc57 100644 --- a/goalc/goos/Interpreter.cpp +++ b/goalc/goos/Interpreter.cpp @@ -137,8 +137,8 @@ void Interpreter::execute_repl() { * for debugging. */ void Interpreter::throw_eval_error(const Object& o, const std::string& err) { - throw std::runtime_error("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + - reader.db.get_info_for(o)); + // throw std::exception("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + + // reader.db.get_info_for(o)); } /*! @@ -151,7 +151,7 @@ Object Interpreter::eval_with_rewind(const Object& obj, Object result = EmptyListObject::make_new(); try { result = eval(obj, env); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { if (!disable_printing) { printf("-----------------------------------------\n"); printf("From object %s\nat %s\n", obj.inspect().c_str(), reader.db.get_info_for(obj).c_str()); diff --git a/goalc/goos/InterpreterEval.cpp b/goalc/goos/InterpreterEval.cpp index 8f73c46052..183566402c 100644 --- a/goalc/goos/InterpreterEval.cpp +++ b/goalc/goos/InterpreterEval.cpp @@ -49,7 +49,7 @@ Object Interpreter::eval_read(const Object& form, try { return reader.read_from_string(args.unnamed.at(0).as_string()->data); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("reader error inside of read:\n") + e.what()); } @@ -67,7 +67,7 @@ Object Interpreter::eval_read_file(const Object& form, try { return reader.read_from_file(args.unnamed.at(0).as_string()->data); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("reader error inside of read-file:\n") + e.what()); } return EmptyListObject::make_new(); @@ -85,13 +85,13 @@ Object Interpreter::eval_load_file(const Object& form, Object o; try { o = reader.read_from_file(args.unnamed.at(0).as_string()->data); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("reader error inside of load-file:\n") + e.what()); } try { return eval_with_rewind(o, global_environment.as_env()); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_eval_error(form, std::string("eval error inside of load-file:\n") + e.what()); } return EmptyListObject::make_new(); diff --git a/goalc/goos/Object.cpp b/goalc/goos/Object.cpp index 1023ff3581..649947d1f5 100644 --- a/goalc/goos/Object.cpp +++ b/goalc/goos/Object.cpp @@ -33,7 +33,7 @@ std::string object_type_to_string(ObjectType type) { case ObjectType::ENVIRONMENT: return "[environment]"; default: - throw std::runtime_error("unknown object type in object_type_to_string"); + throw std::exception("unknown object type in object_type_to_string"); } } @@ -151,7 +151,7 @@ bool Object::operator==(const Object& other) const { } default: - throw std::runtime_error("equality not implemented for " + print()); + //throw std::exception("equality not implemented for " + print()); } } diff --git a/goalc/goos/Object.h b/goalc/goos/Object.h index 926014bc6e..bf45ba384d 100644 --- a/goalc/goos/Object.h +++ b/goalc/goos/Object.h @@ -222,78 +222,78 @@ class Object { std::shared_ptr as_pair() const { if (type != ObjectType::PAIR) { - throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_pair called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_env() const { if (type != ObjectType::ENVIRONMENT) { - throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print()); + // throw std::exception("as_env called on a " + object_type_to_string(type) + " " + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_symbol() const { if (type != ObjectType::SYMBOL) { - throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_symbol called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_string() const { if (type != ObjectType::STRING) { - throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_string called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_lambda() const { if (type != ObjectType::LAMBDA) { - throw std::runtime_error("as_lambda called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_lambda called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_macro() const { if (type != ObjectType::MACRO) { - throw std::runtime_error("as_macro called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_macro called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_array() const { if (type != ObjectType::ARRAY) { - throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_array called on a " + object_type_to_string(type) + " " + + // print()); } return std::dynamic_pointer_cast(heap_obj); } IntType& as_int() { if (type != ObjectType::INTEGER) { - throw std::runtime_error("as_int called on a " + object_type_to_string(type) + " " + print()); + // throw std::exception("as_int called on a " + object_type_to_string(type) + " " + print()); } return integer_obj.value; } FloatType& as_float() { if (type != ObjectType::FLOAT) { - throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_float called on a " + object_type_to_string(type) + " " + + // print()); } return float_obj.value; } char& as_char() { if (type != ObjectType::CHAR) { - throw std::runtime_error("as_char called on a " + object_type_to_string(type) + " " + - print()); + // throw std::exception("as_char called on a " + object_type_to_string(type) + " " + + // print()); } return char_obj.value; } diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index 7e195a73cc..33f1182d7b 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -102,7 +102,7 @@ Reader::Reader() { // find the source directory auto result = std::getenv("NEXT_DIR"); if (!result) { - throw std::runtime_error( + throw std::exception( "Environment variable NEXT_DIR is not set. Please set this to point to next/"); } @@ -588,7 +588,7 @@ bool Reader::try_token_as_binary(const Token& tok, Object& obj) { for (uint32_t i = 2; i < tok.text.size(); i++) { if (value & (0x8000000000000000)) { - throw std::runtime_error("overflow in binary constant: " + tok.text); + throw std::exception("overflow in binary constant: " + tok.text); } value <<= 1u; @@ -628,7 +628,7 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::runtime_error("The number " + tok.text + " cannot be a hexadecimal constant"); + throw std::exception("The number " + tok.text + " cannot be a hexadecimal constant"); } } return false; @@ -662,7 +662,7 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::runtime_error("The number " + tok.text + " cannot be an integer constant"); + throw std::exception("The number " + tok.text + " cannot be an integer constant"); } } return false; @@ -697,7 +697,7 @@ bool Reader::try_token_as_char(const Token& tok, Object& obj) { * Used for reader errors, like "missing close paren" or similar. */ void Reader::throw_reader_error(TextStream& here, const std::string& err, int seek_offset) { - throw std::runtime_error("Reader error:\n" + err + "\nat " + + throw std::exception("Reader error:\n" + err + "\nat " + db.get_info_for(here.text, here.seek + seek_offset)); } diff --git a/goalc/listener/Deci2Server.cpp b/goalc/listener/Deci2Server.cpp index 9b2a29f942..d4d8eafb31 100644 --- a/goalc/listener/Deci2Server.cpp +++ b/goalc/listener/Deci2Server.cpp @@ -214,7 +214,7 @@ void Deci2Server::run() { printf("[DECI2] Warning: no handler for this message, ignoring...\n"); unlock(); return; - // throw std::runtime_error("no handler!"); + // throw std::exception("no handler!"); } auto& driver = d2_drivers[handler]; diff --git a/goalc/listener/Deci2Server.h b/goalc/listener/Deci2Server.h index 45e3727851..c07e649711 100644 --- a/goalc/listener/Deci2Server.h +++ b/goalc/listener/Deci2Server.h @@ -2,7 +2,7 @@ * @file Deci2Server.h * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target - */ + #ifndef JAK1_DECI2SERVER_H #define JAK1_DECI2SERVER_H @@ -55,3 +55,5 @@ class Deci2Server { #endif // JAK1_DECI2SERVER_H + +*/ diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 72265faaba..8ab1c4563a 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -1,12 +1,11 @@ /*! * @file Listener.cpp * The Listener can connect to a Deci2Server for debugging. - */ + #include -#include -#include -#include +#include +#include #include #include "Listener.h" #include "common/versions.h" @@ -40,13 +39,11 @@ bool Listener::is_connected() const { return m_connected; } -/*! - * Attempt to connect to the target. If the target isn't running, this should fail quickly. - * Returns true if successfully 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!"); + throw std::exception("attempted a Listener::connect_to_target when already connected!"); } if (socket_fd >= 0) { @@ -73,8 +70,8 @@ bool Listener::connect_to_target(const std::string& ip, int port) { } // set nodelay, which makes small rapid messages faster, but large messages slower - int one = 1; - if (setsockopt(socket_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { + const char one = 1; + if (setsockopt(socket_fd, SOL_SOCKET, TCP_NODELAY, &one, sizeof(one))) { printf("[Listener] failed to TCP_NODELAY\n"); close(socket_fd); socket_fd = -1; @@ -144,7 +141,15 @@ 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 @@ -239,3 +244,5 @@ void Listener::receive_func() { } } // namespace listener + +*/ diff --git a/goalc/util/file_io.cpp b/goalc/util/file_io.cpp index d6b35e1735..44b93035c5 100644 --- a/goalc/util/file_io.cpp +++ b/goalc/util/file_io.cpp @@ -7,7 +7,7 @@ namespace util { std::string read_text_file(const std::string& path) { std::ifstream file(path); if (!file.good()) { - throw std::runtime_error("couldn't open " + path); + throw std::exception("couldn't open "); } std::stringstream ss; ss << file.rdbuf(); diff --git a/mman.c b/mman.c new file mode 100644 index 0000000000..486ed94d88 --- /dev/null +++ b/mman.c @@ -0,0 +1,180 @@ + +#include +#include +#include + +#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; +} diff --git a/test/all_jak1_symbols.cpp b/test/all_jak1_symbols.cpp index 9004c70890..e0089acc88 100644 --- a/test/all_jak1_symbols.cpp +++ b/test/all_jak1_symbols.cpp @@ -7748,7 +7748,7 @@ const char* all_syms[7941] = {"ripple-for-lava", "list-control", "sunken-pipegame-idle", "anim-test-edit-seq-insert-item", - "anim-tester-interface", + "anim-tester-interfaces", "anim-tester-adjust-frame", "extra-radius", "*volume-descriptor*", diff --git a/third-party/fmt/format-inl.h b/third-party/fmt/format-inl.h index d8c9c8a5ee..db590a275e 100644 --- a/third-party/fmt/format-inl.h +++ b/third-party/fmt/format-inl.h @@ -226,8 +226,8 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str, error_code_ = err_code; memory_buffer buffer; format_system_error(buffer, err_code, vformat(format_str, args)); - std::runtime_error& base = *this; - base = std::runtime_error(to_string(buffer)); + std::exception& base = *this; +// base = std::exception(to_string(buffer)); } namespace detail { @@ -1175,7 +1175,7 @@ int snprintf_float(T value, int precision, float_specs specs, auto capacity = buf.capacity() - offset; #ifdef FMT_FUZZ if (precision > 100000) - throw std::runtime_error( + throw std::exception( "fuzz mode - avoid large allocation inside snprintf"); #endif // Suppress the warning about a nonliteral format string. @@ -1327,7 +1327,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { auto cp = uint32_t(); auto error = 0; p = utf8_decode(p, &cp, &error); - if (error != 0) FMT_THROW(std::runtime_error("invalid utf8")); + if (error != 0) FMT_THROW(std::exception("invalid utf8")); if (cp <= 0xFFFF) { buffer_.push_back(static_cast(cp)); } else { diff --git a/third-party/fmt/format.cc b/third-party/fmt/format.cc index a64a1f3893..42ea06ed74 100644 --- a/third-party/fmt/format.cc +++ b/third-party/fmt/format.cc @@ -15,7 +15,7 @@ int format_float(char* buf, std::size_t size, const char* format, int precision, T value) { #ifdef FMT_FUZZ if (precision > 100000) - throw std::runtime_error( + throw std::exception( "fuzz mode - avoid large allocation inside snprintf"); #endif // Suppress the warning about nonliteral format string. diff --git a/third-party/fmt/format.h b/third-party/fmt/format.h index 17509b7b45..b312bb4bee 100644 --- a/third-party/fmt/format.h +++ b/third-party/fmt/format.h @@ -683,7 +683,7 @@ class basic_memory_buffer : public detail::buffer { template void basic_memory_buffer::grow(size_t size) { #ifdef FMT_FUZZ - if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much"); + if (size > 5000) throw std::exception("fuzz mode - won't grow that much"); #endif size_t old_capacity = this->capacity(); size_t new_capacity = old_capacity + old_capacity / 2; @@ -710,11 +710,11 @@ struct is_contiguous> : std::true_type { /** A formatting error such as invalid format string. */ FMT_CLASS_API -class FMT_API format_error : public std::runtime_error { +class FMT_API format_error : public std::exception { public: - explicit format_error(const char* message) : std::runtime_error(message) {} - explicit format_error(const std::string& message) - : std::runtime_error(message) {} + explicit format_error(const char* message) : std::exception(message) {} + explicit format_error(const std::string& message); + // : std::exception(message) {} format_error(const format_error&) = default; format_error& operator=(const format_error&) = default; format_error(format_error&&) = default; @@ -1145,7 +1145,7 @@ template class float_writer { } #ifdef FMT_FUZZ if (num_zeros > 5000) - throw std::runtime_error("fuzz mode - avoiding excessive cpu use"); + throw std::exception("fuzz mode - avoiding excessive cpu use"); #endif it = std::fill_n(it, num_zeros, static_cast('0')); } @@ -2952,14 +2952,14 @@ using arg_formatter FMT_DEPRECATED_ALIAS = for example a file opening error. */ FMT_CLASS_API -class FMT_API system_error : public std::runtime_error { +class FMT_API system_error : public std::exception { private: void init(int err_code, string_view format_str, format_args args); protected: int error_code_; - system_error() : std::runtime_error(""), error_code_(0) {} + system_error() : std::exception(""), error_code_(0) {} public: /** @@ -2982,7 +2982,7 @@ class FMT_API system_error : public std::runtime_error { */ template system_error(int error_code, string_view message, const Args&... args) - : std::runtime_error("") { + : std::exception("") { init(error_code, message, make_format_args(args...)); } system_error(const system_error&) = default; diff --git a/third-party/json.hpp b/third-party/json.hpp index 9c66a8457f..54e5f75365 100644 --- a/third-party/json.hpp +++ b/third-party/json.hpp @@ -70,7 +70,7 @@ SOFTWARE. #include // exception -#include // runtime_error +#include // exception #include // to_string // #include @@ -92,7 +92,7 @@ struct position_t /// the number of lines read std::size_t lines_read = 0; - /// conversion to size_t to preserve SAX interface + /// conversion to size_t to preserve SAX interfaces constexpr operator size_t() const { return chars_read_total; @@ -2339,7 +2339,7 @@ Subclasses: @internal @note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. + `std::exception` which can cope with arbitrary-length error messages. Intermediate strings are built with static functions and then passed to the actual constructor. @endinternal @@ -2373,7 +2373,7 @@ class exception : public std::exception private: /// an exception object as storage for error messages - std::runtime_error m; + std::exception m; }; /*! @@ -4823,7 +4823,7 @@ class input_stream_adapter std::char_traits::int_type get_character() { auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interface. + // set eof manually, as we don't use the istream interfaces. if (JSON_HEDLEY_UNLIKELY(res == EOF)) { is->clear(is->rdstate() | std::ios::eofbit); @@ -5191,9 +5191,9 @@ namespace nlohmann { /*! -@brief SAX interface +@brief SAX interfaces -This class describes the SAX interface used by @ref nlohmann::json::sax_parse. +This class describes the SAX interfaces used by @ref nlohmann::json::sax_parse. Each function is called in different situations while the input is parsed. The boolean return value informs the parser whether to continue processing the input. @@ -5314,7 +5314,7 @@ namespace detail /*! @brief SAX implementation to create a JSON value from SAX events -This class implements the @ref json_sax interface and processes the SAX events +This class implements the @ref json_sax interfaces and processes the SAX events to create a JSON value which makes it basically a DOM parser. The structure or hierarchy of the JSON value is managed by the stack `ref_stack` which contains a pointer to the respective array or object for each recursion depth. @@ -7198,7 +7198,7 @@ scan_number_done: /* @brief get next character from the input - This function provides the interface to the used input adapter. It does + This function provides the interfaces to the used input adapter. It does not throw in case the input reached EOF, but returns a `std::char_traits::eof()` in that case. Stores the scanned characters for use in error messages. @@ -9881,7 +9881,7 @@ class binary_reader /*! @brief get next character from the input - This function provides the interface to the used input adapter. It does + This function provides the interfaces to the used input adapter. It does not throw in case the input reached EOF, but returns a -'ve valued `std::char_traits::eof()` in that case. @@ -10184,7 +10184,7 @@ class parser } /*! - @brief public parser interface + @brief public parser interfaces @param[in] strict whether to expect the last token to be EOF @param[in,out] result parsed JSON value @@ -10249,7 +10249,7 @@ class parser } /*! - @brief public accept interface + @brief public accept interfaces @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text @@ -12628,7 +12628,7 @@ namespace nlohmann { namespace detail { -/// abstract output adapter interface +/// abstract output adapter interfaces template struct output_adapter_protocol { virtual void write_character(CharType c) = 0; @@ -16724,7 +16724,7 @@ class basic_json using initializer_list_t = std::initializer_list>; using input_format_t = detail::input_format_t; - /// SAX interface type, see @ref nlohmann::json_sax + /// SAX interfaces type, see @ref nlohmann::json_sax using json_sax_t = json_sax; //////////////// @@ -21253,7 +21253,7 @@ class basic_json element as string (see example). @param[in] ref reference to a JSON value - @return iteration proxy object wrapping @a ref with an interface to use in + @return iteration proxy object wrapping @a ref with an interfaces to use in range-based for loops @liveexample{The following code shows how the wrapper is used,iterator_wrapper} @@ -21341,7 +21341,7 @@ class basic_json for more information. - @return iteration proxy object wrapping @a ref with an interface to use in + @return iteration proxy object wrapping @a ref with an interfaces to use in range-based for loops @liveexample{The following code shows how the function is used.,items} @@ -23249,7 +23249,7 @@ class basic_json /*! @brief generate SAX events - The SAX event lister must follow the interface of @ref json_sax. + The SAX event lister must follow the interfaces of @ref json_sax. This function reads from a compatible input. Examples are: - an std::istream object diff --git a/third-party/minilzo/lzoconf.h b/third-party/minilzo/lzoconf.h index f9a8bdbee7..a8ffb99ef8 100644 --- a/third-party/minilzo/lzoconf.h +++ b/third-party/minilzo/lzoconf.h @@ -264,7 +264,7 @@ typedef int const lzo_bytep dict, lzo_uint dict_len ); -/* Callback interface. Currently only the progress indicator ("nprogress") +/* Callback interfaces. Currently only the progress indicator ("nprogress") * is used, but this may change in a future release. */ struct lzo_callback_t; diff --git a/third-party/mman.h b/third-party/mman.h new file mode 100644 index 0000000000..220b37ddec --- /dev/null +++ b/third-party/mman.h @@ -0,0 +1,57 @@ +/* + * sys/mman.h + * mman-win32 + */ + +#ifndef _SYS_MMAN_H_ +#define _SYS_MMAN_H_ + +#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. +#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. +#endif + +/* All the headers include this file. */ +#ifndef _MSC_VER +#include <_mingw.h> +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_TYPE 0xf +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */ +#define MAP_ANON MAP_ANONYMOUS + +#define MAP_FAILED ((void *)-1) + +/* Flags for msync. */ +#define MS_ASYNC 1 +#define MS_SYNC 2 +#define MS_INVALIDATE 4 +#define MAP_POPULATE 0x08000 + +void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); +int munmap(void *addr, size_t len); +int mprotect(void *addr, size_t len, int prot); +int msync(void *addr, size_t len, int flags); +int mlock(const void *addr, size_t len); +int munlock(const void *addr, size_t len); + +#ifdef __cplusplus +}; +#endif + +#endif /* _SYS_MMAN_H_ */ From 406549bf6adc8d4b1e1ec0e8109b04decfb650db Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 26 Aug 2020 21:08:18 -0400 Subject: [PATCH 07/32] some small changes --- game/CMakeLists.txt | 9 ++++++++- game/runtime.cpp | 2 +- goalc/emitter/CodeTester.cpp | 2 +- mman.c => third-party/mman/mman.c | 0 third-party/{ => mman}/mman.h | 0 5 files changed, 10 insertions(+), 3 deletions(-) rename mman.c => third-party/mman/mman.c (100%) rename third-party/{ => mman}/mman.h (100%) diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 5e79e3eb31..009350b124 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -71,4 +71,11 @@ add_executable(gk ${RUNTIME_SOURCE}) # can be used to test other things. add_library(runtime ${RUNTIME_SOURCE}) -target_link_libraries(gk pthread) \ No newline at end of file + +IF (WIN32) + # set stuff for windows + target_link_libraries(gk) +ELSE() + # set stuff for other systems + target_link_libraries(gk pthread) +ENDIF() diff --git a/game/runtime.cpp b/game/runtime.cpp index 5f8cb3b7a3..7bd2b42b66 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include diff --git a/goalc/emitter/CodeTester.cpp b/goalc/emitter/CodeTester.cpp index 676841797f..c40f6a8d52 100644 --- a/goalc/emitter/CodeTester.cpp +++ b/goalc/emitter/CodeTester.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include "CodeTester.h" #include "Instruction.h" diff --git a/mman.c b/third-party/mman/mman.c similarity index 100% rename from mman.c rename to third-party/mman/mman.c diff --git a/third-party/mman.h b/third-party/mman/mman.h similarity index 100% rename from third-party/mman.h rename to third-party/mman/mman.h From 1dc206edb9df8aec43fecf84589b1c84407be82e Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Wed, 26 Aug 2020 19:34:54 -0600 Subject: [PATCH 08/32] More fixes Comment out related deci2 code until networking can be reworked. Resolved std::exception errors with a temporary fix --- game/runtime.cpp | 2 +- goalc/goos/Object.cpp | 2 +- goalc/goos/Reader.cpp | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/game/runtime.cpp b/game/runtime.cpp index 7bd2b42b66..89de649c25 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -227,7 +227,7 @@ void exec_runtime(int argc, char** argv) { // step 1: sce library prep iop::LIBRARY_INIT(); ee::LIBRARY_INIT_sceCd(); - ee::LIBRARY_INIT_sceDeci2(); + //ee::LIBRARY_INIT_sceDeci2(); ee::LIBRARY_INIT_sceSif(); // step 2: system prep diff --git a/goalc/goos/Object.cpp b/goalc/goos/Object.cpp index 649947d1f5..0b5792a039 100644 --- a/goalc/goos/Object.cpp +++ b/goalc/goos/Object.cpp @@ -151,7 +151,7 @@ bool Object::operator==(const Object& other) const { } default: - //throw std::exception("equality not implemented for " + print()); + throw std::exception("equality not implemented for"); } } diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index 33f1182d7b..58882e9cf6 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -588,7 +588,7 @@ bool Reader::try_token_as_binary(const Token& tok, Object& obj) { for (uint32_t i = 2; i < tok.text.size(); i++) { if (value & (0x8000000000000000)) { - throw std::exception("overflow in binary constant: " + tok.text); + throw std::exception("overflow in binary constant:)"); } value <<= 1u; @@ -628,7 +628,7 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::exception("The number " + tok.text + " cannot be a hexadecimal constant"); + throw std::exception("The number cannot be a hexadecimal constant"); } } return false; @@ -662,7 +662,7 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::exception("The number " + tok.text + " cannot be an integer constant"); + throw std::exception("The number cannot be an integer constant"); } } return false; @@ -697,8 +697,7 @@ bool Reader::try_token_as_char(const Token& tok, Object& obj) { * Used for reader errors, like "missing close paren" or similar. */ void Reader::throw_reader_error(TextStream& here, const std::string& err, int seek_offset) { - throw std::exception("Reader error:\n" + err + "\nat " + - db.get_info_for(here.text, here.seek + seek_offset)); + throw std::exception("Reader error at"); } /*! From 51c23aaedeb9121a1547313a6cdbafb088ef013a Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Wed, 26 Aug 2020 22:23:16 -0400 Subject: [PATCH 09/32] A whole bunch of cmake fixes --- CMakeLists.txt | 11 ++- game/CMakeLists.txt | 2 +- game/runtime.cpp | 68 +++++++------- game/sce/deci2.cpp | 156 ++++++++++++++++---------------- goalc/CMakeLists.txt | 11 ++- goalc/goos/Object.cpp | 2 +- goalc/goos/Reader.cpp | 8 +- goalc/listener/Deci2Server.cpp | 4 +- test/CMakeLists.txt | 8 +- test/test_kernel.cpp | 4 +- test/test_listener_deci2.cpp | 5 +- third-party/mman.h | 57 ------------ third-party/mman/CMakeLists.txt | 1 + third-party/mman/mman.h | 2 +- 14 files changed, 157 insertions(+), 182 deletions(-) delete mode 100644 third-party/mman.h create mode 100644 third-party/mman/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index ce4228908f..1b676f7dfc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,10 @@ if(CMAKE_COMPILER_IS_GNUCXX) -Wsign-promo") endif(CMAKE_COMPILER_IS_GNUCXX) +IF (WIN32) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +ENDIF() + # includes relative to top level jak-project folder include_directories(./) @@ -53,4 +57,9 @@ add_subdirectory(test) add_subdirectory(third-party/minilzo) # build format library -add_subdirectory(third-party/fmt) \ No newline at end of file +add_subdirectory(third-party/fmt) + +# windows memory management lib +IF (WIN32) + add_subdirectory(third-party/mman) +ENDIF() \ No newline at end of file diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 009350b124..f35f7dc47d 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -74,7 +74,7 @@ add_library(runtime ${RUNTIME_SOURCE}) IF (WIN32) # set stuff for windows - target_link_libraries(gk) + target_link_libraries(gk mman) ELSE() # set stuff for other systems target_link_libraries(gk pthread) diff --git a/game/runtime.cpp b/game/runtime.cpp index 7bd2b42b66..19981da5e9 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -46,44 +46,42 @@ namespace { */ -/* void deci2_runner(SystemThreadInterface& interfaces) { - // callback function so the server knows when to give up and shutdown - std::function 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::exception("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); - } - } +// // callback function so the server knows when to give up and shutdown +// std::function 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::exception("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); +// } +// } } -*/ // EE System diff --git a/game/sce/deci2.cpp b/game/sce/deci2.cpp index 75b7a076d5..541eb5db3e 100644 --- a/game/sce/deci2.cpp +++ b/game/sce/deci2.cpp @@ -1,7 +1,7 @@ /*! * @file deci2.cpp * Implementation of SCE DECI2 library. - + */ #include #include @@ -12,127 +12,131 @@ 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 +// 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 } // namespace - +/* * Initialize the library. - + */ void LIBRARY_INIT_sceDeci2() { - // reset protocols - for (auto& p : protocols) { - p = Deci2Driver(); - } - protocol_count = 0; - server = nullptr; - sending_driver = nullptr; + // // reset protocols + // for (auto& p : protocols) { + // p = Deci2Driver(); + // } + // protocol_count = 0; + // server = nullptr; + // sending_driver = nullptr; } /*! * Run any pending requested sends. - + */ void LIBRARY_sceDeci2_run_sends() { - 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); - } - } + 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); + // } + //} } /*! * Register a Deci2Server with this library. - + */ void LIBRARY_sceDeci2_register(::Deci2Server* s) { - server = s; + // server = s; } /*! * Open a new socket with given protocol number and handler. * The "opt" pointer is passed to the handler function. * 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(); + // 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; + return 0; } /*! * Deactivate a DECI2 protocol by socket descriptor. - + */ s32 sceDeci2Close(s32 s) { - assert(s - 1 < protocol_count); - protocols[s - 1].active = false; + // assert(s - 1 < protocol_count); + // protocols[s - 1].active = false; + // return 1; return 1; } /*! * Start a send. - + */ s32 sceDeci2ReqSend(s32 s, char dest) { - assert(s - 1 < protocol_count); - auto& proto = protocols[s - 1]; - proto.pending_send = dest; + // assert(s - 1 < protocol_count); + // auto& proto = protocols[s - 1]; + // proto.pending_send = dest; + // return 0; return 0; } /*! * Do a receive from socket s into buf of size len. * 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; - } + // 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; + //} + return 0; } /*! * 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; + // 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; } } // namespace ee - -*/ \ No newline at end of file diff --git a/goalc/CMakeLists.txt b/goalc/CMakeLists.txt index 562b73af64..37507451f6 100644 --- a/goalc/CMakeLists.txt +++ b/goalc/CMakeLists.txt @@ -1,8 +1,17 @@ add_subdirectory(util) add_subdirectory(goos) -add_subdirectory(listener) +IF (WIN32) + # TODO - implement windows listener + message("Windows Listener Not Implemented!") +ELSE() + add_subdirectory(listener) +ENDIF() add_subdirectory(emitter) add_executable(goalc main.cpp) +IF (WIN32) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +ENDIF() + target_link_libraries(goalc util goos) \ No newline at end of file diff --git a/goalc/goos/Object.cpp b/goalc/goos/Object.cpp index 649947d1f5..7a2feeae55 100644 --- a/goalc/goos/Object.cpp +++ b/goalc/goos/Object.cpp @@ -151,7 +151,7 @@ bool Object::operator==(const Object& other) const { } default: - //throw std::exception("equality not implemented for " + print()); + throw std::runtime_error("equality not implemented for " + print()); } } diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index 33f1182d7b..0d7ff7368b 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -588,7 +588,7 @@ bool Reader::try_token_as_binary(const Token& tok, Object& obj) { for (uint32_t i = 2; i < tok.text.size(); i++) { if (value & (0x8000000000000000)) { - throw std::exception("overflow in binary constant: " + tok.text); + throw std::runtime_error("overflow in binary constant: " + tok.text); } value <<= 1u; @@ -628,7 +628,7 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::exception("The number " + tok.text + " cannot be a hexadecimal constant"); + throw std::runtime_error("The number " + tok.text + " cannot be a hexadecimal constant"); } } return false; @@ -662,7 +662,7 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::exception("The number " + tok.text + " cannot be an integer constant"); + throw std::runtime_error("The number " + tok.text + " cannot be an integer constant"); } } return false; @@ -697,7 +697,7 @@ bool Reader::try_token_as_char(const Token& tok, Object& obj) { * Used for reader errors, like "missing close paren" or similar. */ void Reader::throw_reader_error(TextStream& here, const std::string& err, int seek_offset) { - throw std::exception("Reader error:\n" + err + "\nat " + + throw std::runtime_error("Reader error:\n" + err + "\nat " + db.get_info_for(here.text, here.seek + seek_offset)); } diff --git a/goalc/listener/Deci2Server.cpp b/goalc/listener/Deci2Server.cpp index d4d8eafb31..4b20b4c3ec 100644 --- a/goalc/listener/Deci2Server.cpp +++ b/goalc/listener/Deci2Server.cpp @@ -3,7 +3,7 @@ * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target */ - +#ifdef __unix__ #include #include #include @@ -262,3 +262,5 @@ void Deci2Server::accept_thread_func() { } } } + +#endif \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3cff0d2440..ccb48ee674 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -9,4 +9,10 @@ add_executable(goalc-test all_jak1_symbols.cpp test_type_system.cpp) -target_link_libraries(goalc-test goos util listener runtime emitter type_system gtest) \ No newline at end of file +IF (WIN32) + # TODO - implement windows listener + message("Windows Listener Not Implemented!") + target_link_libraries(goalc-test goos util runtime emitter type_system gtest) +ELSE() + target_link_libraries(goalc-test goos util listener runtime emitter type_system gtest) +ENDIF() diff --git a/test/test_kernel.cpp b/test/test_kernel.cpp index 064449aed9..0e5b3b96ba 100644 --- a/test/test_kernel.cpp +++ b/test/test_kernel.cpp @@ -156,7 +156,7 @@ TEST(Kernel, ftoa) { ftoa(buffer, 1., 1, ' ', 1, 0); EXPECT_EQ("1.0", std::string(buffer)); - ftoa(buffer, 0.f / 0.f, 1, ' ', 4, 0); + //ftoa(buffer, 0.f / 0.f, 1, ' ', 4, 0); EXPECT_EQ("NaN", std::string(buffer)); ftoa(buffer, 1., 8, ' ', 1, 0); @@ -165,7 +165,7 @@ TEST(Kernel, ftoa) { ftoa(buffer, -1., 8, '0', 1, 0); EXPECT_EQ("0000-1.0", std::string(buffer)); - ftoa(buffer, 0.f / 0.f, 8, ' ', 4, 0); + //ftoa(buffer, 0.f / 0.f, 8, ' ', 4, 0); EXPECT_EQ(" NaN", std::string(buffer)); ftoa(buffer, 0.1, 1, ' ', 4, 0); diff --git a/test/test_listener_deci2.cpp b/test/test_listener_deci2.cpp index 4efa4d5bd9..0422beec05 100644 --- a/test/test_listener_deci2.cpp +++ b/test/test_listener_deci2.cpp @@ -1,3 +1,5 @@ +#ifdef __unix__ + #include "gtest/gtest.h" #include "goalc/listener/Listener.h" #include "goalc/listener/Deci2Server.h" @@ -118,5 +120,6 @@ TEST(Listener, ListenerMultipleDecis) { } l.disconnect(); } +} -} \ No newline at end of file +#endif \ No newline at end of file diff --git a/third-party/mman.h b/third-party/mman.h deleted file mode 100644 index 220b37ddec..0000000000 --- a/third-party/mman.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * sys/mman.h - * mman-win32 - */ - -#ifndef _SYS_MMAN_H_ -#define _SYS_MMAN_H_ - -#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. -#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. -#endif - -/* All the headers include this file. */ -#ifndef _MSC_VER -#include <_mingw.h> -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define PROT_NONE 0 -#define PROT_READ 1 -#define PROT_WRITE 2 -#define PROT_EXEC 4 - -#define MAP_FILE 0 -#define MAP_SHARED 1 -#define MAP_PRIVATE 2 -#define MAP_TYPE 0xf -#define MAP_FIXED 0x10 -#define MAP_ANONYMOUS 0x20 -#define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */ -#define MAP_ANON MAP_ANONYMOUS - -#define MAP_FAILED ((void *)-1) - -/* Flags for msync. */ -#define MS_ASYNC 1 -#define MS_SYNC 2 -#define MS_INVALIDATE 4 -#define MAP_POPULATE 0x08000 - -void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); -int munmap(void *addr, size_t len); -int mprotect(void *addr, size_t len, int prot); -int msync(void *addr, size_t len, int flags); -int mlock(const void *addr, size_t len); -int munlock(const void *addr, size_t len); - -#ifdef __cplusplus -}; -#endif - -#endif /* _SYS_MMAN_H_ */ diff --git a/third-party/mman/CMakeLists.txt b/third-party/mman/CMakeLists.txt new file mode 100644 index 0000000000..bc8675e384 --- /dev/null +++ b/third-party/mman/CMakeLists.txt @@ -0,0 +1 @@ +add_library(mman SHARED mman.c) \ No newline at end of file diff --git a/third-party/mman/mman.h b/third-party/mman/mman.h index 220b37ddec..febfbcbca1 100644 --- a/third-party/mman/mman.h +++ b/third-party/mman/mman.h @@ -29,6 +29,7 @@ extern "C" { #define MAP_FILE 0 #define MAP_SHARED 1 #define MAP_PRIVATE 2 +#define MAP_POPULATE 0x08000 #define MAP_TYPE 0xf #define MAP_FIXED 0x10 #define MAP_ANONYMOUS 0x20 @@ -41,7 +42,6 @@ extern "C" { #define MS_ASYNC 1 #define MS_SYNC 2 #define MS_INVALIDATE 4 -#define MAP_POPULATE 0x08000 void* mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); int munmap(void *addr, size_t len); From 8a81ff78dd9131f6b15b5e18e93e8e98b1256795 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Wed, 26 Aug 2020 20:23:22 -0600 Subject: [PATCH 10/32] Windows fixes Partially addresses issues with unresolved external symbols --- game/kernel/kboot.cpp | 2 +- game/kernel/kdsnetm.cpp | 20 ++++++++++++++------ goalc/CMakeLists.txt | 4 ++++ goalc/goos/CMakeLists.txt | 2 +- goalc/listener/Deci2Server.cpp | 23 ++++++++++++++--------- 5 files changed, 34 insertions(+), 17 deletions(-) diff --git a/game/kernel/kboot.cpp b/game/kernel/kboot.cpp index e6d53fa857..babb26f3b2 100644 --- a/game/kernel/kboot.cpp +++ b/game/kernel/kboot.cpp @@ -128,7 +128,7 @@ void KernelCheckAndDispatch() { // dispatch the kernel //(**kernel_dispatcher)(); call_goal(Ptr(kernel_dispatcher->value), 0, 0, 0, s7.offset, g_ee_main_mem); - ClearPending(); + //ClearPending(); // if the listener function changed, it means the kernel ran it, so we should notify compiler. if (MasterDebug && ListenerFunction->value != old_listener) { diff --git a/game/kernel/kdsnetm.cpp b/game/kernel/kdsnetm.cpp index 8dcec18a9b..00f1080c7e 100644 --- a/game/kernel/kdsnetm.cpp +++ b/game/kernel/kdsnetm.cpp @@ -1,3 +1,6 @@ + + +/* /*! * @file kdsnetm.cpp * Low-level DECI2 wrapper for ksocket @@ -30,7 +33,7 @@ void kdsnetm_init_globals() { /*! * Register GOAL DECI2 Protocol Driver with DECI2 service * DONE, EXACT - */ + void InitGoalProto() { protoBlock.socket = sceDeci2Open(DECI2_PROTOCOL, &protoBlock, GoalProtoHandler); if (protoBlock.socket < 0) { @@ -46,10 +49,12 @@ void InitGoalProto() { } } +*/ + /*! * Close the DECI2 Protocol Driver * DONE, EXACT - */ + void ShutdownGoalProto() { if (protoBlock.socket > 0) { sceDeci2Close(protoBlock.socket); @@ -60,7 +65,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? @@ -160,7 +165,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) { @@ -215,8 +220,11 @@ 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); -} \ No newline at end of file +} + + +*/ \ No newline at end of file diff --git a/goalc/CMakeLists.txt b/goalc/CMakeLists.txt index 562b73af64..fd52e9b40f 100644 --- a/goalc/CMakeLists.txt +++ b/goalc/CMakeLists.txt @@ -5,4 +5,8 @@ add_subdirectory(emitter) add_executable(goalc main.cpp) +IF (WIN32) + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +ENDIF() + target_link_libraries(goalc util goos) \ No newline at end of file diff --git a/goalc/goos/CMakeLists.txt b/goalc/goos/CMakeLists.txt index a6b2e6b489..2da8649efc 100644 --- a/goalc/goos/CMakeLists.txt +++ b/goalc/goos/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(goos SHARED Object.cpp TextDB.cpp Reader.cpp Interpreter.cpp InterpreterEval.cpp) +add_library(goos STATIC Object.cpp TextDB.cpp Reader.cpp Interpreter.cpp InterpreterEval.cpp) target_link_libraries(goos util) \ No newline at end of file diff --git a/goalc/listener/Deci2Server.cpp b/goalc/listener/Deci2Server.cpp index d4d8eafb31..a49cb20651 100644 --- a/goalc/listener/Deci2Server.cpp +++ b/goalc/listener/Deci2Server.cpp @@ -1,8 +1,12 @@ + + + + /*! * @file Deci2Server.cpp * Basic implementation of a DECI2 server. * Works with deci2.cpp (sceDeci2) to implement the networking on target - */ + #include #include @@ -41,7 +45,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) { @@ -103,7 +107,7 @@ bool Deci2Server::init() { /*! * Return true if the listener is connected. - */ + bool Deci2Server::check_for_listener() { if (server_connected) { if (accept_thread_running) { @@ -118,7 +122,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) { @@ -139,14 +143,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(); } @@ -154,7 +158,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; @@ -167,7 +171,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; @@ -249,7 +253,7 @@ void Deci2Server::run() { /*! * Background thread for waiting for the listener. - */ + void Deci2Server::accept_thread_func() { socklen_t l = sizeof(addr); while (!kill_accept_thread) { @@ -262,3 +266,4 @@ void Deci2Server::accept_thread_func() { } } } +*/ \ No newline at end of file From 86ee6637fe47d91b214dfddfa2feb70807481894 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Wed, 26 Aug 2020 21:12:32 -0600 Subject: [PATCH 11/32] Symbol fixes Quick fixing a few more unresolved symbols. This should compile as is, but will not run as it requires mman.dll. --- game/kernel/kdsnetm.h | 6 +++--- game/kernel/klisten.cpp | 10 +++++----- game/kernel/kmachine.cpp | 4 ++-- game/kernel/ksocket.cpp | 6 +++--- goalc/goos/Reader.cpp | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/game/kernel/kdsnetm.h b/game/kernel/kdsnetm.h index bdbef66096..f49a5132ae 100644 --- a/game/kernel/kdsnetm.h +++ b/game/kernel/kdsnetm.h @@ -55,13 +55,13 @@ void kdsnetm_init_globals(); * 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(); /*! * Handle a DECI2 Protocol Event for the GOAL Proto. @@ -76,7 +76,7 @@ void GoalProtoHandler(int event, int param, void* data); * DONE, original version used an uncached address and had a FlushCache call, which were both * removed */ -s32 SendFromBufferD(s32 p1, u64 p2, char* data, s32 size); +//s32 SendFromBufferD(s32 p1, u64 p2, char* data, s32 size); /*! * Print GOAL Protocol status diff --git a/game/kernel/klisten.cpp b/game/kernel/klisten.cpp index dc29e08043..ed78cd297d 100644 --- a/game/kernel/klisten.cpp +++ b/game/kernel/klisten.cpp @@ -71,7 +71,7 @@ void ClearPending() { Ptr msg = OutputBufArea.cast() + 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); + // SendFromBuffer(msg.c(), size); clear_output(); } @@ -84,7 +84,7 @@ void ClearPending() { if (send_size > 64000) { send_size = 64000; } - SendFromBufferD(2, 0, msg, send_size); +// SendFromBufferD(2, 0, msg, send_size); size -= send_size; msg += send_size; } @@ -103,9 +103,9 @@ void ClearPending() { */ void SendAck() { if (MasterDebug) { - SendFromBufferD(u16(ListenerMessageKind::MSG_ACK), protoBlock.msg_id, - AckBufArea + sizeof(GoalMessageHeader), - strlen(AckBufArea + sizeof(GoalMessageHeader))); +// SendFromBufferD(u16(ListenerMessageKind::MSG_ACK), protoBlock.msg_id, + // AckBufArea + sizeof(GoalMessageHeader), + // strlen(AckBufArea + sizeof(GoalMessageHeader))); } } diff --git a/game/kernel/kmachine.cpp b/game/kernel/kmachine.cpp index 168619844a..91d6194fbb 100644 --- a/game/kernel/kmachine.cpp +++ b/game/kernel/kmachine.cpp @@ -329,7 +329,7 @@ int InitMachine() { // } if (MasterDebug) { // connect to GOAL compiler - InitGoalProto(); +// InitGoalProto(); } printf("InitSound\n"); @@ -359,7 +359,7 @@ int ShutdownMachine() { StopIOP(); CloseListener(); ShutdownSound(); - ShutdownGoalProto(); +// ShutdownGoalProto(); Msg(6, "kernel: machine shutdown"); return 0; } diff --git a/game/kernel/ksocket.cpp b/game/kernel/ksocket.cpp index 4eb0194017..cf6faf5e7d 100644 --- a/game/kernel/ksocket.cpp +++ b/game/kernel/ksocket.cpp @@ -57,9 +57,9 @@ u32 ReceiveToBuffer(char* buff) { * 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); + /*! * Just prepare the Ack buffer, doesn't actually connect. diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index 58882e9cf6..a66bafb5ca 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -588,7 +588,7 @@ bool Reader::try_token_as_binary(const Token& tok, Object& obj) { for (uint32_t i = 2; i < tok.text.size(); i++) { if (value & (0x8000000000000000)) { - throw std::exception("overflow in binary constant:)"); + throw std::runtime_error("overflow in binary constant:)"); } value <<= 1u; From 311e025fe9685a51ca86892aea05c4e9ba36367d Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Wed, 26 Aug 2020 21:45:52 -0600 Subject: [PATCH 12/32] Update CMakeLists.txt Quick fix to resolve missing dependency issue. Will compile on the fly. Next task is threading system --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b676f7dfc..af6508aeee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,9 @@ 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) ENDIF() # includes relative to top level jak-project folder From 92976234a14b20b6d7165ea750e18ee4dcb27bd9 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Wed, 26 Aug 2020 22:24:03 -0600 Subject: [PATCH 13/32] Replacing std::exception with std::runtime_error --- common/type_system/Type.cpp | 16 +++++----- common/type_system/TypeSystem.cpp | 26 +++++++-------- common/type_system/TypeSystem.h | 2 +- decompiler/ObjectFile/LinkedObjectFile.cpp | 2 +- .../ObjectFile/LinkedObjectFileCreation.cpp | 4 +-- decompiler/util/FileIO.cpp | 6 ++-- decompiler/util/LispPrint.cpp | 4 +-- decompiler/util/LispPrint.h | 2 +- game/kernel/Ptr.h | 4 +-- game/kernel/klink.cpp | 2 +- game/kernel/kprint.cpp | 32 +++++++++---------- game/kernel/kscheme.cpp | 10 +++--- game/runtime.cpp | 2 +- game/sce/iop.cpp | 4 +-- game/sce/stubs.cpp | 10 +++--- game/system/Deci2Server.cpp | 2 +- game/system/IOP_Kernel.cpp | 16 +++++----- game/system/IOP_Kernel.h | 6 ++-- game/system/SystemThread.cpp | 2 +- goalc/goos/Interpreter.cpp | 6 ++-- goalc/goos/InterpreterEval.cpp | 8 ++--- goalc/goos/Object.cpp | 4 +-- goalc/goos/Object.h | 20 ++++++------ goalc/goos/Reader.cpp | 16 +++++----- goalc/listener/Deci2Server.cpp | 2 +- goalc/listener/Listener.cpp | 2 +- goalc/util/file_io.cpp | 2 +- third-party/fmt/format-inl.h | 8 ++--- third-party/fmt/format.cc | 2 +- third-party/fmt/format.h | 16 +++++----- third-party/json.hpp | 8 ++--- 31 files changed, 123 insertions(+), 123 deletions(-) diff --git a/common/type_system/Type.cpp b/common/type_system/Type.cpp index 160af24e3e..3dd0fe1a80 100644 --- a/common/type_system/Type.cpp +++ b/common/type_system/Type.cpp @@ -227,35 +227,35 @@ std::string Type::print_method_info() const { NoneType::NoneType() : Type("", "none", false) {} bool NoneType::is_reference() const { - throw std::exception("is_reference called on NoneType"); + throw std::runtime_error("is_reference called on NoneType"); } int NoneType::get_load_size() const { - throw std::exception("get_load_size called on NoneType"); + throw std::runtime_error("get_load_size called on NoneType"); } bool NoneType::get_load_signed() const { - throw std::exception("get_load_size called on NoneType"); + throw std::runtime_error("get_load_size called on NoneType"); } int NoneType::get_size_in_memory() const { - throw std::exception("get_size_in_memory called on NoneType"); + throw std::runtime_error("get_size_in_memory called on NoneType"); } RegKind NoneType::get_preferred_reg_kind() const { - throw std::exception("get_preferred_reg_kind called on NoneType"); + throw std::runtime_error("get_preferred_reg_kind called on NoneType"); } int NoneType::get_offset() const { - throw std::exception("get_offset called on NoneType"); + throw std::runtime_error("get_offset called on NoneType"); } int NoneType::get_in_memory_alignment() const { - throw std::exception("get_in_memory_alignment called on NoneType"); + throw std::runtime_error("get_in_memory_alignment called on NoneType"); } int NoneType::get_inline_array_alignment() const { - throw std::exception("get_inline_array_alignment called on NoneType"); + throw std::runtime_error("get_inline_array_alignment called on NoneType"); } std::string NoneType::print() const { diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index 9cbabfd54a..76e4005c59 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -32,7 +32,7 @@ Type* TypeSystem::add_type(const std::string& name, std::unique_ptr type) // update the type m_types[name] = std::move(type); } else { - throw std::exception("Type was redefined with throw_on_redefine set."); + throw std::runtime_error("Type was redefined with throw_on_redefine set."); } } } else { @@ -43,13 +43,13 @@ Type* TypeSystem::add_type(const std::string& name, std::unique_ptr type) if (m_forward_declared_types.find(type->get_parent()) != m_forward_declared_types.end()) { fmt::print("[TypeSystem] Type {} has incompletely defined parent {}\n", type->get_name(), type->get_parent()); - throw std::exception("add_type failed"); + throw std::runtime_error("add_type failed"); } if (m_types.find(type->get_parent()) == m_types.end()) { fmt::print("[TypeSystem] Type {} has undefined parent {}\n", type->get_name(), type->get_parent()); - throw std::exception("add_type failed"); + throw std::runtime_error("add_type failed"); } } @@ -135,7 +135,7 @@ TypeSpec TypeSystem::make_typespec(const std::string& name) { return TypeSpec(name); } else { fmt::print("[TypeSystem] The type {} is unknown.\n", name); - throw std::exception("make_typespec failed"); + throw std::runtime_error("make_typespec failed"); } } @@ -199,7 +199,7 @@ Type* TypeSystem::lookup_type(const std::string& name) { fmt::print("[TypeSystem] The type {} is not defined.\n", name); } - throw std::exception("lookup_type failed"); + throw std::runtime_error("lookup_type failed"); } /*! @@ -254,7 +254,7 @@ MethodInfo TypeSystem::add_method(Type* type, const std::string& method_name, co method_name, type->get_name(), existing_info.type.print(), ts.print()); // unlike type re-definition, method re-definition is almost certain to go wrong. // probably better to give up. - throw std::exception("method redefinition"); + throw std::runtime_error("method redefinition"); } return existing_info; @@ -278,7 +278,7 @@ MethodInfo TypeSystem::add_new_method(Type* type, const TypeSpec& ts) { "[TypeSystem] The new method of {} was originally defined as {}, but has been redefined " "as {}\n", type->get_name(), existing.type.print(), ts.print()); - throw std::exception("add_new_method failed"); + throw std::runtime_error("add_new_method failed"); } return existing; @@ -317,7 +317,7 @@ MethodInfo TypeSystem::lookup_method(const std::string& type_name, const std::st } fmt::print("[TypeSystem] The method {} of type {} could not be found.\n", method_name, type_name); - throw std::exception("lookup_method failed"); + throw std::runtime_error("lookup_method failed"); } /*! @@ -345,7 +345,7 @@ MethodInfo TypeSystem::lookup_new_method(const std::string& type_name) { } fmt::print("[TypeSystem] The new method of type {} could not be found.\n", type_name); - throw std::exception("lookup_new_method failed"); + throw std::runtime_error("lookup_new_method failed"); } /*! @@ -420,7 +420,7 @@ void TypeSystem::assert_field_offset(const std::string& type_name, if (field.offset() != offset) { fmt::print("[TypeSystem] assert_field_offset({}, {}, {}) failed - got {}\n", type_name, field_name, offset); - throw std::exception("assert_field_offset failed"); + throw std::runtime_error("assert_field_offset failed"); } } @@ -436,7 +436,7 @@ int TypeSystem::add_field_to_type(StructureType* type, int offset_override) { if (type->lookup_field(field_name, nullptr)) { fmt::print("[TypeSystem] Type {} already has a field named {}\n", type->get_name(), field_name); - throw std::exception("add_field_to_type duplicate field names"); + throw std::runtime_error("add_field_to_type duplicate field names"); } // first, construct the field @@ -467,7 +467,7 @@ int TypeSystem::add_field_to_type(StructureType* type, "[TypeSystem] Tried to overwrite offset of field to be {}, but it is not aligned " "correctly\n", offset); - throw std::exception("add_field_to_type bad offset_override"); + throw std::runtime_error("add_field_to_type bad offset_override"); } } @@ -649,7 +649,7 @@ Field TypeSystem::lookup_field(const std::string& type_name, const std::string& Field field; if (!type->lookup_field(field_name, &field)) { fmt::print("[TypeSystem] Type {} has no field named {}\n", type_name, field_name); - throw std::exception("lookup_field failed"); + throw std::runtime_error("lookup_field failed"); } return field; } diff --git a/common/type_system/TypeSystem.h b/common/type_system/TypeSystem.h index e290c13f06..d866804db5 100644 --- a/common/type_system/TypeSystem.h +++ b/common/type_system/TypeSystem.h @@ -76,7 +76,7 @@ class TypeSystem { auto x = lookup_type(type_name); T* result = dynamic_cast(x); if (!result) { - throw std::exception("Failed to get the right type"); + throw std::runtime_error("Failed to get the right type"); } return result; } diff --git a/decompiler/ObjectFile/LinkedObjectFile.cpp b/decompiler/ObjectFile/LinkedObjectFile.cpp index 263144d4b1..d02fc3bf31 100644 --- a/decompiler/ObjectFile/LinkedObjectFile.cpp +++ b/decompiler/ObjectFile/LinkedObjectFile.cpp @@ -272,7 +272,7 @@ void LinkedObjectFile::append_word_to_string(std::string& dest, const LinkedWord sprintf(buff, " .sym-off 0x%x %s\n", word.data >> 16, word.symbol_name.c_str()); break; default: - throw std::exception("nyi"); + throw std::runtime_error("nyi"); } dest += buff; diff --git a/decompiler/ObjectFile/LinkedObjectFileCreation.cpp b/decompiler/ObjectFile/LinkedObjectFileCreation.cpp index a4d99849d1..d61b515224 100644 --- a/decompiler/ObjectFile/LinkedObjectFileCreation.cpp +++ b/decompiler/ObjectFile/LinkedObjectFileCreation.cpp @@ -134,7 +134,7 @@ static uint32_t c_symlink2(LinkedObjectFile& f, word_kind = LinkedWord::TYPE_PTR; break; default: - throw std::exception("unhandled SymbolLinkKind"); + throw std::runtime_error("unhandled SymbolLinkKind"); } f.symbol_link_word(seg_id, code_ptr_offset - initial_offset, name, word_kind); @@ -191,7 +191,7 @@ static uint32_t c_symlink3(LinkedObjectFile& f, word_kind = LinkedWord::TYPE_PTR; break; default: - throw std::exception("unhandled SymbolLinkKind"); + throw std::runtime_error("unhandled SymbolLinkKind"); } f.symbol_link_word(seg, code_ptr - initial_offset, name, word_kind); diff --git a/decompiler/util/FileIO.cpp b/decompiler/util/FileIO.cpp index b3f63d16fa..9a7dd7224b 100644 --- a/decompiler/util/FileIO.cpp +++ b/decompiler/util/FileIO.cpp @@ -16,7 +16,7 @@ std::string combine_path(const std::string& parent, const std::string& child) { std::vector read_binary_file(const std::string& filename) { auto fp = fopen(filename.c_str(), "rb"); - if(!fp) throw std::exception("File cannot be opened"); + if(!fp) throw std::runtime_error("File cannot be opened"); fseek(fp, 0, SEEK_END); auto len = ftell(fp); rewind(fp); @@ -25,7 +25,7 @@ std::vector read_binary_file(const std::string& filename) { data.resize(len); if(fread(data.data(), len, 1, fp) != 1) { - throw std::exception("File cannot be read"); + throw std::runtime_error("File cannot be read"); } return data; @@ -75,7 +75,7 @@ void write_text_file(const std::string& file_name, const std::string& text) { FILE* fp = fopen(file_name.c_str(), "w"); if(!fp) { printf("Failed to fopen %s\n", file_name.c_str()); - throw std::exception("Failed to open file"); + throw std::runtime_error("Failed to open file"); } fprintf(fp, "%s\n", text.c_str()); fclose(fp); diff --git a/decompiler/util/LispPrint.cpp b/decompiler/util/LispPrint.cpp index a2a0877950..103fa42f5a 100644 --- a/decompiler/util/LispPrint.cpp +++ b/decompiler/util/LispPrint.cpp @@ -72,7 +72,7 @@ void Form::buildStringSimple(std::string &str) { str.append(*token.str); break; default: - throw std::exception("buildStringSimple unknown token kind"); + throw std::runtime_error("buildStringSimple unknown token kind"); } } } @@ -110,7 +110,7 @@ void Form::toTokenList(std::vector &tokens) { tokens.emplace_back(TokenKind::EMPTY_PAIR); break; default: - throw std::exception("unhandled form type in buildSimpleString"); + throw std::runtime_error("unhandled form type in buildSimpleString"); break; } } diff --git a/decompiler/util/LispPrint.h b/decompiler/util/LispPrint.h index 5a537b3021..28eaf1f5db 100644 --- a/decompiler/util/LispPrint.h +++ b/decompiler/util/LispPrint.h @@ -70,7 +70,7 @@ struct FormToken { s.append(*str); break; default: - throw std::exception("toString unknown token kind"); + throw std::runtime_error("toString unknown token kind"); } return s; } diff --git a/game/kernel/Ptr.h b/game/kernel/Ptr.h index 0f9c7811a8..9764de9fb4 100644 --- a/game/kernel/Ptr.h +++ b/game/kernel/Ptr.h @@ -40,7 +40,7 @@ struct Ptr { if (offset) { return (T*)(g_ee_main_mem + offset); } else { - throw std::exception("Ptr null dereference!"); + throw std::runtime_error("Ptr null dereference!"); } } @@ -51,7 +51,7 @@ struct Ptr { if (offset) { return *(T*)(g_ee_main_mem + offset); } else { - throw std::exception("Ptr null dereference!"); + throw std::runtime_error("Ptr null dereference!"); } } diff --git a/game/kernel/klink.cpp b/game/kernel/klink.cpp index 3326b64ba5..38eba8ee74 100644 --- a/game/kernel/klink.cpp +++ b/game/kernel/klink.cpp @@ -264,7 +264,7 @@ uint32_t cross_seg_dist_link_v3(Ptr link, } else if (size == 8) { *Ptr(offset_of_patch).c() = diff; } else { - throw std::exception("unknown size in cross_seg_dist_link_v3"); + throw std::runtime_error("unknown size in cross_seg_dist_link_v3"); } return 1 + 3 * 4; diff --git a/game/kernel/kprint.cpp b/game/kernel/kprint.cpp index f57f5af5c3..59b086a667 100644 --- a/game/kernel/kprint.cpp +++ b/game/kernel/kprint.cpp @@ -338,10 +338,10 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu value = (char)rounder; } else if (!(ru32 >> 31)) { // sign bit value = 0; - throw std::exception("got very large exponent in rounding calculation"); + throw std::runtime_error("got very large exponent in rounding calculation"); } else { value = -1; // happens on NaN's - // throw std::exception("got negative sign bit in rounding calculation"); + // throw std::runtime_error("got negative sign bit in rounding calculation"); } // place number at the end of the buffer and move pointer back @@ -386,10 +386,10 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu value = (char)next_int; } else if (!(ru32 >> 0x1f)) { value = 0; - throw std::exception("got very large exponent in rounding calculation"); + throw std::runtime_error("got very large exponent in rounding calculation"); } else { value = -1; // happens on NaN's - // throw std::exception("got negative sign bit in rounding calculation"); + // throw std::runtime_error("got negative sign bit in rounding calculation"); } *count_chrp = value + '0'; count_chrp++; @@ -401,7 +401,7 @@ s32 cvt_float(float x, s32 precision, s32* lead_char, char* buff_start, char* bu // however, the rounding flag is always disabled and the rounding code doesn't work. if ((fraction_part != 0.f) && ((flags & 1) != 0)) { start_ptr = round(fraction_part, nullptr, start_ptr, count_chrp - 1, 0, lead_char); - throw std::exception("cvt_float called round!"); + throw std::runtime_error("cvt_float called round!"); } } @@ -553,7 +553,7 @@ char* kitoa(char* buffer, s64 value, u64 base, s32 length, char pad, u32 flag) { * uses C varags, but 128-bit varags don't work, so "format" always passes 0 for quadword printing. */ void kqtoa() { - throw std::exception("kqtoa not implemented"); + throw std::runtime_error("kqtoa not implemented"); } struct format_struct { @@ -791,7 +791,7 @@ s32 format_impl(uint64_t* args) { } kstrinsert(output_ptr, pad, desired_length - print_len); } else { - throw std::exception("unsupported justify in format"); + throw std::runtime_error("unsupported justify in format"); // output_ptr = strend(output_ptr); // while(0 < (desired_length - print_len)) { // char pad = ' '; @@ -842,7 +842,7 @@ s32 format_impl(uint64_t* args) { kstrinsert(output_ptr, pad, desired_length - print_len); } else { - throw std::exception("unsupported justify in format"); + throw std::runtime_error("unsupported justify in format"); // output_ptr = strend(output_ptr); // u32 l140 = 0; // while(l140 < (desired_length - print_len)) { @@ -883,7 +883,7 @@ s32 format_impl(uint64_t* args) { call_method_of_type(in, type, GOAL_PRINT_FUNC); } } else { - throw std::exception("failed to find symbol in format!"); + throw std::runtime_error("failed to find symbol in format!"); } } output_ptr = strend(output_ptr); @@ -904,7 +904,7 @@ s32 format_impl(uint64_t* args) { call_method_of_type(in, type, GOAL_INSPECT_FUNC); } } else { - throw std::exception("failed to find symbol in format!"); + throw std::runtime_error("failed to find symbol in format!"); } } output_ptr = strend(output_ptr); @@ -912,7 +912,7 @@ s32 format_impl(uint64_t* args) { case 'Q': // not yet implemented. hopefully andy gavin finishes this one soon. case 'q': - throw std::exception("nyi q format string"); + throw std::runtime_error("nyi q format string"); break; case 'X': // hex, 64 bit, pad padchar @@ -1009,7 +1009,7 @@ s32 format_impl(uint64_t* args) { precision = 4; float value; if (in < 0) { - throw std::exception("time seconds format error negative.\n"); + throw std::runtime_error("time seconds format error negative.\n"); } else { value = in; } @@ -1025,7 +1025,7 @@ s32 format_impl(uint64_t* args) { default: MsgErr("format: unknown code 0x%02x\n", format_ptr[1]); - throw std::exception("format error"); + throw std::runtime_error("format error"); break; } format_ptr++; @@ -1067,13 +1067,13 @@ s32 format_impl(uint64_t* args) { *PrintPendingLocal3 = 0; return 0; } else if (type == *Ptr>(s7.offset + FIX_SYM_FILE_STREAM_TYPE)) { - throw std::exception("FORMAT into a file stream not supported"); + throw std::runtime_error("FORMAT into a file stream not supported"); } } - throw std::exception("unknown format destination"); + throw std::runtime_error("unknown format destination"); return 0; } - throw std::exception("how did we get here?"); + throw std::runtime_error("how did we get here?"); return 7; } \ No newline at end of file diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index 6e69334ad8..8e21544dac 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -124,7 +124,7 @@ u64 goal_malloc(u32 heap, u32 size, u32 flags, u32 name) { */ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { if (size <= 0) { - throw std::exception("got <= 0 size allocation in alloc_from_heap!"); + throw std::runtime_error("got <= 0 size allocation in alloc_from_heap!"); } // align to 16 bytes (part one) @@ -162,7 +162,7 @@ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { return kmalloc(*Ptr>(heapSymbol), size, KMALLOC_MEMSET, gstr->data()).offset; } else if (heapOffset == FIX_SYM_PROCESS_TYPE) { - throw std::exception("this type of process allocation is not supported yet!\n"); + throw std::runtime_error("this type of process allocation is not supported yet!\n"); // allocate on current process heap // Ptr start = *ptr(getS6() + 0x4c + 8); // Ptr heapEnd = *ptr(getS6() + 0x4c + 4); @@ -178,7 +178,7 @@ u64 alloc_from_heap(u32 heapSymbol, u32 type, s32 size) { // alignedSize); return 0; // } } else if (heapOffset == FIX_SYM_SCRATCH) { - throw std::exception("this type of scratchpad allocation is not used!\n"); + throw std::runtime_error("this type of scratchpad allocation is not used!\n"); } else { memset(Ptr(heapSymbol).c(), 0, (size_t)alignedSize); // treat it as a stack address return heapSymbol; @@ -920,7 +920,7 @@ u64 call_method_of_type(u32 arg, Ptr type, u32 method_id) { (*type_tag).offset); } } - // throw std::exception("call_method_of_type failed!\n"); + // throw std::runtime_error("call_method_of_type failed!\n"); printf("[ERROR] call_method_of_type failed!\n"); printf("type is %s\n", info(type->symbol)->str->data()); return arg; @@ -958,7 +958,7 @@ u64 call_method_of_type_arg2(u32 arg, Ptr type, u32 method_id, u32 a1, u32 (*type_tag).offset); } } - throw std::exception("call_method_of_type failed!\n"); + throw std::runtime_error("call_method_of_type failed!\n"); return arg; } diff --git a/game/runtime.cpp b/game/runtime.cpp index 554f09860a..9644c544c0 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -63,7 +63,7 @@ void deci2_runner(SystemThreadInterface& interfaces) { // server.wait_for_protos_ready(); // // then allow the server to accept connections // if (!server.init()) { -// throw std::exception("DECI2 server init failed"); +// throw std::runtime_error("DECI2 server init failed"); // } // // printf("[DECI2] waiting for listener...\n"); diff --git a/game/sce/iop.cpp b/game/sce/iop.cpp index 002d8b8179..6f954a0183 100644 --- a/game/sce/iop.cpp +++ b/game/sce/iop.cpp @@ -201,12 +201,12 @@ s32 CreateSema(SemaParam* param) { s32 WaitSema(s32 sema) { (void)sema; - throw std::exception("NYI"); + throw std::runtime_error("NYI"); } s32 SignalSema(s32 sema) { (void)sema; - throw std::exception("NYI"); + throw std::runtime_error("NYI"); } s32 WakeupThread(s32 thid) { diff --git a/game/sce/stubs.cpp b/game/sce/stubs.cpp index 7f92ade562..4e218a4739 100644 --- a/game/sce/stubs.cpp +++ b/game/sce/stubs.cpp @@ -6,33 +6,33 @@ namespace ee { s32 sceOpen(const char *filename, s32 flag) { (void)filename; (void)flag; - throw std::exception("sceOpen NYI"); + throw std::runtime_error("sceOpen NYI"); } s32 sceClose(s32 fd) { (void)fd; - throw std::exception("sceClose NYI"); + throw std::runtime_error("sceClose NYI"); } s32 sceRead(s32 fd, void *buf, s32 nbyte) { (void)fd; (void)buf; (void)nbyte; - throw std::exception("sceRead NYI"); + throw std::runtime_error("sceRead NYI"); } s32 sceWrite(s32 fd, const void *buf, s32 nbyte) { (void)fd; (void)buf; (void)nbyte; - throw std::exception("sceWrite NYI"); + throw std::runtime_error("sceWrite NYI"); } s32 sceLseek(s32 fd, s32 offset, s32 where) { (void)fd; (void)offset; (void)where; - throw std::exception("sceLseek NYI"); + throw std::runtime_error("sceLseek NYI"); } int scePadPortOpen(int port, int slot, void* data) { diff --git a/game/system/Deci2Server.cpp b/game/system/Deci2Server.cpp index 21b9e89bba..f6606d7196 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -215,7 +215,7 @@ void Deci2Server::run() { printf("[DECI2] Warning: no handler for this message, ignoring...\n"); unlock(); return; - // throw std::exception("no handler!"); + // throw std::runtime_error("no handler!"); } auto& driver = d2_drivers[handler]; diff --git a/game/system/IOP_Kernel.cpp b/game/system/IOP_Kernel.cpp index 291aaa3381..f7093b5026 100644 --- a/game/system/IOP_Kernel.cpp +++ b/game/system/IOP_Kernel.cpp @@ -7,9 +7,9 @@ * Create a new thread. Will not run the thread. */ s32 IOP_Kernel::CreateThread(std::string name, u32 (*func)()) { - if(_currentThread != -1) throw std::exception("tried to create thread from thread"); + if(_currentThread != -1) throw std::runtime_error("tried to create thread from thread"); u32 ID = (u32)_nextThID++; - if(threads.size() != ID) throw std::exception("thread number error?"); + if(threads.size() != ID) throw std::runtime_error("thread number error?"); // add entry threads.emplace_back(name, func, ID, this); // setup the thread! @@ -47,7 +47,7 @@ void IOP_Kernel::setupThread(s32 id) { threads.at(id).waitForDispatch(); // printf("[IOP Kernel] Thread %s first dispatch!\n", threads.at(id).name.c_str()); if(_currentThread != id) { - throw std::exception("the wrong thread has run!\n"); + throw std::runtime_error("the wrong thread has run!\n"); } (threads.at(id).function)(); printf("Thread %s has returned!\n", threads.at(id).name.c_str()); @@ -59,7 +59,7 @@ void IOP_Kernel::setupThread(s32 id) { * Run a thread (call from kernel) */ void IOP_Kernel::runThread(s32 id) { - if(_currentThread != -1) throw std::exception("tried to runThread in a thread"); + if(_currentThread != -1) throw std::runtime_error("tried to runThread in a thread"); _currentThread = id; threads.at(id).dispatch(); threads.at(id).waitForReturnToKernel(); @@ -76,7 +76,7 @@ void IOP_Kernel::SuspendThread() { threads.at(oldThread).returnToKernel(); threads.at(oldThread).waitForDispatch(); if(_currentThread != oldThread) { - throw std::exception("bad resume"); + throw std::runtime_error("bad resume"); } } @@ -128,7 +128,7 @@ void IOP_Kernel::dispatchAll() { */ void IopThreadRecord::returnToKernel() { runThreadReady = false; - if(kernel->getCurrentThread() != thID) throw std::exception("tried to sleep the wrong thread!"); + if(kernel->getCurrentThread() != thID) throw std::runtime_error("tried to sleep the wrong thread!"); { std::lock_guard lck(*threadToKernelMutex); @@ -142,7 +142,7 @@ void IopThreadRecord::returnToKernel() { */ void IopThreadRecord::dispatch() { syscallReady = false; - if(kernel->getCurrentThread() != thID) throw std::exception("tried to dispatch the wrong thread!"); + if(kernel->getCurrentThread() != thID) throw std::runtime_error("tried to dispatch the wrong thread!"); { std::lock_guard lck(*kernelToThreadMutex); runThreadReady = true; @@ -163,7 +163,7 @@ void IopThreadRecord::waitForReturnToKernel() { * Thread waits for kernel to dispatch it. */ void IopThreadRecord::waitForDispatch() { - //if(kernel->getCurrentThread() == -1) throw std::exception("tried to suspend main!\n"); + //if(kernel->getCurrentThread() == -1) throw std::runtime_error("tried to suspend main!\n"); std::unique_lock lck(*kernelToThreadMutex); kernelToThreadCV->wait(lck, [this]{return runThreadReady;}); //runThreadReady = false; diff --git a/game/system/IOP_Kernel.h b/game/system/IOP_Kernel.h index c811770be5..d05083dbc8 100644 --- a/game/system/IOP_Kernel.h +++ b/game/system/IOP_Kernel.h @@ -98,7 +98,7 @@ public: * Resume the kernel. */ void returnToKernel() { - if(_currentThread < 0) throw std::exception("tried to return to kernel not in a thread"); + if(_currentThread < 0) throw std::runtime_error("tried to return to kernel not in a thread"); threads[_currentThread].returnToKernel(); } @@ -129,7 +129,7 @@ public: return -0x1a9; } // printf("poll %d %ld\n", mbx, mbxs.size()); - if(mbx >= (s32) mbxs.size()) throw std::exception("invalid PollMbx"); + if(mbx >= (s32) mbxs.size()) throw std::runtime_error("invalid PollMbx"); s32 gotSomething = mbxs[mbx].empty() ? 0 : 1; if(gotSomething) { void* thing = mbxs[mbx].front(); @@ -146,7 +146,7 @@ public: * Push something into a mbx */ s32 SendMbx(s32 mbx, void* value) { - if(mbx >= (s32) mbxs.size()) throw std::exception("invalid SendMbx"); + if(mbx >= (s32) mbxs.size()) throw std::runtime_error("invalid SendMbx"); mbxs[mbx].push(value); // printf("push into messagebox %d %p\n", mbx, value); // printf("mbx size %ld\n", mbxs.size()); diff --git a/game/system/SystemThread.cpp b/game/system/SystemThread.cpp index 1860f59507..f938b32ccd 100644 --- a/game/system/SystemThread.cpp +++ b/game/system/SystemThread.cpp @@ -13,7 +13,7 @@ */ SystemThread& SystemThreadManager::create_thread(const std::string& name) { if (thread_count >= MAX_SYSTEM_THREADS) { - throw std::exception("Out of System Threads! Please increase MAX_SYSTEM_THREADS"); + throw std::runtime_error("Out of System Threads! Please increase MAX_SYSTEM_THREADS"); } auto& thread = threads[thread_count]; diff --git a/goalc/goos/Interpreter.cpp b/goalc/goos/Interpreter.cpp index 64bb0ffc57..f0d03f4d81 100644 --- a/goalc/goos/Interpreter.cpp +++ b/goalc/goos/Interpreter.cpp @@ -126,7 +126,7 @@ void Interpreter::execute_repl() { Object evald = eval_with_rewind(obj, global_environment.as_env()); // print printf("%s\n", evald.print().c_str()); - } catch (std::exception& e) { + } catch (std::runtime_error& e) { printf("REPL Error: %s\n", e.what()); } } @@ -137,7 +137,7 @@ void Interpreter::execute_repl() { * for debugging. */ void Interpreter::throw_eval_error(const Object& o, const std::string& err) { - // throw std::exception("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + + // throw std::runtime_error("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + // reader.db.get_info_for(o)); } @@ -151,7 +151,7 @@ Object Interpreter::eval_with_rewind(const Object& obj, Object result = EmptyListObject::make_new(); try { result = eval(obj, env); - } catch (std::exception& e) { + } catch (std::runtime_error& e) { if (!disable_printing) { printf("-----------------------------------------\n"); printf("From object %s\nat %s\n", obj.inspect().c_str(), reader.db.get_info_for(obj).c_str()); diff --git a/goalc/goos/InterpreterEval.cpp b/goalc/goos/InterpreterEval.cpp index 183566402c..8f73c46052 100644 --- a/goalc/goos/InterpreterEval.cpp +++ b/goalc/goos/InterpreterEval.cpp @@ -49,7 +49,7 @@ Object Interpreter::eval_read(const Object& form, try { return reader.read_from_string(args.unnamed.at(0).as_string()->data); - } catch (std::exception& e) { + } catch (std::runtime_error& e) { throw_eval_error(form, std::string("reader error inside of read:\n") + e.what()); } @@ -67,7 +67,7 @@ Object Interpreter::eval_read_file(const Object& form, try { return reader.read_from_file(args.unnamed.at(0).as_string()->data); - } catch (std::exception& e) { + } catch (std::runtime_error& e) { throw_eval_error(form, std::string("reader error inside of read-file:\n") + e.what()); } return EmptyListObject::make_new(); @@ -85,13 +85,13 @@ Object Interpreter::eval_load_file(const Object& form, Object o; try { o = reader.read_from_file(args.unnamed.at(0).as_string()->data); - } catch (std::exception& e) { + } catch (std::runtime_error& e) { throw_eval_error(form, std::string("reader error inside of load-file:\n") + e.what()); } try { return eval_with_rewind(o, global_environment.as_env()); - } catch (std::exception& e) { + } catch (std::runtime_error& e) { throw_eval_error(form, std::string("eval error inside of load-file:\n") + e.what()); } return EmptyListObject::make_new(); diff --git a/goalc/goos/Object.cpp b/goalc/goos/Object.cpp index 0b5792a039..f2f0dfd623 100644 --- a/goalc/goos/Object.cpp +++ b/goalc/goos/Object.cpp @@ -33,7 +33,7 @@ std::string object_type_to_string(ObjectType type) { case ObjectType::ENVIRONMENT: return "[environment]"; default: - throw std::exception("unknown object type in object_type_to_string"); + throw std::runtime_error("unknown object type in object_type_to_string"); } } @@ -151,7 +151,7 @@ bool Object::operator==(const Object& other) const { } default: - throw std::exception("equality not implemented for"); + throw std::runtime_error("equality not implemented for"); } } diff --git a/goalc/goos/Object.h b/goalc/goos/Object.h index bf45ba384d..9f6ba23e31 100644 --- a/goalc/goos/Object.h +++ b/goalc/goos/Object.h @@ -222,7 +222,7 @@ class Object { std::shared_ptr as_pair() const { if (type != ObjectType::PAIR) { - // throw std::exception("as_pair called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + // print()); } return std::dynamic_pointer_cast(heap_obj); @@ -230,14 +230,14 @@ class Object { std::shared_ptr as_env() const { if (type != ObjectType::ENVIRONMENT) { - // throw std::exception("as_env called on a " + object_type_to_string(type) + " " + print()); + // throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_symbol() const { if (type != ObjectType::SYMBOL) { - // throw std::exception("as_symbol called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " + // print()); } return std::dynamic_pointer_cast(heap_obj); @@ -245,7 +245,7 @@ class Object { std::shared_ptr as_string() const { if (type != ObjectType::STRING) { - // throw std::exception("as_string called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " + // print()); } return std::dynamic_pointer_cast(heap_obj); @@ -253,7 +253,7 @@ class Object { std::shared_ptr as_lambda() const { if (type != ObjectType::LAMBDA) { - // throw std::exception("as_lambda called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_lambda called on a " + object_type_to_string(type) + " " + // print()); } return std::dynamic_pointer_cast(heap_obj); @@ -261,7 +261,7 @@ class Object { std::shared_ptr as_macro() const { if (type != ObjectType::MACRO) { - // throw std::exception("as_macro called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_macro called on a " + object_type_to_string(type) + " " + // print()); } return std::dynamic_pointer_cast(heap_obj); @@ -269,7 +269,7 @@ class Object { std::shared_ptr as_array() const { if (type != ObjectType::ARRAY) { - // throw std::exception("as_array called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + // print()); } return std::dynamic_pointer_cast(heap_obj); @@ -277,14 +277,14 @@ class Object { IntType& as_int() { if (type != ObjectType::INTEGER) { - // throw std::exception("as_int called on a " + object_type_to_string(type) + " " + print()); + // throw std::runtime_error("as_int called on a " + object_type_to_string(type) + " " + print()); } return integer_obj.value; } FloatType& as_float() { if (type != ObjectType::FLOAT) { - // throw std::exception("as_float called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " + // print()); } return float_obj.value; @@ -292,7 +292,7 @@ class Object { char& as_char() { if (type != ObjectType::CHAR) { - // throw std::exception("as_char called on a " + object_type_to_string(type) + " " + + // throw std::runtime_error("as_char called on a " + object_type_to_string(type) + " " + // print()); } return char_obj.value; diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index a66bafb5ca..b329d8a350 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -102,7 +102,7 @@ Reader::Reader() { // find the source directory auto result = std::getenv("NEXT_DIR"); if (!result) { - throw std::exception( + throw std::runtime_error( "Environment variable NEXT_DIR is not set. Please set this to point to next/"); } @@ -278,7 +278,7 @@ bool Reader::read_object(Token& tok, TextStream& ts, Object& obj) { if (try_token_as_symbol(tok, obj)) { return true; } - } catch (std::exception& e) { + } catch (std::runtime_error& e) { throw_reader_error(ts, "parsing token " + tok.text + " failed: " + e.what(), -1); } @@ -564,7 +564,7 @@ bool Reader::try_token_as_float(const Token& tok, Object& obj) { return false; obj = Object::make_float(v); return true; - } catch (std::exception& e) { + } catch (std::runtime_error& e) { return false; } } @@ -627,8 +627,8 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { return false; obj = Object::make_integer(v); return true; - } catch (std::exception& e) { - throw std::exception("The number cannot be a hexadecimal constant"); + } catch (std::runtime_error& e) { + throw std::runtime_error("The number cannot be a hexadecimal constant"); } } return false; @@ -661,8 +661,8 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { return false; obj = Object::make_integer(v); return true; - } catch (std::exception& e) { - throw std::exception("The number cannot be an integer constant"); + } catch (std::runtime_error& e) { + throw std::runtime_error("The number cannot be an integer constant"); } } return false; @@ -697,7 +697,7 @@ bool Reader::try_token_as_char(const Token& tok, Object& obj) { * Used for reader errors, like "missing close paren" or similar. */ void Reader::throw_reader_error(TextStream& here, const std::string& err, int seek_offset) { - throw std::exception("Reader error at"); + throw std::runtime_error("Reader error at"); } /*! diff --git a/goalc/listener/Deci2Server.cpp b/goalc/listener/Deci2Server.cpp index 154cdf7638..be9732b917 100644 --- a/goalc/listener/Deci2Server.cpp +++ b/goalc/listener/Deci2Server.cpp @@ -218,7 +218,7 @@ void Deci2Server::run() { printf("[DECI2] Warning: no handler for this message, ignoring...\n"); unlock(); return; - // throw std::exception("no handler!"); + // throw std::runtime_error("no handler!"); } auto& driver = d2_drivers[handler]; diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 8ab1c4563a..143f95e082 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -43,7 +43,7 @@ bool Listener::is_connected() const { /* bool Listener::connect_to_target(const std::string& ip, int port) { if (m_connected) { - throw std::exception("attempted a Listener::connect_to_target when already connected!"); + throw std::runtime_error("attempted a Listener::connect_to_target when already connected!"); } if (socket_fd >= 0) { diff --git a/goalc/util/file_io.cpp b/goalc/util/file_io.cpp index 44b93035c5..b659ed7bca 100644 --- a/goalc/util/file_io.cpp +++ b/goalc/util/file_io.cpp @@ -7,7 +7,7 @@ namespace util { std::string read_text_file(const std::string& path) { std::ifstream file(path); if (!file.good()) { - throw std::exception("couldn't open "); + throw std::runtime_error("couldn't open "); } std::stringstream ss; ss << file.rdbuf(); diff --git a/third-party/fmt/format-inl.h b/third-party/fmt/format-inl.h index db590a275e..c379681be2 100644 --- a/third-party/fmt/format-inl.h +++ b/third-party/fmt/format-inl.h @@ -226,8 +226,8 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str, error_code_ = err_code; memory_buffer buffer; format_system_error(buffer, err_code, vformat(format_str, args)); - std::exception& base = *this; -// base = std::exception(to_string(buffer)); + std::runtime_error& base = *this; +// base = std::runtime_error(to_string(buffer)); } namespace detail { @@ -1175,7 +1175,7 @@ int snprintf_float(T value, int precision, float_specs specs, auto capacity = buf.capacity() - offset; #ifdef FMT_FUZZ if (precision > 100000) - throw std::exception( + throw std::runtime_error( "fuzz mode - avoid large allocation inside snprintf"); #endif // Suppress the warning about a nonliteral format string. @@ -1327,7 +1327,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { auto cp = uint32_t(); auto error = 0; p = utf8_decode(p, &cp, &error); - if (error != 0) FMT_THROW(std::exception("invalid utf8")); + if (error != 0) FMT_THROW(std::runtime_error("invalid utf8")); if (cp <= 0xFFFF) { buffer_.push_back(static_cast(cp)); } else { diff --git a/third-party/fmt/format.cc b/third-party/fmt/format.cc index 42ea06ed74..a64a1f3893 100644 --- a/third-party/fmt/format.cc +++ b/third-party/fmt/format.cc @@ -15,7 +15,7 @@ int format_float(char* buf, std::size_t size, const char* format, int precision, T value) { #ifdef FMT_FUZZ if (precision > 100000) - throw std::exception( + throw std::runtime_error( "fuzz mode - avoid large allocation inside snprintf"); #endif // Suppress the warning about nonliteral format string. diff --git a/third-party/fmt/format.h b/third-party/fmt/format.h index b312bb4bee..a778ce376d 100644 --- a/third-party/fmt/format.h +++ b/third-party/fmt/format.h @@ -683,7 +683,7 @@ class basic_memory_buffer : public detail::buffer { template void basic_memory_buffer::grow(size_t size) { #ifdef FMT_FUZZ - if (size > 5000) throw std::exception("fuzz mode - won't grow that much"); + if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much"); #endif size_t old_capacity = this->capacity(); size_t new_capacity = old_capacity + old_capacity / 2; @@ -710,11 +710,11 @@ struct is_contiguous> : std::true_type { /** A formatting error such as invalid format string. */ FMT_CLASS_API -class FMT_API format_error : public std::exception { +class FMT_API format_error : public std::runtime_error { public: - explicit format_error(const char* message) : std::exception(message) {} + explicit format_error(const char* message) : std::runtime_error(message) {} explicit format_error(const std::string& message); - // : std::exception(message) {} + // : std::runtime_error(message) {} format_error(const format_error&) = default; format_error& operator=(const format_error&) = default; format_error(format_error&&) = default; @@ -1145,7 +1145,7 @@ template class float_writer { } #ifdef FMT_FUZZ if (num_zeros > 5000) - throw std::exception("fuzz mode - avoiding excessive cpu use"); + throw std::runtime_error("fuzz mode - avoiding excessive cpu use"); #endif it = std::fill_n(it, num_zeros, static_cast('0')); } @@ -2952,14 +2952,14 @@ using arg_formatter FMT_DEPRECATED_ALIAS = for example a file opening error. */ FMT_CLASS_API -class FMT_API system_error : public std::exception { +class FMT_API system_error : public std::runtime_error { private: void init(int err_code, string_view format_str, format_args args); protected: int error_code_; - system_error() : std::exception(""), error_code_(0) {} + system_error() : std::runtime_error(""), error_code_(0) {} public: /** @@ -2982,7 +2982,7 @@ class FMT_API system_error : public std::exception { */ template system_error(int error_code, string_view message, const Args&... args) - : std::exception("") { + : std::runtime_error("") { init(error_code, message, make_format_args(args...)); } system_error(const system_error&) = default; diff --git a/third-party/json.hpp b/third-party/json.hpp index 54e5f75365..740e9f12a7 100644 --- a/third-party/json.hpp +++ b/third-party/json.hpp @@ -2324,7 +2324,7 @@ namespace detail /*! @brief general exception of the @ref basic_json class -This class is an extension of `std::exception` objects with a member @a id for +This class is an extension of `std::runtime_error` objects with a member @a id for exception ids. It is used as the base class for all exceptions thrown by the @ref basic_json class. This class can hence be used as "wildcard" to catch exceptions. @@ -2339,7 +2339,7 @@ Subclasses: @internal @note To have nothrow-copy-constructible exceptions, we internally use - `std::exception` which can cope with arbitrary-length error messages. + `std::runtime_error` which can cope with arbitrary-length error messages. Intermediate strings are built with static functions and then passed to the actual constructor. @endinternal @@ -2349,7 +2349,7 @@ caught.,exception} @since version 3.0.0 */ -class exception : public std::exception +class exception : public std::runtime_error { public: /// returns the explanatory string @@ -2373,7 +2373,7 @@ class exception : public std::exception private: /// an exception object as storage for error messages - std::exception m; + std::runtime_error m; }; /*! From 2138beb1508aae7c57853f020960825adc567663 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Fri, 28 Aug 2020 11:59:20 -0600 Subject: [PATCH 14/32] Windows threading fixes Further cripple Deci2Listener pending Windows implementation, finish converting POSIX threads to std::thread. Hardcoded pathing in overlord\fake_iso.cpp until environment variables can be implemented for Windows. Currently loads KERNEL.CGO and links gcommon object file, but crashes when executing due to Windows/Linux differences. --- game/kernel/kmachine.cpp | 2 +- game/overlord/fake_iso.cpp | 15 ++++++++++----- game/runtime.cpp | 12 ++++++++++-- game/system/IOP_Kernel.cpp | 2 +- game/system/SystemThread.cpp | 2 +- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/game/kernel/kmachine.cpp b/game/kernel/kmachine.cpp index 91d6194fbb..c72ef5e66c 100644 --- a/game/kernel/kmachine.cpp +++ b/game/kernel/kmachine.cpp @@ -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 diff --git a/game/overlord/fake_iso.cpp b/game/overlord/fake_iso.cpp index 0f44fca108..8de67e0b7d 100644 --- a/game/overlord/fake_iso.cpp +++ b/game/overlord/fake_iso.cpp @@ -79,14 +79,20 @@ static const char* next_dir = nullptr; */ int FS_Init(u8* buffer) { (void)buffer; - // get path to next/. Will be set in the gk.sh launch script. - next_dir = std::getenv("NEXT_DIR"); // todo windows? + // get path to next/. Will be set in the gk.sh launch script. This is for Linux only + + /* + next_dir = std::getenv("NEXT_DIR"); // todo windows? + assert(next_dir); // get path to next/data/fake_iso.txt, the map file. char fakeiso_path[512]; strcpy(fakeiso_path, next_dir); strcat(fakeiso_path, "/game/fake_iso.txt"); // todo windows paths? + */ + char fakeiso_path[] = "C:\\Users\\Shalen\\Documents\\GitHub\\jak-project-windows-proj\\game\\fake_iso.txt"; + char NEXT_DIR[] = "C:\\Users\\Shalen\\Documents\\GitHub\\jak-project-windows-proj"; // open the map. FILE* fp = fopen(fakeiso_path, "r"); @@ -96,7 +102,7 @@ int FS_Init(u8* buffer) { rewind(fp); char* fakeiso = (char*)malloc(len); if (fread(fakeiso, len, 1, fp) != 1) { - assert(false); + assert(true); } // loop over lines @@ -190,8 +196,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, next_dir); - strcat(path_buffer, "/"); + strcpy(path_buffer, "C:\\Users\\Shalen\\Documents\\GitHub\\jak-project\\"); strcat(path_buffer, fake_iso_entries[fr->location].file_path); return path_buffer; } diff --git a/game/runtime.cpp b/game/runtime.cpp index 9644c544c0..fd0557600e 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -39,6 +39,10 @@ u8* g_ee_main_mem = nullptr; +/*! +* runtime.cpp - Deci2Listener has been disabled for now, pending rewriting for Windows. +*/ + namespace { /*! @@ -48,7 +52,11 @@ namespace { void deci2_runner(SystemThreadInterface& interfaces) { -// // callback function so the server knows when to give up and shutdown + interfaces.initialization_complete(); + while (true) { + } + + // // callback function so the server knows when to give up and shutdown // std::function shutdown_callback = [&]() { return interfaces.get_want_exit(); }; // // // create and register server @@ -237,7 +245,7 @@ void exec_runtime(int argc, char** argv) { // step 3: start the EE! iop_thread.start(iop_runner); ee_thread.start(ee_runner); - //deci_thread.start(deci2_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(); diff --git a/game/system/IOP_Kernel.cpp b/game/system/IOP_Kernel.cpp index f7093b5026..ffa2a9cbad 100644 --- a/game/system/IOP_Kernel.cpp +++ b/game/system/IOP_Kernel.cpp @@ -19,7 +19,7 @@ s32 IOP_Kernel::CreateThread(std::string name, u32 (*func)()) { if(func) { _currentThread = ID; // create OS thread, will run the setupThread function - //threads.back().thread = new std::thread(&IOP_Kernel::setupThread, this, ID); --- quick hack to make the build + threads.back().thread = new std::thread(&IOP_Kernel::setupThread, this, ID); // wait for thread to finish setup. threads.back().waitForReturnToKernel(); // ensure we are back in the kernel. diff --git a/game/system/SystemThread.cpp b/game/system/SystemThread.cpp index f938b32ccd..a601902bde 100644 --- a/game/system/SystemThread.cpp +++ b/game/system/SystemThread.cpp @@ -83,7 +83,7 @@ void* bootstrap_thread_func(void* x) { void SystemThread::start(std::function f) { printf("# Initialize %s...\n", name.c_str()); function = f; - std::thread(thread); + thread = std::thread(bootstrap_thread_func, this); running = true; // and wait for initialization From c5bb7aab54ef679e16d111fa6826510098fadea9 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Fri, 28 Aug 2020 20:26:27 -0400 Subject: [PATCH 15/32] nasm fixes #1 --- common/type_system/TypeSystem.cpp | 1 + game/CMakeLists.txt | 6 +- game/kernel/{asm_funcs.nasm => asm_funcs.asm} | 60 ++++++++++++------- 3 files changed, 43 insertions(+), 24 deletions(-) rename game/kernel/{asm_funcs.nasm => asm_funcs.asm} (71%) diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index 76e4005c59..7922eb90d1 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -3,6 +3,7 @@ #include "TypeSystem.h" #include "type_util.h" #include +#include TypeSystem::TypeSystem() { // the "none" type is included by default. diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index f35f7dc47d..8b0f502456 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -22,6 +22,10 @@ if(CMAKE_COMPILER_IS_GNUCXX) 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 " -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o ") +set_source_files_properties(kernel/asm_funcs.asm PROPERTIES COMPILE_FLAGS "-g") set(RUNTIME_SOURCE main.cpp runtime.cpp @@ -35,7 +39,7 @@ set(RUNTIME_SOURCE sce/sif_ee.cpp sce/iop.cpp sce/stubs.cpp - kernel/asm_funcs.nasm + kernel/asm_funcs.asm kernel/fileio.cpp kernel/kboot.cpp kernel/kdgo.cpp diff --git a/game/kernel/asm_funcs.nasm b/game/kernel/asm_funcs.asm similarity index 71% rename from game/kernel/asm_funcs.nasm rename to game/kernel/asm_funcs.asm index d449265338..0e506f23f0 100644 --- a/game/kernel/asm_funcs.nasm +++ b/game/kernel/asm_funcs.asm @@ -32,10 +32,12 @@ _format: push rdi ; set the first argument register to the stack argument array - mov rdi, rsp + mov rcx, rsp + sub rsp, 32 ; call C function to do format, result will go in RAX call format_impl + add rsp, 32 ; restore ; (note - this could probably just be add rsp 72, we don't care about the value of these register) @@ -70,29 +72,41 @@ _format: global _call_goal_asm _call_goal_asm: - ;; x86 saved registers we need to modify for GOAL should be saved - push r13 - push r14 - push r15 - - ;; RDI - first arg - ;; RSI - second arg - ;; RDX - third arg - ;; RCX - function pointer (goes in r13) - ;; R8 - st (goes in r14) - ;; R9 - off (goes in r15) - - ;; set GOAL function pointer - mov r13, rcx - ;; offset - mov r15, r8 - ;; symbol table - mov r14, r9 - ;; call GOAL by function pointer + push rdx ; 8 + push rbx ; 16 + push rbp ; 24 + push rsi ; 32 + push rdi ; 40 + push r8 ; 48 + push r9 ; 56 + push r10 ; 64 + push r11 ; 72 + push r12 ; 80 + push r13 ; 88 + push r14 ; 96 + push r15 ; 104 + + mov rdi, rcx ;; rdi is GOAL first argument, rcx is windows first argument + mov rsi, rdx ;; rsi is GOAL second argument, rdx is windows second argument + mov rdx, r8 ;; rdx is GOAL third argument, r8 is windows third argument + mov r13, r9 ;; r13 is GOAL fp, r9 is windows fourth argument + mov r14, [rsp + 144] ;; symbol table + mov r15, [rsp + 152] ;; offset + call r13 - - ;; retore x86 registers. + pop r15 pop r14 pop r13 - ret \ No newline at end of file + pop r12 + pop r11 + pop r10 + pop r9 + pop r8 + pop rdi + pop rsi + pop rbp + pop rbx + pop rdx + + ret From 324d2121b108f276fb6c27dbc884c186cd1cad06 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Fri, 28 Aug 2020 21:01:59 -0400 Subject: [PATCH 16/32] push --- game/kernel/asm_funcs.asm | 6 +++--- game/kernel/kscheme.cpp | 37 ++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/game/kernel/asm_funcs.asm b/game/kernel/asm_funcs.asm index 0e506f23f0..e3e39a6034 100644 --- a/game/kernel/asm_funcs.asm +++ b/game/kernel/asm_funcs.asm @@ -90,8 +90,8 @@ _call_goal_asm: mov rsi, rdx ;; rsi is GOAL second argument, rdx is windows second argument mov rdx, r8 ;; rdx is GOAL third argument, r8 is windows third argument mov r13, r9 ;; r13 is GOAL fp, r9 is windows fourth argument - mov r14, [rsp + 144] ;; symbol table - mov r15, [rsp + 152] ;; offset + mov r15, [rsp + 144] ;; symbol table + mov r14, [rsp + 152] ;; offset call r13 @@ -109,4 +109,4 @@ _call_goal_asm: pop rbx pop rdx - ret + ret \ No newline at end of file diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index 8e21544dac..d5f569dc8d 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -317,24 +317,47 @@ 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 make_function_from_c(void* func) { // allocate a function object on the global heap auto mem = Ptr( - alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, *(s7 + FIX_SYM_FUNCTION_TYPE), 0x40)); + alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, *(s7 + FIX_SYM_FUNCTION_TYPE), 0x80)); auto f = (uint64_t)func; auto fp = (u8*)&f; + int i = 0; // we will put the function address in RAX with a movabs rax, imm8 - mem.c()[0] = 0x48; - mem.c()[1] = 0xb8; - for (int i = 0; i < 8; i++) { - mem.c()[2 + i] = fp[i]; + mem.c()[i++] = 0x48; + mem.c()[i++] = 0xb8; + for (int j = 0; j < 8; j++) { + mem.c()[i++] = fp[j]; + } + + /* + * push rdi + * push rsi + * push rdx + * push rcx + * pop r9 + * pop r8 + * pop rdx + * pop rcx + * + * sub rsp, 40 + * call rax + * add rsp, 40 + * ret + */ + for (auto x : {0x57, 0x56, 0x52, 0x51, 0x41, 0x59, 0x41, 0x58, 0x5A, 0x59, 0x48, + 0x83, 0xEC, 0x28, 0xFF, 0xD0, 0x48, 0x83, 0xC4, 0x28, 0xC3}) { + mem.c()[i++] = x; } // jmp rax - mem.c()[10] = 0xff; - mem.c()[11] = 0xe0; + // mem.c()[10] = 0xff; + // mem.c()[11] = 0xe0; // the C function's ret will return to the caller of this trampoline. From d38ec3f44c5da2bd4119d57cac5e7551d1018f8f Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 29 Aug 2020 00:01:55 -0400 Subject: [PATCH 17/32] Add some premade launch configs, and fix google test --- .editorconfig | 5 +++++ .gitignore | 3 +-- .vs/.gitignore | 3 +++ .vs/launch.vs.json | 34 ++++++++++++++++++++++++++++++++++ CMakeSettings.json | 34 ++++++++++++++++++++-------------- test/CMakeLists.txt | 6 +++++- 6 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 .editorconfig create mode 100644 .vs/.gitignore create mode 100644 .vs/launch.vs.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000000..79b8023985 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +# Rules in this file were initially inferred by Visual Studio IntelliCode from the C:\Users\xtvas\Repositories\jak-project codebase based on best match to current usage at 2020-08-28 +# You can modify the rules from these initially generated values to suit your own policies +# You can learn more about editorconfig here: https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference +[*.cs] + diff --git a/.gitignore b/.gitignore index d722b67441..e542be2281 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ # for clion cmake-build-debug/* .idea/* -build/* -/.vs \ No newline at end of file +build/* \ No newline at end of file diff --git a/.vs/.gitignore b/.vs/.gitignore new file mode 100644 index 0000000000..fdc7c3f305 --- /dev/null +++ b/.vs/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!launch.vs.json diff --git a/.vs/launch.vs.json b/.vs/launch.vs.json new file mode 100644 index 0000000000..ae65ad6e91 --- /dev/null +++ b/.vs/launch.vs.json @@ -0,0 +1,34 @@ +{ + // https://docs.microsoft.com/en-us/cpp/build/launch-vs-schema-reference-cpp?view=vs-2019 + "version": "0.2.1", + "defaults": {}, + "configurations": [ + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "goalc-test.exe (bin\\goalc-test.exe)", + "name": "Run Tests - Summary", + "args": [ + "--gtest_brief=1" + ] + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "gk.exe (bin\\gk.exe)", + "name": "Run Game" + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "goalc.exe (bin\\goalc.exe)", + "name": "Build Compiler" + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "decompiler.exe (bin\\decompiler.exe)", + "name": "Build Decompiler" + } + ] +} \ No newline at end of file diff --git a/CMakeSettings.json b/CMakeSettings.json index 08c8f8af93..298f497edd 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,16 +1,22 @@ { - // See https://go.microsoft.com/fwlink/?linkid=834763 for more information about this file. - "configurations": [ - { - "name": "x64-Debug", - "generator": "Ninja", - "configurationType": "Debug", - "inheritEnvironments": [ "msvc_x64_x64" ], - "buildRoot": "${projectDir}\\out\\build\\${name}", - "installRoot": "${projectDir}\\out\\install\\${name}", - "cmakeCommandArgs": "", - "buildCommandArgs": "", - "ctestCommandArgs": "" - } - ] + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "variables": [ + { + "name": "INSTALL_GTEST", + "value": "True", + "type": "BOOL" + } + ] + } + ] } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ccb48ee674..feb0976de2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,3 +1,5 @@ +enable_testing() + add_executable(goalc-test test_main.cpp test_test.cpp @@ -9,10 +11,12 @@ add_executable(goalc-test all_jak1_symbols.cpp test_type_system.cpp) + IF (WIN32) + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # TODO - implement windows listener message("Windows Listener Not Implemented!") - target_link_libraries(goalc-test goos util runtime emitter type_system gtest) + target_link_libraries(goalc-test mman goos util runtime emitter type_system gtest) ELSE() target_link_libraries(goalc-test goos util listener runtime emitter type_system gtest) ENDIF() From 14c1b8be7413d85b82292617f5ffe9fe9edf7e2e Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 29 Aug 2020 14:52:45 -0400 Subject: [PATCH 18/32] working my way through the tests --- .vs/launch.vs.json | 77 +++--- goalc/goos/Interpreter.cpp | 8 +- goalc/goos/Object.h | 36 +-- goalc/goos/Reader.cpp | 8 +- test/CMakeLists.txt | 17 +- test/test_kernel.cpp | 5 +- test/test_reader.cpp | 547 +++++++++++++++++++------------------ 7 files changed, 356 insertions(+), 342 deletions(-) diff --git a/.vs/launch.vs.json b/.vs/launch.vs.json index ae65ad6e91..7201456d92 100644 --- a/.vs/launch.vs.json +++ b/.vs/launch.vs.json @@ -1,34 +1,45 @@ { - // https://docs.microsoft.com/en-us/cpp/build/launch-vs-schema-reference-cpp?view=vs-2019 - "version": "0.2.1", - "defaults": {}, - "configurations": [ - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "goalc-test.exe (bin\\goalc-test.exe)", - "name": "Run Tests - Summary", - "args": [ - "--gtest_brief=1" - ] - }, - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "gk.exe (bin\\gk.exe)", - "name": "Run Game" - }, - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "goalc.exe (bin\\goalc.exe)", - "name": "Build Compiler" - }, - { - "type": "default", - "project": "CMakeLists.txt", - "projectTarget": "decompiler.exe (bin\\decompiler.exe)", - "name": "Build Decompiler" - } - ] -} \ No newline at end of file + // https://docs.microsoft.com/en-us/cpp/build/launch-vs-schema-reference-cpp?view=vs-2019 + "version": "0.2.1", + "defaults": {}, + "configurations": [ + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "goalc-test.exe (bin\\goalc-test.exe)", + "name": "Run Tests - Summary", + "args": ["--gtest_brief=1"], + "env": { + "NEXT_DIR": "${projectDir}" + } + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "goalc-test.exe (bin\\goalc-test.exe)", + "name": "Run Tests - Verbose", + "args": ["--gtest_brief=0"], + "env": { + "NEXT_DIR": "${projectDir}" + } + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "gk.exe (bin\\gk.exe)", + "name": "Run Game" + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "goalc.exe (bin\\goalc.exe)", + "name": "Build Compiler" + }, + { + "type": "default", + "project": "CMakeLists.txt", + "projectTarget": "decompiler.exe (bin\\decompiler.exe)", + "name": "Build Decompiler" + } + ] +} diff --git a/goalc/goos/Interpreter.cpp b/goalc/goos/Interpreter.cpp index f0d03f4d81..e98f0df660 100644 --- a/goalc/goos/Interpreter.cpp +++ b/goalc/goos/Interpreter.cpp @@ -97,7 +97,7 @@ void Interpreter::disable_printfs() { */ void Interpreter::load_goos_library() { auto cmd = "(load-file \"goalc/gs/goos-lib.gs\")"; - eval_with_rewind(reader.read_from_string(cmd), global_environment.as_env()); + eval_with_rewind(reader.read_from_string(cmd), global_environment.as_env()); } /*! @@ -126,7 +126,7 @@ void Interpreter::execute_repl() { Object evald = eval_with_rewind(obj, global_environment.as_env()); // print printf("%s\n", evald.print().c_str()); - } catch (std::runtime_error& e) { + } catch (std::exception& e) { printf("REPL Error: %s\n", e.what()); } } @@ -137,8 +137,8 @@ void Interpreter::execute_repl() { * for debugging. */ void Interpreter::throw_eval_error(const Object& o, const std::string& err) { - // throw std::runtime_error("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + - // reader.db.get_info_for(o)); + throw std::runtime_error("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + + reader.db.get_info_for(o)); } /*! diff --git a/goalc/goos/Object.h b/goalc/goos/Object.h index 9f6ba23e31..6381b3ed29 100644 --- a/goalc/goos/Object.h +++ b/goalc/goos/Object.h @@ -222,78 +222,78 @@ class Object { std::shared_ptr as_pair() const { if (type != ObjectType::PAIR) { - // throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_env() const { if (type != ObjectType::ENVIRONMENT) { - // throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print()); + throw std::runtime_error("as_env called on a " + object_type_to_string(type) + " " + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_symbol() const { if (type != ObjectType::SYMBOL) { - // throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_symbol called on a " + object_type_to_string(type) + " " + + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_string() const { if (type != ObjectType::STRING) { - // throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " + + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_lambda() const { if (type != ObjectType::LAMBDA) { - // throw std::runtime_error("as_lambda called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_lambda called on a " + object_type_to_string(type) + " " + + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_macro() const { if (type != ObjectType::MACRO) { - // throw std::runtime_error("as_macro called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_macro called on a " + object_type_to_string(type) + " " + + print()); } return std::dynamic_pointer_cast(heap_obj); } std::shared_ptr as_array() const { if (type != ObjectType::ARRAY) { - // throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + + print()); } return std::dynamic_pointer_cast(heap_obj); } IntType& as_int() { if (type != ObjectType::INTEGER) { - // throw std::runtime_error("as_int called on a " + object_type_to_string(type) + " " + print()); + throw std::runtime_error("as_int called on a " + object_type_to_string(type) + " " + print()); } return integer_obj.value; } FloatType& as_float() { if (type != ObjectType::FLOAT) { - // throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " + + print()); } return float_obj.value; } char& as_char() { if (type != ObjectType::CHAR) { - // throw std::runtime_error("as_char called on a " + object_type_to_string(type) + " " + - // print()); + throw std::runtime_error("as_char called on a " + object_type_to_string(type) + " " + + print()); } return char_obj.value; } diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index b329d8a350..d39cbe5ce7 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -278,7 +278,7 @@ bool Reader::read_object(Token& tok, TextStream& ts, Object& obj) { if (try_token_as_symbol(tok, obj)) { return true; } - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw_reader_error(ts, "parsing token " + tok.text + " failed: " + e.what(), -1); } @@ -564,7 +564,7 @@ bool Reader::try_token_as_float(const Token& tok, Object& obj) { return false; obj = Object::make_float(v); return true; - } catch (std::runtime_error& e) { + } catch (std::exception& e) { return false; } } @@ -627,7 +627,7 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { return false; obj = Object::make_integer(v); return true; - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw std::runtime_error("The number cannot be a hexadecimal constant"); } } @@ -661,7 +661,7 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { return false; obj = Object::make_integer(v); return true; - } catch (std::runtime_error& e) { + } catch (std::exception& e) { throw std::runtime_error("The number cannot be an integer constant"); } } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index feb0976de2..e62259d8e1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,14 +2,15 @@ enable_testing() add_executable(goalc-test test_main.cpp - test_test.cpp - test_reader.cpp - test_goos.cpp - test_listener_deci2.cpp - test_kernel.cpp - test_CodeTester.cpp - all_jak1_symbols.cpp - test_type_system.cpp) + #test_test.cpp + test_reader.cpp #problematic + #test_goos.cpp #problematic + #test_listener_deci2.cpp + #all_jak1_symbols.cpp + #test_kernel.cpp + #test_CodeTester.cpp + #test_type_system.cpp +) IF (WIN32) diff --git a/test/test_kernel.cpp b/test/test_kernel.cpp index 0e5b3b96ba..e5d08c6ec4 100644 --- a/test/test_kernel.cpp +++ b/test/test_kernel.cpp @@ -156,7 +156,8 @@ TEST(Kernel, ftoa) { ftoa(buffer, 1., 1, ' ', 1, 0); EXPECT_EQ("1.0", std::string(buffer)); - //ftoa(buffer, 0.f / 0.f, 1, ' ', 4, 0); + float zero = 0.0f; + ftoa(buffer, 0.f / zero, 1, ' ', 4, 0); EXPECT_EQ("NaN", std::string(buffer)); ftoa(buffer, 1., 8, ' ', 1, 0); @@ -165,7 +166,7 @@ TEST(Kernel, ftoa) { ftoa(buffer, -1., 8, '0', 1, 0); EXPECT_EQ("0000-1.0", std::string(buffer)); - //ftoa(buffer, 0.f / 0.f, 8, ' ', 4, 0); + ftoa(buffer, 0.f / zero, 8, ' ', 4, 0); EXPECT_EQ(" NaN", std::string(buffer)); ftoa(buffer, 0.1, 1, ' ', 4, 0); diff --git a/test/test_reader.cpp b/test/test_reader.cpp index b49eda1242..a670563b83 100644 --- a/test/test_reader.cpp +++ b/test/test_reader.cpp @@ -54,279 +54,280 @@ TEST(GoosReader, Integer) { // too big or too small. EXPECT_ANY_THROW(reader.read_from_string("9223372036854775808")); EXPECT_ANY_THROW(reader.read_from_string("-9223372036854775809")); + printf("got here"); } -TEST(GoosReader, Hex) { - Reader reader; - EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0"), 0)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#x1"), 1)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#xf"), 15)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#xF"), 15)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0F"), 15)); - EXPECT_TRUE(check_first_integer( - reader.read_from_string("#x0000000000000000000000000000000000000000000000000000f"), 15)); +//TEST(GoosReader, Hex) { +// Reader reader; +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0"), 0)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x1"), 1)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xf"), 15)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xF"), 15)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0F"), 15)); +// EXPECT_TRUE(check_first_integer( +// reader.read_from_string("#x0000000000000000000000000000000000000000000000000000f"), 15)); +// +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffff"), UINT32_MAX)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x100000000"), (1LL << 32LL))); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x7FFFFFFFFFFFFFFF"), INT64_MAX)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x8000000000000000"), INT64_MIN)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffffffffffff"), -1)); +// +// EXPECT_ANY_THROW(reader.read_from_string("#x10000000000000000")); +// +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x"), "#x")); +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x-1"), "#x-1")); +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x.1"), "#x.1")); +//} +// +//TEST(GoosReader, Binary) { +// Reader reader; +// +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0"), 0)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0000000000"), 0)); +// EXPECT_TRUE(check_first_integer( +// reader.read_from_string("#b000000000000000000000000000000000000000000000000000000000000000000" +// "00000000000000000000000000000000"), +// 0)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b1"), 1)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b10"), 2)); +// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b01011"), 11)); +// EXPECT_TRUE(check_first_integer( +// reader.read_from_string("#b1111111111111111111111111111111111111111111111111111111111111111"), +// -1)); +// EXPECT_TRUE(check_first_integer( +// reader.read_from_string( +// "#b000001111111111111111111111111111111111111111111111111111111111111111"), +// -1)); +// +// EXPECT_TRUE(check_first_integer( +// reader.read_from_string("#b0111111111111111111111111111111111111111111111111111111111111111"), +// INT64_MAX)); +// EXPECT_TRUE(check_first_integer( +// reader.read_from_string("#b1000000000000000000000000000000000000000000000000000000000000000"), +// INT64_MIN)); +// +// EXPECT_ANY_THROW(reader.read_from_string( +// "#b11111111111111111111111111111111111111111111111111111111111111111")); +// +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b"), "#b")); +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b-1"), "#b-1")); +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b.1"), "#b.1")); +//} - EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffff"), UINT32_MAX)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#x100000000"), (1LL << 32LL))); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#x7FFFFFFFFFFFFFFF"), INT64_MAX)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#x8000000000000000"), INT64_MIN)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffffffffffff"), -1)); - - EXPECT_ANY_THROW(reader.read_from_string("#x10000000000000000")); - - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x"), "#x")); - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x-1"), "#x-1")); - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x.1"), "#x.1")); -} - -TEST(GoosReader, Binary) { - Reader reader; - - EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0"), 0)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0000000000"), 0)); - EXPECT_TRUE(check_first_integer( - reader.read_from_string("#b000000000000000000000000000000000000000000000000000000000000000000" - "00000000000000000000000000000000"), - 0)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#b1"), 1)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#b10"), 2)); - EXPECT_TRUE(check_first_integer(reader.read_from_string("#b01011"), 11)); - EXPECT_TRUE(check_first_integer( - reader.read_from_string("#b1111111111111111111111111111111111111111111111111111111111111111"), - -1)); - EXPECT_TRUE(check_first_integer( - reader.read_from_string( - "#b000001111111111111111111111111111111111111111111111111111111111111111"), - -1)); - - EXPECT_TRUE(check_first_integer( - reader.read_from_string("#b0111111111111111111111111111111111111111111111111111111111111111"), - INT64_MAX)); - EXPECT_TRUE(check_first_integer( - reader.read_from_string("#b1000000000000000000000000000000000000000000000000000000000000000"), - INT64_MIN)); - - EXPECT_ANY_THROW(reader.read_from_string( - "#b11111111111111111111111111111111111111111111111111111111111111111")); - - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b"), "#b")); - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b-1"), "#b-1")); - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b.1"), "#b.1")); -} - -TEST(GoosReader, Float) { - Reader reader; - - EXPECT_TRUE(check_first_float(reader.read_from_string("1.6"), 1.6)); - EXPECT_TRUE(check_first_float(reader.read_from_string("0000001.6"), 1.6)); - EXPECT_TRUE(check_first_float(reader.read_from_string("0.6"), 0.6)); - EXPECT_TRUE(check_first_float(reader.read_from_string("00000.6"), 0.6)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-0.6"), -0.6)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-000000.6"), -0.6)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-.6"), -.6)); - - EXPECT_TRUE(check_first_float(reader.read_from_string("1."), 1)); - EXPECT_TRUE(check_first_float(reader.read_from_string("1.0"), 1)); - EXPECT_TRUE(check_first_float(reader.read_from_string("01."), 1)); - EXPECT_TRUE(check_first_float(reader.read_from_string("01.0"), 1)); - - EXPECT_TRUE(check_first_float(reader.read_from_string("0."), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string(".0"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("0.0"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("000."), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string(".000"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("0.000"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("000.0"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("000.0000"), 0)); - - EXPECT_TRUE(check_first_float(reader.read_from_string("-0."), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-.0"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-0.0"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-000."), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-.000"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-0.000"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0"), 0)); - EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0000"), 0)); - - EXPECT_TRUE(check_first_symbol(reader.read_from_string("1e0"), "1e0")); - EXPECT_ANY_THROW(reader.read_from_string(".")); -} - -TEST(GoosReader, Boolean) { - Reader reader; - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#f"), "#f")); - EXPECT_TRUE(check_first_symbol(reader.read_from_string("#t"), "#t")); -} - -TEST(GoosReader, String) { - Reader reader; - EXPECT_TRUE( - check_first_string(reader.read_from_string("\"testing string ()\""), "testing string ()")); - EXPECT_TRUE(check_first_string(reader.read_from_string("\"\""), "")); - EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\t \""), " \t ")); - EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\n \""), " \n ")); - EXPECT_TRUE(check_first_string(reader.read_from_string("\"test \\n\""), "test \n")); - EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\\\ \""), " \\ ")); - EXPECT_ANY_THROW(reader.read_from_string("\"\\\"")); // "\" invalid escape - EXPECT_ANY_THROW(reader.read_from_string("\"\\w\"")); // "\w" invalid escape -} - -TEST(GoosReader, Symbol) { - std::vector test_symbols = { - "test", "test-two", "__werid-sym__", "-a", "-", "/", "*", "+", "a", "#f"}; - - Reader reader; - - for (const auto& sym : test_symbols) { - EXPECT_TRUE(check_first_symbol(reader.read_from_string(sym), sym)); - } -} - -namespace { -bool first_list_matches(Object o, std::vector stuff) { - auto lst = o.as_pair()->cdr.as_pair()->car; - for (const auto& x : stuff) { - const auto check = x.as_pair()->cdr.as_pair()->car; - if (lst.as_pair()->car != check) { - return false; - } - lst = lst.as_pair()->cdr; - } - - return lst.is_empty_list(); -} - -bool first_array_matches(Object o, std::vector stuff) { - auto array = o.as_pair()->cdr.as_pair()->car.as_array(); - if (stuff.size() != array->size()) { - return false; - } - - for (size_t i = 0; i < array->size(); i++) { - if ((*array)[i] != stuff.at(i)) { - return false; - } - } - return true; -} - -bool first_pair_matches(Object o, Object car, Object cdr) { - auto lst = o.as_pair()->cdr.as_pair()->car; - return (lst.as_pair()->car == car) && (lst.as_pair()->cdr == cdr); -} - -bool print_matches(Object o, std::string expected) { - return o.as_pair()->cdr.as_pair()->car.print() == expected; -} - -bool first_char_matches(Object o, char c) { - return o.as_pair()->cdr.as_pair()->car.as_char() == c; -} - -} // namespace - -TEST(GoosReader, List) { - Reader reader; - auto r = [&](std::string s) { return reader.read_from_string(s); }; - EXPECT_TRUE(first_list_matches(r("()"), {})); - EXPECT_TRUE(first_list_matches(r("(1)"), {r("1")})); - EXPECT_TRUE(first_list_matches(r(" ( 1 ) "), {r("1")})); - EXPECT_TRUE(first_list_matches(r("(1 2 3)"), {r("1"), r("2"), r("3")})); - EXPECT_TRUE(first_list_matches(r(" ( 1 bbbb 3 ) "), {r("1"), r("bbbb"), r("3")})); - - EXPECT_TRUE(first_pair_matches(r("(1 . 2)"), Object::make_integer(1), Object::make_integer(2))); - - EXPECT_TRUE(print_matches(r(" ( 1 . 2 ) "), "(1 . 2)")); - EXPECT_TRUE(print_matches(r(" ( 1 1 . 2 ) "), "(1 1 . 2)")); - EXPECT_TRUE(print_matches(r(" ( 1 . ( 1 . 2 ) ) "), "(1 1 . 2)")); - EXPECT_TRUE( - print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . 3 ) "), "(1 (1 2) (1 (12 3)) . 3)")); - EXPECT_TRUE( - print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . ( ) ) "), "(1 (1 2) (1 (12 3)))")); - - std::vector expected_to_throw = {"(", ")", " (", " )()() ", - ")(", "(1 2 ))", "(( 1 2)", "(1 . . 2)", - "(1 . )", "(1 . 2 3)", "( . 2)"}; - - for (const auto& x : expected_to_throw) { - EXPECT_ANY_THROW(r(x)); - } -} - -TEST(GoosReader, Comments) { - Reader reader; - auto r = [&](std::string s) { return reader.read_from_string(s); }; - EXPECT_TRUE(first_list_matches(r(";;\n(1)\n;;"), {r("1")})); - EXPECT_TRUE(first_list_matches(r(";;\n(;1\n1;)\n);;\n;"), {r("1")})); - - r(";"); - r(" ;"); - r("\n;"); - r(";\n"); - - EXPECT_TRUE(first_list_matches( - r("#|multi line\n com(((((ment |# (1) #| multi line\n comm)))))ent |#"), {r("1")})); - EXPECT_TRUE(first_list_matches( - r("#| #| multi l#|ine\n com#|ment |# (1) #| multi line\n commen))))))t |#"), {r("1")})); - - std::vector expected_to_throw = {"|#", "#| |# |#"}; - - for (const auto& x : expected_to_throw) { - EXPECT_ANY_THROW(r(x)); - } -} - -TEST(GoosReader, Char) { - Reader reader; - auto r = [&](std::string s) { return reader.read_from_string(s); }; - - EXPECT_TRUE(first_char_matches(r("#\\c"), 'c')); - EXPECT_TRUE(first_char_matches(r("#\\n"), 'n')); - EXPECT_TRUE(first_char_matches(r("#\\\\n"), '\n')); - EXPECT_TRUE(first_char_matches(r("#\\\\t"), '\t')); - EXPECT_TRUE(first_char_matches(r("#\\\\s"), ' ')); -} - -TEST(GoosReader, Array) { - Reader reader; - auto r = [&](std::string s) { return reader.read_from_string(s); }; - EXPECT_TRUE(print_matches(r(" #( ) "), "#()")); - EXPECT_TRUE(first_array_matches(r("#()"), {})); - EXPECT_TRUE(first_array_matches(r("#(1 2)"), {Object::make_integer(1), Object::make_integer(2)})); - EXPECT_TRUE(first_array_matches(r("#( 1 #| 2 |# 3 )"), - {Object::make_integer(1), Object::make_integer(3)})); - EXPECT_TRUE( - first_array_matches(r("#( 1 #|2|# 3 )"), {Object::make_integer(1), Object::make_integer(3)})); -} - -TEST(GoosReader, Macros) { - Reader reader; - auto r = [&](std::string s) { return reader.read_from_string(s); }; - EXPECT_TRUE(print_matches(r("'x"), "(quote x)")); - EXPECT_TRUE(print_matches(r("`x"), "(quasiquote x)")); - EXPECT_TRUE(print_matches(r(",x"), "(unquote x)")); - EXPECT_TRUE(print_matches(r(",@x"), "(unquote-splicing x)")); -} - -TEST(GoosReader, TopLevel) { - Reader reader; - auto r = [&](std::string s) { return reader.read_from_string(s); }; - EXPECT_EQ(r("x").print(), "(top-level x)"); -} - -TEST(GoosReader, FromFile) { - Reader reader; - auto result = - reader.read_from_file(util::combine_path({"test", "test_reader_file0.gc"})).print(); - EXPECT_TRUE(result == "(top-level (1 2 3 4))"); -} - -TEST(GoosReader, TextDb) { - // very specific to this particular test file, but whatever. - Reader reader; - auto file_path = util::combine_path({"test", "test_reader_file0.gc"}); - auto result = reader.read_from_file(file_path).as_pair()->cdr.as_pair()->car; - std::string expected = "text from " + util::combine_path(reader.get_source_dir(), file_path) + - ", line: 5\n(1 2 3 4)\n"; - EXPECT_EQ(expected, reader.db.get_info_for(result)); -} +//TEST(GoosReader, Float) { +// Reader reader; +// +// EXPECT_TRUE(check_first_float(reader.read_from_string("1.6"), 1.6)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("0000001.6"), 1.6)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("0.6"), 0.6)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("00000.6"), 0.6)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.6"), -0.6)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-000000.6"), -0.6)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-.6"), -.6)); +// +// EXPECT_TRUE(check_first_float(reader.read_from_string("1."), 1)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("1.0"), 1)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("01."), 1)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("01.0"), 1)); +// +// EXPECT_TRUE(check_first_float(reader.read_from_string("0."), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string(".0"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("0.0"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("000."), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string(".000"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("0.000"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("000.0"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("000.0000"), 0)); +// +// EXPECT_TRUE(check_first_float(reader.read_from_string("-0."), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-.0"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.0"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-000."), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-.000"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.000"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0"), 0)); +// EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0000"), 0)); +// +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("1e0"), "1e0")); +// EXPECT_ANY_THROW(reader.read_from_string(".")); +//} +// +//TEST(GoosReader, Boolean) { +// Reader reader; +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#f"), "#f")); +// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#t"), "#t")); +//} +// +//TEST(GoosReader, String) { +// Reader reader; +// EXPECT_TRUE( +// check_first_string(reader.read_from_string("\"testing string ()\""), "testing string ()")); +// EXPECT_TRUE(check_first_string(reader.read_from_string("\"\""), "")); +// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\t \""), " \t ")); +// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\n \""), " \n ")); +// EXPECT_TRUE(check_first_string(reader.read_from_string("\"test \\n\""), "test \n")); +// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\\\ \""), " \\ ")); +// EXPECT_ANY_THROW(reader.read_from_string("\"\\\"")); // "\" invalid escape +// EXPECT_ANY_THROW(reader.read_from_string("\"\\w\"")); // "\w" invalid escape +//} +// +//TEST(GoosReader, Symbol) { +// std::vector test_symbols = { +// "test", "test-two", "__werid-sym__", "-a", "-", "/", "*", "+", "a", "#f"}; +// +// Reader reader; +// +// for (const auto& sym : test_symbols) { +// EXPECT_TRUE(check_first_symbol(reader.read_from_string(sym), sym)); +// } +//} +// +//namespace { +//bool first_list_matches(Object o, std::vector stuff) { +// auto lst = o.as_pair()->cdr.as_pair()->car; +// for (const auto& x : stuff) { +// const auto check = x.as_pair()->cdr.as_pair()->car; +// if (lst.as_pair()->car != check) { +// return false; +// } +// lst = lst.as_pair()->cdr; +// } +// +// return lst.is_empty_list(); +//} +// +//bool first_array_matches(Object o, std::vector stuff) { +// auto array = o.as_pair()->cdr.as_pair()->car.as_array(); +// if (stuff.size() != array->size()) { +// return false; +// } +// +// for (size_t i = 0; i < array->size(); i++) { +// if ((*array)[i] != stuff.at(i)) { +// return false; +// } +// } +// return true; +//} +// +//bool first_pair_matches(Object o, Object car, Object cdr) { +// auto lst = o.as_pair()->cdr.as_pair()->car; +// return (lst.as_pair()->car == car) && (lst.as_pair()->cdr == cdr); +//} +// +//bool print_matches(Object o, std::string expected) { +// return o.as_pair()->cdr.as_pair()->car.print() == expected; +//} +// +//bool first_char_matches(Object o, char c) { +// return o.as_pair()->cdr.as_pair()->car.as_char() == c; +//} +// +//} // namespace +// +//TEST(GoosReader, List) { +// Reader reader; +// auto r = [&](std::string s) { return reader.read_from_string(s); }; +// EXPECT_TRUE(first_list_matches(r("()"), {})); +// EXPECT_TRUE(first_list_matches(r("(1)"), {r("1")})); +// EXPECT_TRUE(first_list_matches(r(" ( 1 ) "), {r("1")})); +// EXPECT_TRUE(first_list_matches(r("(1 2 3)"), {r("1"), r("2"), r("3")})); +// EXPECT_TRUE(first_list_matches(r(" ( 1 bbbb 3 ) "), {r("1"), r("bbbb"), r("3")})); +// +// EXPECT_TRUE(first_pair_matches(r("(1 . 2)"), Object::make_integer(1), Object::make_integer(2))); +// +// EXPECT_TRUE(print_matches(r(" ( 1 . 2 ) "), "(1 . 2)")); +// EXPECT_TRUE(print_matches(r(" ( 1 1 . 2 ) "), "(1 1 . 2)")); +// EXPECT_TRUE(print_matches(r(" ( 1 . ( 1 . 2 ) ) "), "(1 1 . 2)")); +// EXPECT_TRUE( +// print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . 3 ) "), "(1 (1 2) (1 (12 3)) . 3)")); +// EXPECT_TRUE( +// print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . ( ) ) "), "(1 (1 2) (1 (12 3)))")); +// +// std::vector expected_to_throw = {"(", ")", " (", " )()() ", +// ")(", "(1 2 ))", "(( 1 2)", "(1 . . 2)", +// "(1 . )", "(1 . 2 3)", "( . 2)"}; +// +// for (const auto& x : expected_to_throw) { +// EXPECT_ANY_THROW(r(x)); +// } +//} +// +//TEST(GoosReader, Comments) { +// Reader reader; +// auto r = [&](std::string s) { return reader.read_from_string(s); }; +// EXPECT_TRUE(first_list_matches(r(";;\n(1)\n;;"), {r("1")})); +// EXPECT_TRUE(first_list_matches(r(";;\n(;1\n1;)\n);;\n;"), {r("1")})); +// +// r(";"); +// r(" ;"); +// r("\n;"); +// r(";\n"); +// +// EXPECT_TRUE(first_list_matches( +// r("#|multi line\n com(((((ment |# (1) #| multi line\n comm)))))ent |#"), {r("1")})); +// EXPECT_TRUE(first_list_matches( +// r("#| #| multi l#|ine\n com#|ment |# (1) #| multi line\n commen))))))t |#"), {r("1")})); +// +// std::vector expected_to_throw = {"|#", "#| |# |#"}; +// +// for (const auto& x : expected_to_throw) { +// EXPECT_ANY_THROW(r(x)); +// } +//} +// +//TEST(GoosReader, Char) { +// Reader reader; +// auto r = [&](std::string s) { return reader.read_from_string(s); }; +// +// EXPECT_TRUE(first_char_matches(r("#\\c"), 'c')); +// EXPECT_TRUE(first_char_matches(r("#\\n"), 'n')); +// EXPECT_TRUE(first_char_matches(r("#\\\\n"), '\n')); +// EXPECT_TRUE(first_char_matches(r("#\\\\t"), '\t')); +// EXPECT_TRUE(first_char_matches(r("#\\\\s"), ' ')); +//} +// +//TEST(GoosReader, Array) { +// Reader reader; +// auto r = [&](std::string s) { return reader.read_from_string(s); }; +// EXPECT_TRUE(print_matches(r(" #( ) "), "#()")); +// EXPECT_TRUE(first_array_matches(r("#()"), {})); +// EXPECT_TRUE(first_array_matches(r("#(1 2)"), {Object::make_integer(1), Object::make_integer(2)})); +// EXPECT_TRUE(first_array_matches(r("#( 1 #| 2 |# 3 )"), +// {Object::make_integer(1), Object::make_integer(3)})); +// EXPECT_TRUE( +// first_array_matches(r("#( 1 #|2|# 3 )"), {Object::make_integer(1), Object::make_integer(3)})); +//} +// +//TEST(GoosReader, Macros) { +// Reader reader; +// auto r = [&](std::string s) { return reader.read_from_string(s); }; +// EXPECT_TRUE(print_matches(r("'x"), "(quote x)")); +// EXPECT_TRUE(print_matches(r("`x"), "(quasiquote x)")); +// EXPECT_TRUE(print_matches(r(",x"), "(unquote x)")); +// EXPECT_TRUE(print_matches(r(",@x"), "(unquote-splicing x)")); +//} +// +//TEST(GoosReader, TopLevel) { +// Reader reader; +// auto r = [&](std::string s) { return reader.read_from_string(s); }; +// EXPECT_EQ(r("x").print(), "(top-level x)"); +//} +// +//TEST(GoosReader, FromFile) { +// Reader reader; +// auto result = +// reader.read_from_file(util::combine_path({"test", "test_reader_file0.gc"})).print(); +// EXPECT_TRUE(result == "(top-level (1 2 3 4))"); +//} +// +//TEST(GoosReader, TextDb) { +// // very specific to this particular test file, but whatever. +// Reader reader; +// auto file_path = util::combine_path({"test", "test_reader_file0.gc"}); +// auto result = reader.read_from_file(file_path).as_pair()->cdr.as_pair()->car; +// std::string expected = "text from " + util::combine_path(reader.get_source_dir(), file_path) + +// ", line: 5\n(1 2 3 4)\n"; +// EXPECT_EQ(expected, reader.db.get_info_for(result)); +//} From cfba57e7a3f91e14c95cdd7dd5f3f6ff13fdbe61 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Sat, 29 Aug 2020 12:58:42 -0600 Subject: [PATCH 19/32] Update json.hpp Fix broken changes I made earlier --- third-party/json.hpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/third-party/json.hpp b/third-party/json.hpp index 740e9f12a7..9c66a8457f 100644 --- a/third-party/json.hpp +++ b/third-party/json.hpp @@ -70,7 +70,7 @@ SOFTWARE. #include // exception -#include // exception +#include // runtime_error #include // to_string // #include @@ -92,7 +92,7 @@ struct position_t /// the number of lines read std::size_t lines_read = 0; - /// conversion to size_t to preserve SAX interfaces + /// conversion to size_t to preserve SAX interface constexpr operator size_t() const { return chars_read_total; @@ -2324,7 +2324,7 @@ namespace detail /*! @brief general exception of the @ref basic_json class -This class is an extension of `std::runtime_error` objects with a member @a id for +This class is an extension of `std::exception` objects with a member @a id for exception ids. It is used as the base class for all exceptions thrown by the @ref basic_json class. This class can hence be used as "wildcard" to catch exceptions. @@ -2349,7 +2349,7 @@ caught.,exception} @since version 3.0.0 */ -class exception : public std::runtime_error +class exception : public std::exception { public: /// returns the explanatory string @@ -4823,7 +4823,7 @@ class input_stream_adapter std::char_traits::int_type get_character() { auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interfaces. + // set eof manually, as we don't use the istream interface. if (JSON_HEDLEY_UNLIKELY(res == EOF)) { is->clear(is->rdstate() | std::ios::eofbit); @@ -5191,9 +5191,9 @@ namespace nlohmann { /*! -@brief SAX interfaces +@brief SAX interface -This class describes the SAX interfaces used by @ref nlohmann::json::sax_parse. +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. Each function is called in different situations while the input is parsed. The boolean return value informs the parser whether to continue processing the input. @@ -5314,7 +5314,7 @@ namespace detail /*! @brief SAX implementation to create a JSON value from SAX events -This class implements the @ref json_sax interfaces and processes the SAX events +This class implements the @ref json_sax interface and processes the SAX events to create a JSON value which makes it basically a DOM parser. The structure or hierarchy of the JSON value is managed by the stack `ref_stack` which contains a pointer to the respective array or object for each recursion depth. @@ -7198,7 +7198,7 @@ scan_number_done: /* @brief get next character from the input - This function provides the interfaces to the used input adapter. It does + This function provides the interface to the used input adapter. It does not throw in case the input reached EOF, but returns a `std::char_traits::eof()` in that case. Stores the scanned characters for use in error messages. @@ -9881,7 +9881,7 @@ class binary_reader /*! @brief get next character from the input - This function provides the interfaces to the used input adapter. It does + This function provides the interface to the used input adapter. It does not throw in case the input reached EOF, but returns a -'ve valued `std::char_traits::eof()` in that case. @@ -10184,7 +10184,7 @@ class parser } /*! - @brief public parser interfaces + @brief public parser interface @param[in] strict whether to expect the last token to be EOF @param[in,out] result parsed JSON value @@ -10249,7 +10249,7 @@ class parser } /*! - @brief public accept interfaces + @brief public accept interface @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text @@ -12628,7 +12628,7 @@ namespace nlohmann { namespace detail { -/// abstract output adapter interfaces +/// abstract output adapter interface template struct output_adapter_protocol { virtual void write_character(CharType c) = 0; @@ -16724,7 +16724,7 @@ class basic_json using initializer_list_t = std::initializer_list>; using input_format_t = detail::input_format_t; - /// SAX interfaces type, see @ref nlohmann::json_sax + /// SAX interface type, see @ref nlohmann::json_sax using json_sax_t = json_sax; //////////////// @@ -21253,7 +21253,7 @@ class basic_json element as string (see example). @param[in] ref reference to a JSON value - @return iteration proxy object wrapping @a ref with an interfaces to use in + @return iteration proxy object wrapping @a ref with an interface to use in range-based for loops @liveexample{The following code shows how the wrapper is used,iterator_wrapper} @@ -21341,7 +21341,7 @@ class basic_json for more information. - @return iteration proxy object wrapping @a ref with an interfaces to use in + @return iteration proxy object wrapping @a ref with an interface to use in range-based for loops @liveexample{The following code shows how the function is used.,items} @@ -23249,7 +23249,7 @@ class basic_json /*! @brief generate SAX events - The SAX event lister must follow the interfaces of @ref json_sax. + The SAX event lister must follow the interface of @ref json_sax. This function reads from a compatible input. Examples are: - an std::istream object From a87060320a6b0bfb46cecf08f2bb006ffb061c64 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 29 Aug 2020 15:11:16 -0400 Subject: [PATCH 20/32] Cleaned up some unneeded changes --- common/type_system/TypeSystem.h | 2 +- decompiler/util/FileIO.cpp | 4 ++-- decompiler/util/Timer.cpp | 4 ++-- decompiler/util/Timer.h | 4 +--- goalc/goos/Interpreter.cpp | 8 ++++---- goalc/goos/Object.cpp | 2 +- goalc/goos/Object.h | 8 ++++---- goalc/goos/Reader.cpp | 11 +++++----- goalc/util/file_io.cpp | 2 +- test/all_jak1_symbols.cpp | 2 +- third-party/fmt/format-inl.h | 2 +- third-party/fmt/format.h | 4 ++-- third-party/json.hpp | 36 ++++++++++++++++----------------- third-party/minilzo/lzoconf.h | 2 +- 14 files changed, 45 insertions(+), 46 deletions(-) diff --git a/common/type_system/TypeSystem.h b/common/type_system/TypeSystem.h index d866804db5..71a865588b 100644 --- a/common/type_system/TypeSystem.h +++ b/common/type_system/TypeSystem.h @@ -76,7 +76,7 @@ class TypeSystem { auto x = lookup_type(type_name); T* result = dynamic_cast(x); if (!result) { - throw std::runtime_error("Failed to get the right type"); + throw std::runtime_error("Failed to get " + type_name + " as the right type"); } return result; } diff --git a/decompiler/util/FileIO.cpp b/decompiler/util/FileIO.cpp index 9a7dd7224b..914d647d59 100644 --- a/decompiler/util/FileIO.cpp +++ b/decompiler/util/FileIO.cpp @@ -16,7 +16,7 @@ std::string combine_path(const std::string& parent, const std::string& child) { std::vector read_binary_file(const std::string& filename) { auto fp = fopen(filename.c_str(), "rb"); - if(!fp) throw std::runtime_error("File cannot be opened"); + if(!fp) throw std::runtime_error("File " + filename + " cannot be opened"); fseek(fp, 0, SEEK_END); auto len = ftell(fp); rewind(fp); @@ -25,7 +25,7 @@ std::vector read_binary_file(const std::string& filename) { data.resize(len); if(fread(data.data(), len, 1, fp) != 1) { - throw std::runtime_error("File cannot be read"); + throw std::runtime_error("File " + filename + " cannot be read"); } return data; diff --git a/decompiler/util/Timer.cpp b/decompiler/util/Timer.cpp index 0a5d895064..4ac44ab25c 100644 --- a/decompiler/util/Timer.cpp +++ b/decompiler/util/Timer.cpp @@ -48,7 +48,7 @@ int64_t Timer::getNs() { clock_gettime(CLOCK_MONOTONIC, &now); #elif _WIN32 clock_gettime_monotonic(&now); -#endif; +#endif return (int64_t)(now.tv_nsec - _startTime.tv_nsec) + 1000000000 * (now.tv_sec - _startTime.tv_sec); -} \ No newline at end of file +} diff --git a/decompiler/util/Timer.h b/decompiler/util/Timer.h index c589657a00..5972020339 100644 --- a/decompiler/util/Timer.h +++ b/decompiler/util/Timer.h @@ -19,8 +19,6 @@ class Timer { int clock_gettime_monotonic(struct timespec* tv); #endif - - /*! * Start the timer */ @@ -29,7 +27,7 @@ class Timer { /*! * Get milliseconds elapsed */ - double getMs() { return (double)getNs() / 1.e6; } + double getMs() { return (double)getNs() / 1.e6; } double getUs() { return (double)getNs() / 1.e3; } diff --git a/goalc/goos/Interpreter.cpp b/goalc/goos/Interpreter.cpp index e98f0df660..f37ba8c1e6 100644 --- a/goalc/goos/Interpreter.cpp +++ b/goalc/goos/Interpreter.cpp @@ -97,7 +97,7 @@ void Interpreter::disable_printfs() { */ void Interpreter::load_goos_library() { auto cmd = "(load-file \"goalc/gs/goos-lib.gs\")"; - eval_with_rewind(reader.read_from_string(cmd), global_environment.as_env()); + eval_with_rewind(reader.read_from_string(cmd), global_environment.as_env()); } /*! @@ -137,8 +137,8 @@ void Interpreter::execute_repl() { * for debugging. */ void Interpreter::throw_eval_error(const Object& o, const std::string& err) { - throw std::runtime_error("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + - reader.db.get_info_for(o)); + throw std::runtime_error("[GOOS] Evaluation error on " + o.print() + ": " + err + "\n" + + reader.db.get_info_for(o)); } /*! @@ -918,4 +918,4 @@ Object Interpreter::eval_while(const Object& form, return rv; } -} // namespace goos \ No newline at end of file +} // namespace goos diff --git a/goalc/goos/Object.cpp b/goalc/goos/Object.cpp index f2f0dfd623..1023ff3581 100644 --- a/goalc/goos/Object.cpp +++ b/goalc/goos/Object.cpp @@ -151,7 +151,7 @@ bool Object::operator==(const Object& other) const { } default: - throw std::runtime_error("equality not implemented for"); + throw std::runtime_error("equality not implemented for " + print()); } } diff --git a/goalc/goos/Object.h b/goalc/goos/Object.h index 6381b3ed29..926014bc6e 100644 --- a/goalc/goos/Object.h +++ b/goalc/goos/Object.h @@ -222,7 +222,7 @@ class Object { std::shared_ptr as_pair() const { if (type != ObjectType::PAIR) { - throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + + throw std::runtime_error("as_pair called on a " + object_type_to_string(type) + " " + print()); } return std::dynamic_pointer_cast(heap_obj); @@ -246,7 +246,7 @@ class Object { std::shared_ptr as_string() const { if (type != ObjectType::STRING) { throw std::runtime_error("as_string called on a " + object_type_to_string(type) + " " + - print()); + print()); } return std::dynamic_pointer_cast(heap_obj); } @@ -269,7 +269,7 @@ class Object { std::shared_ptr as_array() const { if (type != ObjectType::ARRAY) { - throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + + throw std::runtime_error("as_array called on a " + object_type_to_string(type) + " " + print()); } return std::dynamic_pointer_cast(heap_obj); @@ -284,7 +284,7 @@ class Object { FloatType& as_float() { if (type != ObjectType::FLOAT) { - throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " + + throw std::runtime_error("as_float called on a " + object_type_to_string(type) + " " + print()); } return float_obj.value; diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index d39cbe5ce7..f4b4ec73da 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -588,7 +588,7 @@ bool Reader::try_token_as_binary(const Token& tok, Object& obj) { for (uint32_t i = 2; i < tok.text.size(); i++) { if (value & (0x8000000000000000)) { - throw std::runtime_error("overflow in binary constant:)"); + throw std::runtime_error("overflow in binary constant: " + tok.text); } value <<= 1u; @@ -628,7 +628,7 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::runtime_error("The number cannot be a hexadecimal constant"); + throw std::runtime_error("The number " + tok.text + " cannot be a hexadecimal constant"); } } return false; @@ -662,7 +662,7 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { obj = Object::make_integer(v); return true; } catch (std::exception& e) { - throw std::runtime_error("The number cannot be an integer constant"); + throw std::runtime_error("The number " + tok.text + " cannot be an integer constant"); } } return false; @@ -697,7 +697,8 @@ bool Reader::try_token_as_char(const Token& tok, Object& obj) { * Used for reader errors, like "missing close paren" or similar. */ void Reader::throw_reader_error(TextStream& here, const std::string& err, int seek_offset) { - throw std::runtime_error("Reader error at"); + throw std::runtime_error("Reader error:\n" + err + "\nat " + + db.get_info_for(here.text, here.seek + seek_offset)); } /*! @@ -706,4 +707,4 @@ void Reader::throw_reader_error(TextStream& here, const std::string& err, int se std::string Reader::get_source_dir() { return source_dir; } -} // namespace goos \ No newline at end of file +} // namespace goos diff --git a/goalc/util/file_io.cpp b/goalc/util/file_io.cpp index b659ed7bca..d6b35e1735 100644 --- a/goalc/util/file_io.cpp +++ b/goalc/util/file_io.cpp @@ -7,7 +7,7 @@ namespace util { std::string read_text_file(const std::string& path) { std::ifstream file(path); if (!file.good()) { - throw std::runtime_error("couldn't open "); + throw std::runtime_error("couldn't open " + path); } std::stringstream ss; ss << file.rdbuf(); diff --git a/test/all_jak1_symbols.cpp b/test/all_jak1_symbols.cpp index e0089acc88..9004c70890 100644 --- a/test/all_jak1_symbols.cpp +++ b/test/all_jak1_symbols.cpp @@ -7748,7 +7748,7 @@ const char* all_syms[7941] = {"ripple-for-lava", "list-control", "sunken-pipegame-idle", "anim-test-edit-seq-insert-item", - "anim-tester-interfaces", + "anim-tester-interface", "anim-tester-adjust-frame", "extra-radius", "*volume-descriptor*", diff --git a/third-party/fmt/format-inl.h b/third-party/fmt/format-inl.h index c379681be2..d8c9c8a5ee 100644 --- a/third-party/fmt/format-inl.h +++ b/third-party/fmt/format-inl.h @@ -227,7 +227,7 @@ FMT_FUNC void system_error::init(int err_code, string_view format_str, memory_buffer buffer; format_system_error(buffer, err_code, vformat(format_str, args)); std::runtime_error& base = *this; -// base = std::runtime_error(to_string(buffer)); + base = std::runtime_error(to_string(buffer)); } namespace detail { diff --git a/third-party/fmt/format.h b/third-party/fmt/format.h index a778ce376d..17509b7b45 100644 --- a/third-party/fmt/format.h +++ b/third-party/fmt/format.h @@ -713,8 +713,8 @@ FMT_CLASS_API class FMT_API format_error : public std::runtime_error { public: explicit format_error(const char* message) : std::runtime_error(message) {} - explicit format_error(const std::string& message); - // : std::runtime_error(message) {} + explicit format_error(const std::string& message) + : std::runtime_error(message) {} format_error(const format_error&) = default; format_error& operator=(const format_error&) = default; format_error(format_error&&) = default; diff --git a/third-party/json.hpp b/third-party/json.hpp index 740e9f12a7..b37b2a5f1f 100644 --- a/third-party/json.hpp +++ b/third-party/json.hpp @@ -70,7 +70,7 @@ SOFTWARE. #include // exception -#include // exception +#include // runtime_error #include // to_string // #include @@ -92,7 +92,7 @@ struct position_t /// the number of lines read std::size_t lines_read = 0; - /// conversion to size_t to preserve SAX interfaces + /// conversion to size_t to preserve SAX interface constexpr operator size_t() const { return chars_read_total; @@ -2324,7 +2324,7 @@ namespace detail /*! @brief general exception of the @ref basic_json class -This class is an extension of `std::runtime_error` objects with a member @a id for +This class is an extension of `std::exception` objects with a member @a id for exception ids. It is used as the base class for all exceptions thrown by the @ref basic_json class. This class can hence be used as "wildcard" to catch exceptions. @@ -2349,7 +2349,7 @@ caught.,exception} @since version 3.0.0 */ -class exception : public std::runtime_error +class exception : public std::exception { public: /// returns the explanatory string @@ -4823,7 +4823,7 @@ class input_stream_adapter std::char_traits::int_type get_character() { auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interfaces. + // set eof manually, as we don't use the istream interface. if (JSON_HEDLEY_UNLIKELY(res == EOF)) { is->clear(is->rdstate() | std::ios::eofbit); @@ -5191,9 +5191,9 @@ namespace nlohmann { /*! -@brief SAX interfaces +@brief SAX interface -This class describes the SAX interfaces used by @ref nlohmann::json::sax_parse. +This class describes the SAX interface used by @ref nlohmann::json::sax_parse. Each function is called in different situations while the input is parsed. The boolean return value informs the parser whether to continue processing the input. @@ -5314,7 +5314,7 @@ namespace detail /*! @brief SAX implementation to create a JSON value from SAX events -This class implements the @ref json_sax interfaces and processes the SAX events +This class implements the @ref json_sax interface and processes the SAX events to create a JSON value which makes it basically a DOM parser. The structure or hierarchy of the JSON value is managed by the stack `ref_stack` which contains a pointer to the respective array or object for each recursion depth. @@ -7198,7 +7198,7 @@ scan_number_done: /* @brief get next character from the input - This function provides the interfaces to the used input adapter. It does + This function provides the interface to the used input adapter. It does not throw in case the input reached EOF, but returns a `std::char_traits::eof()` in that case. Stores the scanned characters for use in error messages. @@ -9881,7 +9881,7 @@ class binary_reader /*! @brief get next character from the input - This function provides the interfaces to the used input adapter. It does + This function provides the interface to the used input adapter. It does not throw in case the input reached EOF, but returns a -'ve valued `std::char_traits::eof()` in that case. @@ -10184,7 +10184,7 @@ class parser } /*! - @brief public parser interfaces + @brief public parser interface @param[in] strict whether to expect the last token to be EOF @param[in,out] result parsed JSON value @@ -10249,7 +10249,7 @@ class parser } /*! - @brief public accept interfaces + @brief public accept interface @param[in] strict whether to expect the last token to be EOF @return whether the input is a proper JSON text @@ -12628,7 +12628,7 @@ namespace nlohmann { namespace detail { -/// abstract output adapter interfaces +/// abstract output adapter interface template struct output_adapter_protocol { virtual void write_character(CharType c) = 0; @@ -12636,7 +12636,7 @@ template struct output_adapter_protocol virtual ~output_adapter_protocol() = default; }; -/// a type to simplify interfaces +/// a type to simplify interface template using output_adapter_t = std::shared_ptr>; @@ -16724,7 +16724,7 @@ class basic_json using initializer_list_t = std::initializer_list>; using input_format_t = detail::input_format_t; - /// SAX interfaces type, see @ref nlohmann::json_sax + /// SAX interface type, see @ref nlohmann::json_sax using json_sax_t = json_sax; //////////////// @@ -21253,7 +21253,7 @@ class basic_json element as string (see example). @param[in] ref reference to a JSON value - @return iteration proxy object wrapping @a ref with an interfaces to use in + @return iteration proxy object wrapping @a ref with an interface to use in range-based for loops @liveexample{The following code shows how the wrapper is used,iterator_wrapper} @@ -21341,7 +21341,7 @@ class basic_json for more information. - @return iteration proxy object wrapping @a ref with an interfaces to use in + @return iteration proxy object wrapping @a ref with an interface to use in range-based for loops @liveexample{The following code shows how the function is used.,items} @@ -23249,7 +23249,7 @@ class basic_json /*! @brief generate SAX events - The SAX event lister must follow the interfaces of @ref json_sax. + The SAX event lister must follow the interface of @ref json_sax. This function reads from a compatible input. Examples are: - an std::istream object diff --git a/third-party/minilzo/lzoconf.h b/third-party/minilzo/lzoconf.h index a8ffb99ef8..f9a8bdbee7 100644 --- a/third-party/minilzo/lzoconf.h +++ b/third-party/minilzo/lzoconf.h @@ -264,7 +264,7 @@ typedef int const lzo_bytep dict, lzo_uint dict_len ); -/* Callback interfaces. Currently only the progress indicator ("nprogress") +/* Callback interface. Currently only the progress indicator ("nprogress") * is used, but this may change in a future release. */ struct lzo_callback_t; From 710e12cfed11f2f1c77819c2ca061d408c6ee543 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 29 Aug 2020 15:11:36 -0400 Subject: [PATCH 21/32] some cmake adjustments --- game/CMakeLists.txt | 3 +-- goalc/goos/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 8b0f502456..468b2bb6fa 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -27,7 +27,6 @@ set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS ${CMAKE_ASM_NASM_SOURCE_FILE_EXTENSION set(CMAKE_ASM_NASM_COMPILE_OBJECT " -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o ") set_source_files_properties(kernel/asm_funcs.asm PROPERTIES COMPILE_FLAGS "-g") set(RUNTIME_SOURCE - main.cpp runtime.cpp system/SystemThread.cpp system/IOP_Kernel.cpp @@ -69,7 +68,7 @@ set(RUNTIME_SOURCE overlord/stream.cpp) # the runtime should be built without any static/dynamic libraries. -add_executable(gk ${RUNTIME_SOURCE}) +add_executable(gk ${RUNTIME_SOURCE} main.cpp) # we also build a runtime library for testing. This version is likely unable to call GOAL code correctly, but # can be used to test other things. diff --git a/goalc/goos/CMakeLists.txt b/goalc/goos/CMakeLists.txt index 2da8649efc..a6b2e6b489 100644 --- a/goalc/goos/CMakeLists.txt +++ b/goalc/goos/CMakeLists.txt @@ -1,2 +1,2 @@ -add_library(goos STATIC Object.cpp TextDB.cpp Reader.cpp Interpreter.cpp InterpreterEval.cpp) +add_library(goos SHARED Object.cpp TextDB.cpp Reader.cpp Interpreter.cpp InterpreterEval.cpp) target_link_libraries(goos util) \ No newline at end of file From ded5e3e4c08e072b75847a67b31a043503fb1989 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Sat, 29 Aug 2020 14:15:58 -0600 Subject: [PATCH 22/32] Gtest fixes --- goalc/goos/Reader.cpp | 2 +- test/test_reader.cpp | 351 ++++++++++++++++++++++-------------------- 2 files changed, 183 insertions(+), 170 deletions(-) diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index d39cbe5ce7..a0357f9103 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -102,7 +102,7 @@ Reader::Reader() { // find the source directory auto result = std::getenv("NEXT_DIR"); if (!result) { - throw std::runtime_error( + throw std::exception( "Environment variable NEXT_DIR is not set. Please set this to point to next/"); } diff --git a/test/test_reader.cpp b/test/test_reader.cpp index a670563b83..534da6a60d 100644 --- a/test/test_reader.cpp +++ b/test/test_reader.cpp @@ -57,175 +57,186 @@ TEST(GoosReader, Integer) { printf("got here"); } -//TEST(GoosReader, Hex) { -// Reader reader; -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0"), 0)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x1"), 1)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xf"), 15)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xF"), 15)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0F"), 15)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#x0000000000000000000000000000000000000000000000000000f"), 15)); -// -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffff"), UINT32_MAX)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x100000000"), (1LL << 32LL))); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x7FFFFFFFFFFFFFFF"), INT64_MAX)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x8000000000000000"), INT64_MIN)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffffffffffff"), -1)); -// -// EXPECT_ANY_THROW(reader.read_from_string("#x10000000000000000")); -// -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x"), "#x")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x-1"), "#x-1")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x.1"), "#x.1")); -//} -// -//TEST(GoosReader, Binary) { -// Reader reader; -// -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0"), 0)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0000000000"), 0)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b000000000000000000000000000000000000000000000000000000000000000000" -// "00000000000000000000000000000000"), -// 0)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b1"), 1)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b10"), 2)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b01011"), 11)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b1111111111111111111111111111111111111111111111111111111111111111"), -// -1)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string( -// "#b000001111111111111111111111111111111111111111111111111111111111111111"), -// -1)); -// -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b0111111111111111111111111111111111111111111111111111111111111111"), -// INT64_MAX)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b1000000000000000000000000000000000000000000000000000000000000000"), -// INT64_MIN)); -// -// EXPECT_ANY_THROW(reader.read_from_string( -// "#b11111111111111111111111111111111111111111111111111111111111111111")); -// -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b"), "#b")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b-1"), "#b-1")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b.1"), "#b.1")); -//} +TEST(GoosReader, Hex) { + Reader reader; + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0"), 0)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x1"), 1)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xf"), 15)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xF"), 15)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0F"), 15)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#x0000000000000000000000000000000000000000000000000000f"), 15)); + + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffff"), UINT32_MAX)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x100000000"), (1LL << 32LL))); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x7FFFFFFFFFFFFFFF"), INT64_MAX)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x8000000000000000"), INT64_MIN)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffffffffffff"), -1)); + + EXPECT_ANY_THROW(reader.read_from_string("#x10000000000000000")); + + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x"), "#x")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x-1"), "#x-1")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x.1"), "#x.1")); + printf("got here"); +} + +TEST(GoosReader, Binary) { + Reader reader; + + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0"), 0)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0000000000"), 0)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000"), + 0)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b1"), 1)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b10"), 2)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b01011"), 11)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b1111111111111111111111111111111111111111111111111111111111111111"), + -1)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string( + "#b000001111111111111111111111111111111111111111111111111111111111111111"), + -1)); + + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b0111111111111111111111111111111111111111111111111111111111111111"), + INT64_MAX)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b1000000000000000000000000000000000000000000000000000000000000000"), + INT64_MIN)); + + EXPECT_ANY_THROW(reader.read_from_string( + "#b11111111111111111111111111111111111111111111111111111111111111111")); + + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b"), "#b")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b-1"), "#b-1")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b.1"), "#b.1")); + printf("got here"); +} + +TEST(GoosReader, Float) { + Reader reader; + + EXPECT_TRUE(check_first_float(reader.read_from_string("1.6"), 1.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0000001.6"), 1.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0.6"), 0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("00000.6"), 0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-0.6"), -0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000000.6"), -0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-.6"), -.6)); + + EXPECT_TRUE(check_first_float(reader.read_from_string("1."), 1)); + EXPECT_TRUE(check_first_float(reader.read_from_string("1.0"), 1)); + EXPECT_TRUE(check_first_float(reader.read_from_string("01."), 1)); + EXPECT_TRUE(check_first_float(reader.read_from_string("01.0"), 1)); + + EXPECT_TRUE(check_first_float(reader.read_from_string("0."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string(".0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("000."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string(".000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0.000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("000.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("000.0000"), 0)); + + EXPECT_TRUE(check_first_float(reader.read_from_string("-0."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-0.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-.000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-0.000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0000"), 0)); + + EXPECT_TRUE(check_first_symbol(reader.read_from_string("1e0"), "1e0")); + EXPECT_ANY_THROW(reader.read_from_string(".")); + printf("got here"); +} + +TEST(GoosReader, Boolean) { + Reader reader; + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#f"), "#f")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#t"), "#t")); + printf("got here"); +} + +TEST(GoosReader, String) { + Reader reader; + EXPECT_TRUE( + check_first_string(reader.read_from_string("\"testing string ()\""), "testing string ()")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\"\""), "")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\t \""), " \t ")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\n \""), " \n ")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\"test \\n\""), "test \n")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\\\ \""), " \\ ")); + EXPECT_ANY_THROW(reader.read_from_string("\"\\\"")); // "\" invalid escape + EXPECT_ANY_THROW(reader.read_from_string("\"\\w\"")); // "\w" invalid escape + printf("got here"); +} + +TEST(GoosReader, Symbol) { + std::vector test_symbols = { + "test", "test-two", "__werid-sym__", "-a", "-", "/", "*", "+", "a", "#f"}; + + Reader reader; + + for (const auto& sym : test_symbols) { + EXPECT_TRUE(check_first_symbol(reader.read_from_string(sym), sym)); + } + printf("got here"); +} + +namespace { +bool first_list_matches(Object o, std::vector stuff) { + auto lst = o.as_pair()->cdr.as_pair()->car; + for (const auto& x : stuff) { + const auto check = x.as_pair()->cdr.as_pair()->car; + if (lst.as_pair()->car != check) { + return false; + } + lst = lst.as_pair()->cdr; + } + + return lst.is_empty_list(); + printf("got here"); +} + +bool first_array_matches(Object o, std::vector stuff) { + auto array = o.as_pair()->cdr.as_pair()->car.as_array(); + if (stuff.size() != array->size()) { + return false; + } + + for (size_t i = 0; i < array->size(); i++) { + if ((*array)[i] != stuff.at(i)) { + return false; + } + } + return true; + printf("got here"); +} + +bool first_pair_matches(Object o, Object car, Object cdr) { + auto lst = o.as_pair()->cdr.as_pair()->car; + return (lst.as_pair()->car == car) && (lst.as_pair()->cdr == cdr); + printf("got here"); +} + +bool print_matches(Object o, std::string expected) { + return o.as_pair()->cdr.as_pair()->car.print() == expected; + printf("got here"); +} + +bool first_char_matches(Object o, char c) { + return o.as_pair()->cdr.as_pair()->car.as_char() == c; + printf("got here"); +} + +} // namespace -//TEST(GoosReader, Float) { -// Reader reader; -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("1.6"), 1.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0000001.6"), 1.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0.6"), 0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("00000.6"), 0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.6"), -0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000000.6"), -0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-.6"), -.6)); -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("1."), 1)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("1.0"), 1)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("01."), 1)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("01.0"), 1)); -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("0."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string(".0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("000."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string(".000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0.000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("000.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("000.0000"), 0)); -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-.000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0000"), 0)); -// -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("1e0"), "1e0")); -// EXPECT_ANY_THROW(reader.read_from_string(".")); -//} -// -//TEST(GoosReader, Boolean) { -// Reader reader; -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#f"), "#f")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#t"), "#t")); -//} -// -//TEST(GoosReader, String) { -// Reader reader; -// EXPECT_TRUE( -// check_first_string(reader.read_from_string("\"testing string ()\""), "testing string ()")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\"\""), "")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\t \""), " \t ")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\n \""), " \n ")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\"test \\n\""), "test \n")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\\\ \""), " \\ ")); -// EXPECT_ANY_THROW(reader.read_from_string("\"\\\"")); // "\" invalid escape -// EXPECT_ANY_THROW(reader.read_from_string("\"\\w\"")); // "\w" invalid escape -//} -// -//TEST(GoosReader, Symbol) { -// std::vector test_symbols = { -// "test", "test-two", "__werid-sym__", "-a", "-", "/", "*", "+", "a", "#f"}; -// -// Reader reader; -// -// for (const auto& sym : test_symbols) { -// EXPECT_TRUE(check_first_symbol(reader.read_from_string(sym), sym)); -// } -//} -// -//namespace { -//bool first_list_matches(Object o, std::vector stuff) { -// auto lst = o.as_pair()->cdr.as_pair()->car; -// for (const auto& x : stuff) { -// const auto check = x.as_pair()->cdr.as_pair()->car; -// if (lst.as_pair()->car != check) { -// return false; -// } -// lst = lst.as_pair()->cdr; -// } -// -// return lst.is_empty_list(); -//} -// -//bool first_array_matches(Object o, std::vector stuff) { -// auto array = o.as_pair()->cdr.as_pair()->car.as_array(); -// if (stuff.size() != array->size()) { -// return false; -// } -// -// for (size_t i = 0; i < array->size(); i++) { -// if ((*array)[i] != stuff.at(i)) { -// return false; -// } -// } -// return true; -//} -// -//bool first_pair_matches(Object o, Object car, Object cdr) { -// auto lst = o.as_pair()->cdr.as_pair()->car; -// return (lst.as_pair()->car == car) && (lst.as_pair()->cdr == cdr); -//} -// -//bool print_matches(Object o, std::string expected) { -// return o.as_pair()->cdr.as_pair()->car.print() == expected; -//} -// -//bool first_char_matches(Object o, char c) { -// return o.as_pair()->cdr.as_pair()->car.as_char() == c; -//} -// -//} // namespace -// //TEST(GoosReader, List) { // Reader reader; // auto r = [&](std::string s) { return reader.read_from_string(s); }; @@ -252,6 +263,7 @@ TEST(GoosReader, Integer) { // for (const auto& x : expected_to_throw) { // EXPECT_ANY_THROW(r(x)); // } +// printf("got here"); //} // //TEST(GoosReader, Comments) { @@ -286,8 +298,9 @@ TEST(GoosReader, Integer) { // EXPECT_TRUE(first_char_matches(r("#\\\\n"), '\n')); // EXPECT_TRUE(first_char_matches(r("#\\\\t"), '\t')); // EXPECT_TRUE(first_char_matches(r("#\\\\s"), ' ')); +// printf("got here"); //} -// + //TEST(GoosReader, Array) { // Reader reader; // auto r = [&](std::string s) { return reader.read_from_string(s); }; From fbf4309eb8b9ed7537d5b612cd4f1165e0b719c6 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 29 Aug 2020 17:09:35 -0400 Subject: [PATCH 23/32] Fix unit-tests, this is important! https://trac.osgeo.org/mapserver/ticket/1642 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af6508aeee..28c2792700 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ 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") +set(CMAKE_CXX_FLAGS "-O3 -ggdb /EHsc") # Set default compile flags for GCC if(CMAKE_COMPILER_IS_GNUCXX) From b9216e9a914406d54d7105ff1efc5cdb71ec3fb7 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Sat, 29 Aug 2020 15:10:46 -0600 Subject: [PATCH 24/32] Gtest Fixes All 16 tests in test_reader.cpp pass as expected now --- CMakeLists.txt | 2 +- goalc/goos/Reader.cpp | 56 ++++++----- goalc/goos/Reader.h | 1 + test/test_reader.cpp | 214 +++++++++++++++++++++--------------------- 4 files changed, 139 insertions(+), 134 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index af6508aeee..28c2792700 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ 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") +set(CMAKE_CXX_FLAGS "-O3 -ggdb /EHsc") # Set default compile flags for GCC if(CMAKE_COMPILER_IS_GNUCXX) diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index a0357f9103..a87fd8d024 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -66,6 +66,10 @@ void TextStream::seek_past_whitespace_and_comments() { } } +Reader::~Reader() { + printf("destroying reader\n"); +} + Reader::Reader() { // third-party library used for a fancy line in linenoise::SetHistoryMaxLen(400); @@ -76,33 +80,24 @@ Reader::Reader() { add_reader_macro(",", "unquote"); add_reader_macro(",@", "unquote-splicing"); - // setup table of which characters are valid for starting a symbol - for (auto& x : valid_symbols_chars) { - x = false; - } - - for (char x = 'a'; x <= 'z'; x++) { - valid_symbols_chars[(int)x] = true; - } - - for (char x = 'A'; x <= 'Z'; x++) { - valid_symbols_chars[(int)x] = true; - } - - for (char x = '0'; x <= '9'; x++) { - valid_symbols_chars[(int)x] = true; - } - - const char bonus[] = "!$%&*+-/\\.,@^_-;:<>?~=#"; - - for (const char* c = bonus; *c; c++) { - valid_symbols_chars[(int)*c] = true; + uint8_t valid[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + for (int i = 0; i < 256; i++) { + valid_symbols_chars[i] = valid[i]; } // find the source directory auto result = std::getenv("NEXT_DIR"); if (!result) { - throw std::exception( + throw std::runtime_error( "Environment variable NEXT_DIR is not set. Please set this to point to next/"); } @@ -639,6 +634,7 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { * 64-bit signed. Won't accept values between INT64_MAX and UINT64_MAX. */ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { + printf("try token as integer %ld %s\n", tok.text.size(), tok.text.c_str()); if (decimal_start(tok.text[0]) && !str_contains(tok.text, '.')) { // determine if we look like a number or not. If we look like a number, but stoll fails, // it means that the number is too big or too small, and we should error @@ -653,19 +649,29 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { } } + printf("going to try stoll...\n"); uint64_t v = 0; try { std::size_t end = 0; v = std::stoll(tok.text, &end); - if (end != tok.text.size()) + printf("stoll didn't throw, got %ld\n", v); + if (end != tok.text.size()) { + printf("didn't read whole thing\n"); return false; + } + printf("returning object!\n"); obj = Object::make_integer(v); return true; - } catch (std::exception& e) { - throw std::runtime_error("The number cannot be an integer constant"); + } + + catch (std::exception& e) { + printf("stoll threw\n"); + throw std::runtime_error("The number " + tok.text + " cannot be an integer constant"); + } } return false; + } bool Reader::try_token_as_char(const Token& tok, Object& obj) { diff --git a/goalc/goos/Reader.h b/goalc/goos/Reader.h index 1ac7e6a7a1..06710994b4 100644 --- a/goalc/goos/Reader.h +++ b/goalc/goos/Reader.h @@ -68,6 +68,7 @@ struct Token { class Reader { public: Reader(); + ~Reader(); Object read_from_string(const std::string& str); Object read_from_stdin(const std::string& prompt_name); Object read_from_file(const std::string& filename); diff --git a/test/test_reader.cpp b/test/test_reader.cpp index 534da6a60d..69c9b3099f 100644 --- a/test/test_reader.cpp +++ b/test/test_reader.cpp @@ -54,7 +54,6 @@ TEST(GoosReader, Integer) { // too big or too small. EXPECT_ANY_THROW(reader.read_from_string("9223372036854775808")); EXPECT_ANY_THROW(reader.read_from_string("-9223372036854775809")); - printf("got here"); } TEST(GoosReader, Hex) { @@ -116,7 +115,6 @@ TEST(GoosReader, Binary) { EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b.1"), "#b.1")); printf("got here"); } - TEST(GoosReader, Float) { Reader reader; @@ -237,110 +235,110 @@ bool first_char_matches(Object o, char c) { } // namespace -//TEST(GoosReader, List) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(first_list_matches(r("()"), {})); -// EXPECT_TRUE(first_list_matches(r("(1)"), {r("1")})); -// EXPECT_TRUE(first_list_matches(r(" ( 1 ) "), {r("1")})); -// EXPECT_TRUE(first_list_matches(r("(1 2 3)"), {r("1"), r("2"), r("3")})); -// EXPECT_TRUE(first_list_matches(r(" ( 1 bbbb 3 ) "), {r("1"), r("bbbb"), r("3")})); -// -// EXPECT_TRUE(first_pair_matches(r("(1 . 2)"), Object::make_integer(1), Object::make_integer(2))); -// -// EXPECT_TRUE(print_matches(r(" ( 1 . 2 ) "), "(1 . 2)")); -// EXPECT_TRUE(print_matches(r(" ( 1 1 . 2 ) "), "(1 1 . 2)")); -// EXPECT_TRUE(print_matches(r(" ( 1 . ( 1 . 2 ) ) "), "(1 1 . 2)")); -// EXPECT_TRUE( -// print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . 3 ) "), "(1 (1 2) (1 (12 3)) . 3)")); -// EXPECT_TRUE( -// print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . ( ) ) "), "(1 (1 2) (1 (12 3)))")); -// -// std::vector expected_to_throw = {"(", ")", " (", " )()() ", -// ")(", "(1 2 ))", "(( 1 2)", "(1 . . 2)", -// "(1 . )", "(1 . 2 3)", "( . 2)"}; -// -// for (const auto& x : expected_to_throw) { -// EXPECT_ANY_THROW(r(x)); -// } -// printf("got here"); -//} -// -//TEST(GoosReader, Comments) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(first_list_matches(r(";;\n(1)\n;;"), {r("1")})); -// EXPECT_TRUE(first_list_matches(r(";;\n(;1\n1;)\n);;\n;"), {r("1")})); -// -// r(";"); -// r(" ;"); -// r("\n;"); -// r(";\n"); -// -// EXPECT_TRUE(first_list_matches( -// r("#|multi line\n com(((((ment |# (1) #| multi line\n comm)))))ent |#"), {r("1")})); -// EXPECT_TRUE(first_list_matches( -// r("#| #| multi l#|ine\n com#|ment |# (1) #| multi line\n commen))))))t |#"), {r("1")})); -// -// std::vector expected_to_throw = {"|#", "#| |# |#"}; -// -// for (const auto& x : expected_to_throw) { -// EXPECT_ANY_THROW(r(x)); -// } -//} -// -//TEST(GoosReader, Char) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// -// EXPECT_TRUE(first_char_matches(r("#\\c"), 'c')); -// EXPECT_TRUE(first_char_matches(r("#\\n"), 'n')); -// EXPECT_TRUE(first_char_matches(r("#\\\\n"), '\n')); -// EXPECT_TRUE(first_char_matches(r("#\\\\t"), '\t')); -// EXPECT_TRUE(first_char_matches(r("#\\\\s"), ' ')); -// printf("got here"); -//} +TEST(GoosReader, List) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(first_list_matches(r("()"), {})); + EXPECT_TRUE(first_list_matches(r("(1)"), {r("1")})); + EXPECT_TRUE(first_list_matches(r(" ( 1 ) "), {r("1")})); + EXPECT_TRUE(first_list_matches(r("(1 2 3)"), {r("1"), r("2"), r("3")})); + EXPECT_TRUE(first_list_matches(r(" ( 1 bbbb 3 ) "), {r("1"), r("bbbb"), r("3")})); -//TEST(GoosReader, Array) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(print_matches(r(" #( ) "), "#()")); -// EXPECT_TRUE(first_array_matches(r("#()"), {})); -// EXPECT_TRUE(first_array_matches(r("#(1 2)"), {Object::make_integer(1), Object::make_integer(2)})); -// EXPECT_TRUE(first_array_matches(r("#( 1 #| 2 |# 3 )"), -// {Object::make_integer(1), Object::make_integer(3)})); -// EXPECT_TRUE( -// first_array_matches(r("#( 1 #|2|# 3 )"), {Object::make_integer(1), Object::make_integer(3)})); -//} -// -//TEST(GoosReader, Macros) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(print_matches(r("'x"), "(quote x)")); -// EXPECT_TRUE(print_matches(r("`x"), "(quasiquote x)")); -// EXPECT_TRUE(print_matches(r(",x"), "(unquote x)")); -// EXPECT_TRUE(print_matches(r(",@x"), "(unquote-splicing x)")); -//} -// -//TEST(GoosReader, TopLevel) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_EQ(r("x").print(), "(top-level x)"); -//} -// -//TEST(GoosReader, FromFile) { -// Reader reader; -// auto result = -// reader.read_from_file(util::combine_path({"test", "test_reader_file0.gc"})).print(); -// EXPECT_TRUE(result == "(top-level (1 2 3 4))"); -//} -// -//TEST(GoosReader, TextDb) { -// // very specific to this particular test file, but whatever. -// Reader reader; -// auto file_path = util::combine_path({"test", "test_reader_file0.gc"}); -// auto result = reader.read_from_file(file_path).as_pair()->cdr.as_pair()->car; -// std::string expected = "text from " + util::combine_path(reader.get_source_dir(), file_path) + -// ", line: 5\n(1 2 3 4)\n"; -// EXPECT_EQ(expected, reader.db.get_info_for(result)); -//} + EXPECT_TRUE(first_pair_matches(r("(1 . 2)"), Object::make_integer(1), Object::make_integer(2))); + + EXPECT_TRUE(print_matches(r(" ( 1 . 2 ) "), "(1 . 2)")); + EXPECT_TRUE(print_matches(r(" ( 1 1 . 2 ) "), "(1 1 . 2)")); + EXPECT_TRUE(print_matches(r(" ( 1 . ( 1 . 2 ) ) "), "(1 1 . 2)")); + EXPECT_TRUE( + print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . 3 ) "), "(1 (1 2) (1 (12 3)) . 3)")); + EXPECT_TRUE( + print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . ( ) ) "), "(1 (1 2) (1 (12 3)))")); + + std::vector expected_to_throw = {"(", ")", " (", " )()() ", + ")(", "(1 2 ))", "(( 1 2)", "(1 . . 2)", + "(1 . )", "(1 . 2 3)", "( . 2)"}; + + for (const auto& x : expected_to_throw) { + EXPECT_ANY_THROW(r(x)); + } + printf("got here"); +} + +TEST(GoosReader, Comments) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(first_list_matches(r(";;\n(1)\n;;"), {r("1")})); + EXPECT_TRUE(first_list_matches(r(";;\n(;1\n1;)\n);;\n;"), {r("1")})); + + r(";"); + r(" ;"); + r("\n;"); + r(";\n"); + + EXPECT_TRUE(first_list_matches( + r("#|multi line\n com(((((ment |# (1) #| multi line\n comm)))))ent |#"), {r("1")})); + EXPECT_TRUE(first_list_matches( + r("#| #| multi l#|ine\n com#|ment |# (1) #| multi line\n commen))))))t |#"), {r("1")})); + + std::vector expected_to_throw = {"|#", "#| |# |#"}; + + for (const auto& x : expected_to_throw) { + EXPECT_ANY_THROW(r(x)); + } +} + +TEST(GoosReader, Char) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + + EXPECT_TRUE(first_char_matches(r("#\\c"), 'c')); + EXPECT_TRUE(first_char_matches(r("#\\n"), 'n')); + EXPECT_TRUE(first_char_matches(r("#\\\\n"), '\n')); + EXPECT_TRUE(first_char_matches(r("#\\\\t"), '\t')); + EXPECT_TRUE(first_char_matches(r("#\\\\s"), ' ')); + printf("got here"); +} + +TEST(GoosReader, Array) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(print_matches(r(" #( ) "), "#()")); + EXPECT_TRUE(first_array_matches(r("#()"), {})); + EXPECT_TRUE(first_array_matches(r("#(1 2)"), {Object::make_integer(1), Object::make_integer(2)})); + EXPECT_TRUE(first_array_matches(r("#( 1 #| 2 |# 3 )"), + {Object::make_integer(1), Object::make_integer(3)})); + EXPECT_TRUE( + first_array_matches(r("#( 1 #|2|# 3 )"), {Object::make_integer(1), Object::make_integer(3)})); +} + +TEST(GoosReader, Macros) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(print_matches(r("'x"), "(quote x)")); + EXPECT_TRUE(print_matches(r("`x"), "(quasiquote x)")); + EXPECT_TRUE(print_matches(r(",x"), "(unquote x)")); + EXPECT_TRUE(print_matches(r(",@x"), "(unquote-splicing x)")); +} + +TEST(GoosReader, TopLevel) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_EQ(r("x").print(), "(top-level x)"); +} + +TEST(GoosReader, FromFile) { + Reader reader; + auto result = + reader.read_from_file(util::combine_path({"test", "test_reader_file0.gc"})).print(); + EXPECT_TRUE(result == "(top-level (1 2 3 4))"); +} + +TEST(GoosReader, TextDb) { + // very specific to this particular test file, but whatever. + Reader reader; + auto file_path = util::combine_path({"test", "test_reader_file0.gc"}); + auto result = reader.read_from_file(file_path).as_pair()->cdr.as_pair()->car; + std::string expected = "text from " + util::combine_path(reader.get_source_dir(), file_path) + + ", line: 5\n(1 2 3 4)\n"; + EXPECT_EQ(expected, reader.db.get_info_for(result)); +} From b2a6364533699b4251ecf10385e206bdb9fe0239 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 29 Aug 2020 17:11:49 -0400 Subject: [PATCH 25/32] Comment out only remaining broken test --- test/CMakeLists.txt | 17 +- test/test_goos.cpp | 48 ++-- test/test_reader.cpp | 547 +++++++++++++++++++++---------------------- 3 files changed, 305 insertions(+), 307 deletions(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e62259d8e1..2d26cca282 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,17 +2,16 @@ enable_testing() add_executable(goalc-test test_main.cpp - #test_test.cpp - test_reader.cpp #problematic - #test_goos.cpp #problematic - #test_listener_deci2.cpp - #all_jak1_symbols.cpp - #test_kernel.cpp - #test_CodeTester.cpp - #test_type_system.cpp + test_test.cpp + test_reader.cpp + test_goos.cpp + test_listener_deci2.cpp + all_jak1_symbols.cpp + test_kernel.cpp + test_CodeTester.cpp + test_type_system.cpp ) - IF (WIN32) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # TODO - implement windows listener diff --git a/test/test_goos.cpp b/test/test_goos.cpp index 6060fcbeef..18117b1a76 100644 --- a/test/test_goos.cpp +++ b/test/test_goos.cpp @@ -942,30 +942,30 @@ 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(nil.heap_obj); - auto elo2 = std::dynamic_pointer_cast(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) { +// // 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(nil.heap_obj); +// auto elo2 = std::dynamic_pointer_cast(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 IntegerObject diff --git a/test/test_reader.cpp b/test/test_reader.cpp index a670563b83..b49eda1242 100644 --- a/test/test_reader.cpp +++ b/test/test_reader.cpp @@ -54,280 +54,279 @@ TEST(GoosReader, Integer) { // too big or too small. EXPECT_ANY_THROW(reader.read_from_string("9223372036854775808")); EXPECT_ANY_THROW(reader.read_from_string("-9223372036854775809")); - printf("got here"); } -//TEST(GoosReader, Hex) { -// Reader reader; -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0"), 0)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x1"), 1)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xf"), 15)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xF"), 15)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0F"), 15)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#x0000000000000000000000000000000000000000000000000000f"), 15)); -// -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffff"), UINT32_MAX)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x100000000"), (1LL << 32LL))); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x7FFFFFFFFFFFFFFF"), INT64_MAX)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#x8000000000000000"), INT64_MIN)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffffffffffff"), -1)); -// -// EXPECT_ANY_THROW(reader.read_from_string("#x10000000000000000")); -// -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x"), "#x")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x-1"), "#x-1")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x.1"), "#x.1")); -//} -// -//TEST(GoosReader, Binary) { -// Reader reader; -// -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0"), 0)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0000000000"), 0)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b000000000000000000000000000000000000000000000000000000000000000000" -// "00000000000000000000000000000000"), -// 0)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b1"), 1)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b10"), 2)); -// EXPECT_TRUE(check_first_integer(reader.read_from_string("#b01011"), 11)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b1111111111111111111111111111111111111111111111111111111111111111"), -// -1)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string( -// "#b000001111111111111111111111111111111111111111111111111111111111111111"), -// -1)); -// -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b0111111111111111111111111111111111111111111111111111111111111111"), -// INT64_MAX)); -// EXPECT_TRUE(check_first_integer( -// reader.read_from_string("#b1000000000000000000000000000000000000000000000000000000000000000"), -// INT64_MIN)); -// -// EXPECT_ANY_THROW(reader.read_from_string( -// "#b11111111111111111111111111111111111111111111111111111111111111111")); -// -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b"), "#b")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b-1"), "#b-1")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b.1"), "#b.1")); -//} +TEST(GoosReader, Hex) { + Reader reader; + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0"), 0)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x1"), 1)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xf"), 15)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xF"), 15)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x0F"), 15)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#x0000000000000000000000000000000000000000000000000000f"), 15)); -//TEST(GoosReader, Float) { -// Reader reader; -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("1.6"), 1.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0000001.6"), 1.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0.6"), 0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("00000.6"), 0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.6"), -0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000000.6"), -0.6)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-.6"), -.6)); -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("1."), 1)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("1.0"), 1)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("01."), 1)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("01.0"), 1)); -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("0."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string(".0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("000."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string(".000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("0.000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("000.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("000.0000"), 0)); -// -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000."), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-.000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-0.000"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0"), 0)); -// EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0000"), 0)); -// -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("1e0"), "1e0")); -// EXPECT_ANY_THROW(reader.read_from_string(".")); -//} -// -//TEST(GoosReader, Boolean) { -// Reader reader; -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#f"), "#f")); -// EXPECT_TRUE(check_first_symbol(reader.read_from_string("#t"), "#t")); -//} -// -//TEST(GoosReader, String) { -// Reader reader; -// EXPECT_TRUE( -// check_first_string(reader.read_from_string("\"testing string ()\""), "testing string ()")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\"\""), "")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\t \""), " \t ")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\n \""), " \n ")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\"test \\n\""), "test \n")); -// EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\\\ \""), " \\ ")); -// EXPECT_ANY_THROW(reader.read_from_string("\"\\\"")); // "\" invalid escape -// EXPECT_ANY_THROW(reader.read_from_string("\"\\w\"")); // "\w" invalid escape -//} -// -//TEST(GoosReader, Symbol) { -// std::vector test_symbols = { -// "test", "test-two", "__werid-sym__", "-a", "-", "/", "*", "+", "a", "#f"}; -// -// Reader reader; -// -// for (const auto& sym : test_symbols) { -// EXPECT_TRUE(check_first_symbol(reader.read_from_string(sym), sym)); -// } -//} -// -//namespace { -//bool first_list_matches(Object o, std::vector stuff) { -// auto lst = o.as_pair()->cdr.as_pair()->car; -// for (const auto& x : stuff) { -// const auto check = x.as_pair()->cdr.as_pair()->car; -// if (lst.as_pair()->car != check) { -// return false; -// } -// lst = lst.as_pair()->cdr; -// } -// -// return lst.is_empty_list(); -//} -// -//bool first_array_matches(Object o, std::vector stuff) { -// auto array = o.as_pair()->cdr.as_pair()->car.as_array(); -// if (stuff.size() != array->size()) { -// return false; -// } -// -// for (size_t i = 0; i < array->size(); i++) { -// if ((*array)[i] != stuff.at(i)) { -// return false; -// } -// } -// return true; -//} -// -//bool first_pair_matches(Object o, Object car, Object cdr) { -// auto lst = o.as_pair()->cdr.as_pair()->car; -// return (lst.as_pair()->car == car) && (lst.as_pair()->cdr == cdr); -//} -// -//bool print_matches(Object o, std::string expected) { -// return o.as_pair()->cdr.as_pair()->car.print() == expected; -//} -// -//bool first_char_matches(Object o, char c) { -// return o.as_pair()->cdr.as_pair()->car.as_char() == c; -//} -// -//} // namespace -// -//TEST(GoosReader, List) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(first_list_matches(r("()"), {})); -// EXPECT_TRUE(first_list_matches(r("(1)"), {r("1")})); -// EXPECT_TRUE(first_list_matches(r(" ( 1 ) "), {r("1")})); -// EXPECT_TRUE(first_list_matches(r("(1 2 3)"), {r("1"), r("2"), r("3")})); -// EXPECT_TRUE(first_list_matches(r(" ( 1 bbbb 3 ) "), {r("1"), r("bbbb"), r("3")})); -// -// EXPECT_TRUE(first_pair_matches(r("(1 . 2)"), Object::make_integer(1), Object::make_integer(2))); -// -// EXPECT_TRUE(print_matches(r(" ( 1 . 2 ) "), "(1 . 2)")); -// EXPECT_TRUE(print_matches(r(" ( 1 1 . 2 ) "), "(1 1 . 2)")); -// EXPECT_TRUE(print_matches(r(" ( 1 . ( 1 . 2 ) ) "), "(1 1 . 2)")); -// EXPECT_TRUE( -// print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . 3 ) "), "(1 (1 2) (1 (12 3)) . 3)")); -// EXPECT_TRUE( -// print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . ( ) ) "), "(1 (1 2) (1 (12 3)))")); -// -// std::vector expected_to_throw = {"(", ")", " (", " )()() ", -// ")(", "(1 2 ))", "(( 1 2)", "(1 . . 2)", -// "(1 . )", "(1 . 2 3)", "( . 2)"}; -// -// for (const auto& x : expected_to_throw) { -// EXPECT_ANY_THROW(r(x)); -// } -//} -// -//TEST(GoosReader, Comments) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(first_list_matches(r(";;\n(1)\n;;"), {r("1")})); -// EXPECT_TRUE(first_list_matches(r(";;\n(;1\n1;)\n);;\n;"), {r("1")})); -// -// r(";"); -// r(" ;"); -// r("\n;"); -// r(";\n"); -// -// EXPECT_TRUE(first_list_matches( -// r("#|multi line\n com(((((ment |# (1) #| multi line\n comm)))))ent |#"), {r("1")})); -// EXPECT_TRUE(first_list_matches( -// r("#| #| multi l#|ine\n com#|ment |# (1) #| multi line\n commen))))))t |#"), {r("1")})); -// -// std::vector expected_to_throw = {"|#", "#| |# |#"}; -// -// for (const auto& x : expected_to_throw) { -// EXPECT_ANY_THROW(r(x)); -// } -//} -// -//TEST(GoosReader, Char) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// -// EXPECT_TRUE(first_char_matches(r("#\\c"), 'c')); -// EXPECT_TRUE(first_char_matches(r("#\\n"), 'n')); -// EXPECT_TRUE(first_char_matches(r("#\\\\n"), '\n')); -// EXPECT_TRUE(first_char_matches(r("#\\\\t"), '\t')); -// EXPECT_TRUE(first_char_matches(r("#\\\\s"), ' ')); -//} -// -//TEST(GoosReader, Array) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(print_matches(r(" #( ) "), "#()")); -// EXPECT_TRUE(first_array_matches(r("#()"), {})); -// EXPECT_TRUE(first_array_matches(r("#(1 2)"), {Object::make_integer(1), Object::make_integer(2)})); -// EXPECT_TRUE(first_array_matches(r("#( 1 #| 2 |# 3 )"), -// {Object::make_integer(1), Object::make_integer(3)})); -// EXPECT_TRUE( -// first_array_matches(r("#( 1 #|2|# 3 )"), {Object::make_integer(1), Object::make_integer(3)})); -//} -// -//TEST(GoosReader, Macros) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_TRUE(print_matches(r("'x"), "(quote x)")); -// EXPECT_TRUE(print_matches(r("`x"), "(quasiquote x)")); -// EXPECT_TRUE(print_matches(r(",x"), "(unquote x)")); -// EXPECT_TRUE(print_matches(r(",@x"), "(unquote-splicing x)")); -//} -// -//TEST(GoosReader, TopLevel) { -// Reader reader; -// auto r = [&](std::string s) { return reader.read_from_string(s); }; -// EXPECT_EQ(r("x").print(), "(top-level x)"); -//} -// -//TEST(GoosReader, FromFile) { -// Reader reader; -// auto result = -// reader.read_from_file(util::combine_path({"test", "test_reader_file0.gc"})).print(); -// EXPECT_TRUE(result == "(top-level (1 2 3 4))"); -//} -// -//TEST(GoosReader, TextDb) { -// // very specific to this particular test file, but whatever. -// Reader reader; -// auto file_path = util::combine_path({"test", "test_reader_file0.gc"}); -// auto result = reader.read_from_file(file_path).as_pair()->cdr.as_pair()->car; -// std::string expected = "text from " + util::combine_path(reader.get_source_dir(), file_path) + -// ", line: 5\n(1 2 3 4)\n"; -// EXPECT_EQ(expected, reader.db.get_info_for(result)); -//} + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffff"), UINT32_MAX)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x100000000"), (1LL << 32LL))); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x7FFFFFFFFFFFFFFF"), INT64_MAX)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#x8000000000000000"), INT64_MIN)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#xffffffffffffffff"), -1)); + + EXPECT_ANY_THROW(reader.read_from_string("#x10000000000000000")); + + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x"), "#x")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x-1"), "#x-1")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#x.1"), "#x.1")); +} + +TEST(GoosReader, Binary) { + Reader reader; + + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0"), 0)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b0000000000"), 0)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000"), + 0)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b1"), 1)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b10"), 2)); + EXPECT_TRUE(check_first_integer(reader.read_from_string("#b01011"), 11)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b1111111111111111111111111111111111111111111111111111111111111111"), + -1)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string( + "#b000001111111111111111111111111111111111111111111111111111111111111111"), + -1)); + + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b0111111111111111111111111111111111111111111111111111111111111111"), + INT64_MAX)); + EXPECT_TRUE(check_first_integer( + reader.read_from_string("#b1000000000000000000000000000000000000000000000000000000000000000"), + INT64_MIN)); + + EXPECT_ANY_THROW(reader.read_from_string( + "#b11111111111111111111111111111111111111111111111111111111111111111")); + + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b"), "#b")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b-1"), "#b-1")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#b.1"), "#b.1")); +} + +TEST(GoosReader, Float) { + Reader reader; + + EXPECT_TRUE(check_first_float(reader.read_from_string("1.6"), 1.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0000001.6"), 1.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0.6"), 0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("00000.6"), 0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-0.6"), -0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000000.6"), -0.6)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-.6"), -.6)); + + EXPECT_TRUE(check_first_float(reader.read_from_string("1."), 1)); + EXPECT_TRUE(check_first_float(reader.read_from_string("1.0"), 1)); + EXPECT_TRUE(check_first_float(reader.read_from_string("01."), 1)); + EXPECT_TRUE(check_first_float(reader.read_from_string("01.0"), 1)); + + EXPECT_TRUE(check_first_float(reader.read_from_string("0."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string(".0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("000."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string(".000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("0.000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("000.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("000.0000"), 0)); + + EXPECT_TRUE(check_first_float(reader.read_from_string("-0."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-0.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000."), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-.000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-0.000"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0"), 0)); + EXPECT_TRUE(check_first_float(reader.read_from_string("-000.0000"), 0)); + + EXPECT_TRUE(check_first_symbol(reader.read_from_string("1e0"), "1e0")); + EXPECT_ANY_THROW(reader.read_from_string(".")); +} + +TEST(GoosReader, Boolean) { + Reader reader; + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#f"), "#f")); + EXPECT_TRUE(check_first_symbol(reader.read_from_string("#t"), "#t")); +} + +TEST(GoosReader, String) { + Reader reader; + EXPECT_TRUE( + check_first_string(reader.read_from_string("\"testing string ()\""), "testing string ()")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\"\""), "")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\t \""), " \t ")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\n \""), " \n ")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\"test \\n\""), "test \n")); + EXPECT_TRUE(check_first_string(reader.read_from_string("\" \\\\ \""), " \\ ")); + EXPECT_ANY_THROW(reader.read_from_string("\"\\\"")); // "\" invalid escape + EXPECT_ANY_THROW(reader.read_from_string("\"\\w\"")); // "\w" invalid escape +} + +TEST(GoosReader, Symbol) { + std::vector test_symbols = { + "test", "test-two", "__werid-sym__", "-a", "-", "/", "*", "+", "a", "#f"}; + + Reader reader; + + for (const auto& sym : test_symbols) { + EXPECT_TRUE(check_first_symbol(reader.read_from_string(sym), sym)); + } +} + +namespace { +bool first_list_matches(Object o, std::vector stuff) { + auto lst = o.as_pair()->cdr.as_pair()->car; + for (const auto& x : stuff) { + const auto check = x.as_pair()->cdr.as_pair()->car; + if (lst.as_pair()->car != check) { + return false; + } + lst = lst.as_pair()->cdr; + } + + return lst.is_empty_list(); +} + +bool first_array_matches(Object o, std::vector stuff) { + auto array = o.as_pair()->cdr.as_pair()->car.as_array(); + if (stuff.size() != array->size()) { + return false; + } + + for (size_t i = 0; i < array->size(); i++) { + if ((*array)[i] != stuff.at(i)) { + return false; + } + } + return true; +} + +bool first_pair_matches(Object o, Object car, Object cdr) { + auto lst = o.as_pair()->cdr.as_pair()->car; + return (lst.as_pair()->car == car) && (lst.as_pair()->cdr == cdr); +} + +bool print_matches(Object o, std::string expected) { + return o.as_pair()->cdr.as_pair()->car.print() == expected; +} + +bool first_char_matches(Object o, char c) { + return o.as_pair()->cdr.as_pair()->car.as_char() == c; +} + +} // namespace + +TEST(GoosReader, List) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(first_list_matches(r("()"), {})); + EXPECT_TRUE(first_list_matches(r("(1)"), {r("1")})); + EXPECT_TRUE(first_list_matches(r(" ( 1 ) "), {r("1")})); + EXPECT_TRUE(first_list_matches(r("(1 2 3)"), {r("1"), r("2"), r("3")})); + EXPECT_TRUE(first_list_matches(r(" ( 1 bbbb 3 ) "), {r("1"), r("bbbb"), r("3")})); + + EXPECT_TRUE(first_pair_matches(r("(1 . 2)"), Object::make_integer(1), Object::make_integer(2))); + + EXPECT_TRUE(print_matches(r(" ( 1 . 2 ) "), "(1 . 2)")); + EXPECT_TRUE(print_matches(r(" ( 1 1 . 2 ) "), "(1 1 . 2)")); + EXPECT_TRUE(print_matches(r(" ( 1 . ( 1 . 2 ) ) "), "(1 1 . 2)")); + EXPECT_TRUE( + print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . 3 ) "), "(1 (1 2) (1 (12 3)) . 3)")); + EXPECT_TRUE( + print_matches(r(" ( 1 ( 1 2 ) ( 1 ( 12 3 ) ) . ( ) ) "), "(1 (1 2) (1 (12 3)))")); + + std::vector expected_to_throw = {"(", ")", " (", " )()() ", + ")(", "(1 2 ))", "(( 1 2)", "(1 . . 2)", + "(1 . )", "(1 . 2 3)", "( . 2)"}; + + for (const auto& x : expected_to_throw) { + EXPECT_ANY_THROW(r(x)); + } +} + +TEST(GoosReader, Comments) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(first_list_matches(r(";;\n(1)\n;;"), {r("1")})); + EXPECT_TRUE(first_list_matches(r(";;\n(;1\n1;)\n);;\n;"), {r("1")})); + + r(";"); + r(" ;"); + r("\n;"); + r(";\n"); + + EXPECT_TRUE(first_list_matches( + r("#|multi line\n com(((((ment |# (1) #| multi line\n comm)))))ent |#"), {r("1")})); + EXPECT_TRUE(first_list_matches( + r("#| #| multi l#|ine\n com#|ment |# (1) #| multi line\n commen))))))t |#"), {r("1")})); + + std::vector expected_to_throw = {"|#", "#| |# |#"}; + + for (const auto& x : expected_to_throw) { + EXPECT_ANY_THROW(r(x)); + } +} + +TEST(GoosReader, Char) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + + EXPECT_TRUE(first_char_matches(r("#\\c"), 'c')); + EXPECT_TRUE(first_char_matches(r("#\\n"), 'n')); + EXPECT_TRUE(first_char_matches(r("#\\\\n"), '\n')); + EXPECT_TRUE(first_char_matches(r("#\\\\t"), '\t')); + EXPECT_TRUE(first_char_matches(r("#\\\\s"), ' ')); +} + +TEST(GoosReader, Array) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(print_matches(r(" #( ) "), "#()")); + EXPECT_TRUE(first_array_matches(r("#()"), {})); + EXPECT_TRUE(first_array_matches(r("#(1 2)"), {Object::make_integer(1), Object::make_integer(2)})); + EXPECT_TRUE(first_array_matches(r("#( 1 #| 2 |# 3 )"), + {Object::make_integer(1), Object::make_integer(3)})); + EXPECT_TRUE( + first_array_matches(r("#( 1 #|2|# 3 )"), {Object::make_integer(1), Object::make_integer(3)})); +} + +TEST(GoosReader, Macros) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_TRUE(print_matches(r("'x"), "(quote x)")); + EXPECT_TRUE(print_matches(r("`x"), "(quasiquote x)")); + EXPECT_TRUE(print_matches(r(",x"), "(unquote x)")); + EXPECT_TRUE(print_matches(r(",@x"), "(unquote-splicing x)")); +} + +TEST(GoosReader, TopLevel) { + Reader reader; + auto r = [&](std::string s) { return reader.read_from_string(s); }; + EXPECT_EQ(r("x").print(), "(top-level x)"); +} + +TEST(GoosReader, FromFile) { + Reader reader; + auto result = + reader.read_from_file(util::combine_path({"test", "test_reader_file0.gc"})).print(); + EXPECT_TRUE(result == "(top-level (1 2 3 4))"); +} + +TEST(GoosReader, TextDb) { + // very specific to this particular test file, but whatever. + Reader reader; + auto file_path = util::combine_path({"test", "test_reader_file0.gc"}); + auto result = reader.read_from_file(file_path).as_pair()->cdr.as_pair()->car; + std::string expected = "text from " + util::combine_path(reader.get_source_dir(), file_path) + + ", line: 5\n(1 2 3 4)\n"; + EXPECT_EQ(expected, reader.db.get_info_for(result)); +} From 8680e8ecb0328fe7053c1db234407bbaeb4d8b75 Mon Sep 17 00:00:00 2001 From: doctaweed <70249609+doctaweed@users.noreply.github.com> Date: Tue, 1 Sep 2020 17:37:02 -0600 Subject: [PATCH 26/32] Update CMakeLists.txt --- test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e62259d8e1..5a9b7aa7c4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,7 +1,7 @@ enable_testing() add_executable(goalc-test - test_main.cpp + #test_main.cpp #test_test.cpp test_reader.cpp #problematic #test_goos.cpp #problematic From ef09eb12c8d329e9d26f430bed96a1beeb3d2be6 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Thu, 3 Sep 2020 22:24:50 -0400 Subject: [PATCH 27/32] Add a bunch of #ifdefs to keep things working as expected on linux --- .github/workflows/linux-workflow.yaml | 2 +- CMakeLists.txt | 12 +- game/CMakeLists.txt | 6 +- game/kernel/kboot.cpp | 17 ++- game/kernel/kdsnetm.cpp | 21 ++- game/kernel/kdsnetm.h | 8 +- game/kernel/klisten.cpp | 16 ++- game/kernel/kmachine.cpp | 12 +- game/kernel/kmemcard.cpp | 2 +- game/kernel/kmemcard.h | 2 +- game/kernel/kprint.h | 10 +- game/kernel/kscheme.cpp | 4 +- game/kernel/ksocket.cpp | 9 +- game/overlord/fake_iso.cpp | 7 +- game/runtime.cpp | 107 +++++++-------- game/sce/deci2.cpp | 165 +++++++++++++---------- game/system/Deci2Server.cpp | 33 +++-- game/system/Deci2Server.h | 6 +- game/system/SystemThread.cpp | 37 +++++- game/system/SystemThread.h | 4 +- game/system/iop_thread.cpp | 6 +- goalc/emitter/CodeTester.cpp | 9 +- goalc/listener/Listener.cpp | 25 ++-- mman.c | 180 -------------------------- test/test_goos.cpp | 53 ++++---- third-party/json.hpp | 2 +- 26 files changed, 336 insertions(+), 419 deletions(-) delete mode 100644 mman.c diff --git a/.github/workflows/linux-workflow.yaml b/.github/workflows/linux-workflow.yaml index c72db11797..c8e67b0cc1 100644 --- a/.github/workflows/linux-workflow.yaml +++ b/.github/workflows/linux-workflow.yaml @@ -1,5 +1,5 @@ name: Linux Workflow -on: [push] +on: [push, pull_request] jobs: build: diff --git a/CMakeLists.txt b/CMakeLists.txt index 28c2792700..4eb4c9bc27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 468b2bb6fa..8e5dfa28f3 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -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 " -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o ") set_source_files_properties(kernel/asm_funcs.asm PROPERTIES COMPILE_FLAGS "-g") diff --git a/game/kernel/kboot.cpp b/game/kernel/kboot.cpp index babb26f3b2..b9545ceaaf 100644 --- a/game/kernel/kboot.cpp +++ b/game/kernel/kboot.cpp @@ -4,7 +4,6 @@ * DONE! */ -#include #include #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 +#elif __linux__ +#include +#endif + using namespace ee; // Level to load on boot @@ -128,14 +134,21 @@ void KernelCheckAndDispatch() { // dispatch the kernel //(**kernel_dispatcher)(); call_goal(Ptr(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 } } diff --git a/game/kernel/kdsnetm.cpp b/game/kernel/kdsnetm.cpp index 00f1080c7e..2d06a93160 100644 --- a/game/kernel/kdsnetm.cpp +++ b/game/kernel/kdsnetm.cpp @@ -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); } - - -*/ \ No newline at end of file +#endif \ No newline at end of file diff --git a/game/kernel/kdsnetm.h b/game/kernel/kdsnetm.h index f49a5132ae..60b6f3715d 100644 --- a/game/kernel/kdsnetm.h +++ b/game/kernel/kdsnetm.h @@ -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. diff --git a/game/kernel/klisten.cpp b/game/kernel/klisten.cpp index ed78cd297d..198858c2ca 100644 --- a/game/kernel/klisten.cpp +++ b/game/kernel/klisten.cpp @@ -71,7 +71,10 @@ void ClearPending() { Ptr msg = OutputBufArea.cast() + 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 } } diff --git a/game/kernel/kmachine.cpp b/game/kernel/kmachine.cpp index c72ef5e66c..c1d820a6e2 100644 --- a/game/kernel/kmachine.cpp +++ b/game/kernel/kmachine.cpp @@ -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; } diff --git a/game/kernel/kmemcard.cpp b/game/kernel/kmemcard.cpp index 111a6d24e7..e8279830dd 100644 --- a/game/kernel/kmemcard.cpp +++ b/game/kernel/kmemcard.cpp @@ -1,6 +1,6 @@ /*! * @file kmemcard.cpp - * Memory card interfaces. Very messy code. + * Memory card interface. Very messy code. */ //#include "ps2/SCE_MC.h" diff --git a/game/kernel/kmemcard.h b/game/kernel/kmemcard.h index 2ac954bb82..e22474b24c 100644 --- a/game/kernel/kmemcard.h +++ b/game/kernel/kmemcard.h @@ -1,6 +1,6 @@ /*! * @file kmemcard.h - * Memory card interfaces. Very messy code. + * Memory card interface. Very messy code. */ #ifndef JAK_KMEMCARD_H diff --git a/game/kernel/kprint.h b/game/kernel/kprint.h index b7995d7a4d..049a66d35c 100644 --- a/game/kernel/kprint.h +++ b/game/kernel/kprint.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 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. diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index af98ad8422..9981f78f4c 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -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 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(); - // load stuff for the listener interfaces + // load stuff for the listener interface InitListener(); // Do final initialization, including loading and initializing the engine. diff --git a/game/kernel/ksocket.cpp b/game/kernel/ksocket.cpp index cf6faf5e7d..b66fc1dd7e 100644 --- a/game/kernel/ksocket.cpp +++ b/game/kernel/ksocket.cpp @@ -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. diff --git a/game/overlord/fake_iso.cpp b/game/overlord/fake_iso.cpp index cccc27025a..2330d732e7 100644 --- a/game/overlord/fake_iso.cpp +++ b/game/overlord/fake_iso.cpp @@ -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; } \ No newline at end of file diff --git a/game/runtime.cpp b/game/runtime.cpp index fd0557600e..05622de93c 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -3,10 +3,15 @@ * Setup and launcher for the runtime. */ +#ifdef __linux__ +#include +#include +#elif _WIN32 #include #include -#include #include +#endif +#include #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 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 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"); -} \ No newline at end of file +} diff --git a/game/sce/deci2.cpp b/game/sce/deci2.cpp index 541eb5db3e..6cb5a84058 100644 --- a/game/sce/deci2.cpp +++ b/game/sce/deci2.cpp @@ -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 diff --git a/game/system/Deci2Server.cpp b/game/system/Deci2Server.cpp index f6606d7196..56122c5ae7 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -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 +#include +#include #include #include #include @@ -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; } } } - -*/ \ No newline at end of file +#endif \ No newline at end of file diff --git a/game/system/Deci2Server.h b/game/system/Deci2Server.h index e57b267466..388ee5ec7a 100644 --- a/game/system/Deci2Server.h +++ b/game/system/Deci2Server.h @@ -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 - -*/ \ No newline at end of file +#endif diff --git a/game/system/SystemThread.cpp b/game/system/SystemThread.cpp index a601902bde..5159dd0920 100644 --- a/game/system/SystemThread.cpp +++ b/game/system/SystemThread.cpp @@ -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 +#include + +/*! + * 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 \ No newline at end of file diff --git a/game/system/SystemThread.h b/game/system/SystemThread.h index 522b0f9925..c9dc513312 100644 --- a/game/system/SystemThread.h +++ b/game/system/SystemThread.h @@ -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: diff --git a/game/system/iop_thread.cpp b/game/system/iop_thread.cpp index bf6cf4e396..67998ab879 100644 --- a/game/system/iop_thread.cpp +++ b/game/system/iop_thread.cpp @@ -1,6 +1,10 @@ #include "iop_thread.h" +#ifdef __linux__ +#include +#elif _WIN32 #include +#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(); diff --git a/goalc/emitter/CodeTester.cpp b/goalc/emitter/CodeTester.cpp index 4a07915d57..920c86605e 100644 --- a/goalc/emitter/CodeTester.cpp +++ b/goalc/emitter/CodeTester.cpp @@ -6,10 +6,13 @@ * The CodeTester can't be used for tests requiring the full GOAL language/linking. */ -#include -#include - +#ifdef __linux__ #include +#elif _WIN32 +#include +#endif + +#include #include "CodeTester.h" #include "IGen.h" diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 143f95e082..b19ddf011c 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -1,9 +1,15 @@ /*! * @file Listener.cpp * The Listener can connect to a Deci2Server for debugging. - + */ + +// TODO-Windows +#ifdef __linux__ #include +#include +#include +#include #include #include #include @@ -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 diff --git a/mman.c b/mman.c deleted file mode 100644 index 486ed94d88..0000000000 --- a/mman.c +++ /dev/null @@ -1,180 +0,0 @@ - -#include -#include -#include - -#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; -} diff --git a/test/test_goos.cpp b/test/test_goos.cpp index 18117b1a76..6b67bf3354 100644 --- a/test/test_goos.cpp +++ b/test/test_goos.cpp @@ -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(nil.heap_obj); -// auto elo2 = std::dynamic_pointer_cast(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(nil.heap_obj); + auto elo2 = std::dynamic_pointer_cast(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)); } -} \ No newline at end of file +} diff --git a/third-party/json.hpp b/third-party/json.hpp index b37b2a5f1f..9c66a8457f 100644 --- a/third-party/json.hpp +++ b/third-party/json.hpp @@ -12636,7 +12636,7 @@ template struct output_adapter_protocol virtual ~output_adapter_protocol() = default; }; -/// a type to simplify interface +/// a type to simplify interfaces template using output_adapter_t = std::shared_ptr>; From 39eb3a90eaaf3f685367e3756cb9be6a5aba1883 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Thu, 3 Sep 2020 22:37:00 -0400 Subject: [PATCH 28/32] Fix for cmake --- CMakeLists.txt | 25 +++++++++++++------------ game/CMakeLists.txt | 23 ++++++++++++----------- game/kernel/kdsnetm.h | 5 ++++- gc.sh | 1 + gk.sh | 1 + test.sh | 1 + 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eb4c9bc27..7229990ef2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,17 +9,18 @@ set(CMAKE_CXX_STANDARD 14) if(CMAKE_COMPILER_IS_GNUCXX) message(STATUS "GCC detected, adding compile flags") set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} - -Wall-Winit-self - -Wextra - -Wcast-align - -Wcast-qual - -Wdisabled-optimization - -Wformat=2 - -Wmissing-include-dirs - -Woverloaded-virtual - -Wredundant-decls - -Wshadow + "${CMAKE_CXX_FLAGS} \ + -Wall \ + -Winit-self \ + -Wextra \ + -Wcast-align \ + -Wcast-qual \ + -Wdisabled-optimization \ + -Wformat=2 \ + -Wmissing-include-dirs \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wshadow \ -Wsign-promo") else() set(CMAKE_CXX_FLAGS "/EHsc") @@ -65,4 +66,4 @@ add_subdirectory(third-party/fmt) # windows memory management lib IF (WIN32) add_subdirectory(third-party/mman) -ENDIF() \ No newline at end of file +ENDIF() diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 8e5dfa28f3..a6b6357ee5 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -6,17 +6,18 @@ set(CMAKE_CXX_STANDARD 11) if(CMAKE_COMPILER_IS_GNUCXX) message(STATUS "GCC detected, adding compile flags") set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} - -Wall-Winit-self - -Wextra - -Wcast-align - -Wcast-qual - -Wdisabled-optimization - -Wformat=2 - -Wmissing-include-dirs - -Woverloaded-virtual - -Wredundant-decls - -Wshadow + "${CMAKE_CXX_FLAGS} \ + -Wall \ + -Winit-self \ + -Wextra \ + -Wcast-align \ + -Wcast-qual \ + -Wdisabled-optimization \ + -Wformat=2 \ + -Wmissing-include-dirs \ + -Woverloaded-virtual \ + -Wredundant-decls \ + -Wshadow \ -Wsign-promo") else() set(CMAKE_CXX_FLAGS "/EHsc") diff --git a/game/kernel/kdsnetm.h b/game/kernel/kdsnetm.h index 60b6f3715d..51125e0c1f 100644 --- a/game/kernel/kdsnetm.h +++ b/game/kernel/kdsnetm.h @@ -74,13 +74,16 @@ void ShutdownGoalProto(); */ void GoalProtoHandler(int event, int param, void* data); +// TODO-WINDOWS +#ifdef __linux__ /*! * Low level DECI2 send * 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 p1, u64 p2, char* data, s32 size); +s32 SendFromBufferD(s32 p1, u64 p2, char* data, s32 size); +#endif /*! * Print GOAL Protocol status diff --git a/gc.sh b/gc.sh index 19ab0e192f..ac079580a1 100755 --- a/gc.sh +++ b/gc.sh @@ -4,4 +4,5 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export NEXT_DIR=$DIR +export FAKE_ISO_PATH=/game/fake_iso.txt $DIR/build/goalc/goalc "$@" \ No newline at end of file diff --git a/gk.sh b/gk.sh index f33bbcd06f..d49ccff100 100755 --- a/gk.sh +++ b/gk.sh @@ -4,4 +4,5 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export NEXT_DIR=$DIR +export FAKE_ISO_PATH=/game/fake_iso.txt $DIR/build/game/gk "$@" diff --git a/test.sh b/test.sh index 3cff7a5976..6370a8a2db 100755 --- a/test.sh +++ b/test.sh @@ -4,4 +4,5 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" export NEXT_DIR=$DIR +export FAKE_ISO_PATH=/game/fake_iso.txt $DIR/build/test/goalc-test --gtest_color=yes "$@" \ No newline at end of file From dcde103c2667c7446a9adffb75506afb2817a37a Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Thu, 3 Sep 2020 23:56:35 -0400 Subject: [PATCH 29/32] Address compiler and test failures --- .github/workflows/linux-workflow.yaml | 1 + game/kernel/kboot.cpp | 4 ++-- game/kernel/klisten.cpp | 24 +++++++++++++----------- game/kernel/kmachine.cpp | 16 ++++++++-------- game/overlord/fake_iso.cpp | 2 +- game/runtime.cpp | 21 +++++++++++---------- game/system/Deci2Server.cpp | 10 +++------- game/system/Deci2Server.h | 2 +- game/system/SystemThread.cpp | 3 +-- game/system/SystemThread.h | 2 ++ goalc/goos/Reader.cpp | 11 +---------- goalc/listener/Listener.cpp | 4 +--- test/test_kernel.cpp | 2 +- test/test_listener_deci2.cpp | 2 +- 14 files changed, 47 insertions(+), 57 deletions(-) diff --git a/.github/workflows/linux-workflow.yaml b/.github/workflows/linux-workflow.yaml index c8e67b0cc1..fbb17ac238 100644 --- a/.github/workflows/linux-workflow.yaml +++ b/.github/workflows/linux-workflow.yaml @@ -20,6 +20,7 @@ jobs: make -j - name: Test Project with gTest run: ./test.sh + timeout-minutes: 5 - name: Check Clang-Formatting run: | chmod +x ./third-party/run-clang-format/run-clang-format.py diff --git a/game/kernel/kboot.cpp b/game/kernel/kboot.cpp index b9545ceaaf..9f6f6de06d 100644 --- a/game/kernel/kboot.cpp +++ b/game/kernel/kboot.cpp @@ -134,7 +134,7 @@ void KernelCheckAndDispatch() { // dispatch the kernel //(**kernel_dispatcher)(); call_goal(Ptr(kernel_dispatcher->value), 0, 0, 0, s7.offset, g_ee_main_mem); - // TODO-WINDOWS + // TODO-WINDOWS #ifdef __linux__ ClearPending(); #endif @@ -147,7 +147,7 @@ void KernelCheckAndDispatch() { #ifdef _WIN32 Sleep(1000); // todo - remove this #elif __linux__ - usleep(1000); + usleep(1000); #endif } } diff --git a/game/kernel/klisten.cpp b/game/kernel/klisten.cpp index 198858c2ca..7f990bf27e 100644 --- a/game/kernel/klisten.cpp +++ b/game/kernel/klisten.cpp @@ -71,10 +71,10 @@ void ClearPending() { Ptr msg = OutputBufArea.cast() + sizeof(GoalMessageHeader); auto size = strlen(msg.c()); // note - if size is ever greater than 2^16 this will cause an issue. - // TODO-WINDOWS - #ifdef __linux__ - SendFromBuffer(msg.c(), size); - #endif + // TODO-WINDOWS +#ifdef __linux__ + SendFromBuffer(msg.c(), size); +#endif clear_output(); } @@ -87,10 +87,10 @@ void ClearPending() { if (send_size > 64000) { send_size = 64000; } - // TODO-WINDOWS - #ifdef __linux__ - SendFromBufferD(2, 0, msg, send_size); - #endif +// TODO-WINDOWS +#ifdef __linux__ + SendFromBufferD(2, 0, msg, send_size); +#endif size -= send_size; msg += send_size; } @@ -109,9 +109,11 @@ void ClearPending() { */ void SendAck() { if (MasterDebug) { - #ifdef __linux__ - SendFromBufferD(u16(ListenerMessageKind::MSG_ACK), protoBlock.msg_id, AckBufArea + sizeof(GoalMessageHeader), strlen(AckBufArea + sizeof(GoalMessageHeader))); - #endif +#ifdef __linux__ + SendFromBufferD(u16(ListenerMessageKind::MSG_ACK), protoBlock.msg_id, + AckBufArea + sizeof(GoalMessageHeader), + strlen(AckBufArea + sizeof(GoalMessageHeader))); +#endif } } diff --git a/game/kernel/kmachine.cpp b/game/kernel/kmachine.cpp index c1d820a6e2..4752b90b93 100644 --- a/game/kernel/kmachine.cpp +++ b/game/kernel/kmachine.cpp @@ -329,10 +329,10 @@ int InitMachine() { // } if (MasterDebug) { // connect to GOAL compiler - // TODO-WINDOWS - #ifdef __linux__ - InitGoalProto(); - #endif +// TODO-WINDOWS +#ifdef __linux__ + InitGoalProto(); +#endif } printf("InitSound\n"); @@ -362,10 +362,10 @@ int ShutdownMachine() { StopIOP(); CloseListener(); ShutdownSound(); - // TODO-WINDOWS - #ifdef __linux__ - ShutdownGoalProto(); - #endif +// TODO-WINDOWS +#ifdef __linux__ + ShutdownGoalProto(); +#endif Msg(6, "kernel: machine shutdown"); return 0; } diff --git a/game/overlord/fake_iso.cpp b/game/overlord/fake_iso.cpp index 2330d732e7..91840ec4f9 100644 --- a/game/overlord/fake_iso.cpp +++ b/game/overlord/fake_iso.cpp @@ -87,7 +87,7 @@ int FS_Init(u8* buffer) { // get path to next/data/fake_iso.txt, the map file. char fakeiso_path[512]; strcpy(fakeiso_path, next_dir); - fake_iso_path = std::getenv("FAKE_ISO_PATH"); + fake_iso_path = std::getenv("FAKE_ISO_PATH"); assert(fake_iso_path); strcat(fakeiso_path, fake_iso_path); diff --git a/game/runtime.cpp b/game/runtime.cpp index 05622de93c..379898a9a1 100644 --- a/game/runtime.cpp +++ b/game/runtime.cpp @@ -11,6 +11,7 @@ #include #include #endif + #include #include "runtime.h" @@ -55,18 +56,18 @@ namespace { * SystemThread function for running the DECI2 communication with the GOAL compiler. */ -void deci2_runner(SystemThreadInterface& interfaces) { - // TODO-WINDOWS - #ifdef __linux__ +void deci2_runner(SystemThreadInterface& iface) { +// TODO-WINDOWS +#ifdef __linux__ // callback function so the server knows when to give up and shutdown - std::function shutdown_callback = [&]() { return interface.get_want_exit(); }; + std::function shutdown_callback = [&]() { return iface.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(); + iface.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"); @@ -78,7 +79,7 @@ void deci2_runner(SystemThreadInterface& interfaces) { printf("[DECI2] waiting for listener...\n"); bool saw_listener = false; - while (!interface.get_want_exit()) { + while (!iface.get_want_exit()) { if (server.check_for_listener()) { if (!saw_listener) { printf("[DECI2] Connected!\n"); @@ -91,7 +92,7 @@ void deci2_runner(SystemThreadInterface& interfaces) { usleep(50000); } } - #endif +#endif } // EE System @@ -235,10 +236,10 @@ void exec_runtime(int argc, char** argv) { // step 1: sce library prep iop::LIBRARY_INIT(); ee::LIBRARY_INIT_sceCd(); - // TODO-WINDOWS - #ifdef __linux__ +// TODO-WINDOWS +#ifdef __linux__ ee::LIBRARY_INIT_sceDeci2(); - #endif +#endif ee::LIBRARY_INIT_sceSif(); // step 2: system prep diff --git a/game/system/Deci2Server.cpp b/game/system/Deci2Server.cpp index 56122c5ae7..600f34462e 100644 --- a/game/system/Deci2Server.cpp +++ b/game/system/Deci2Server.cpp @@ -7,12 +7,10 @@ // TODO-WINDOWS #ifdef __linux__ +#include #include #include #include -#include -#include -#include #include #include @@ -20,8 +18,6 @@ #include "common/versions.h" #include "Deci2Server.h" -typedef int socklen_t; - Deci2Server::Deci2Server(std::function shutdown_callback) { buffer = new char[BUFFER_SIZE]; want_exit = std::move(shutdown_callback); @@ -56,7 +52,7 @@ bool Deci2Server::init() { return false; } - const char opt = 1; + int opt = 1; if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { printf("[Deci2Server] Failed to setsockopt 1\n"); close(server_fd); @@ -64,7 +60,7 @@ bool Deci2Server::init() { return false; } - const char one = 1; + int one = 1; if (setsockopt(server_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { printf("[Deci2Server] Failed to setsockopt 2\n"); close(server_fd); diff --git a/game/system/Deci2Server.h b/game/system/Deci2Server.h index 388ee5ec7a..8695ff020d 100644 --- a/game/system/Deci2Server.h +++ b/game/system/Deci2Server.h @@ -8,7 +8,7 @@ #ifndef JAK1_DECI2SERVER_H #define JAK1_DECI2SERVER_H -#include +#include #include #include #include diff --git a/game/system/SystemThread.cpp b/game/system/SystemThread.cpp index 5159dd0920..64121c6e11 100644 --- a/game/system/SystemThread.cpp +++ b/game/system/SystemThread.cpp @@ -99,7 +99,6 @@ void SystemThread::start(std::function f) { * Join a system thread */ void SystemThread::join() { - void* x; thread.join(); running = false; } @@ -166,5 +165,5 @@ void SystemThreadInterface::report_perf_stats() { thread.last_cpu_user = current_user; thread.last_collection_nanoseconds = current_ns; } -} +} #endif \ No newline at end of file diff --git a/game/system/SystemThread.h b/game/system/SystemThread.h index c9dc513312..0a01af1837 100644 --- a/game/system/SystemThread.h +++ b/game/system/SystemThread.h @@ -10,7 +10,9 @@ #include #include #include +#include #include + #include "Timer.h" constexpr int MAX_SYSTEM_THREADS = 16; diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index b3d8fa6035..33fcc0a6fa 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -66,9 +66,7 @@ void TextStream::seek_past_whitespace_and_comments() { } } -Reader::~Reader() { - printf("destroying reader\n"); -} +Reader::~Reader() {} Reader::Reader() { // third-party library used for a fancy line in @@ -634,7 +632,6 @@ bool Reader::try_token_as_hex(const Token& tok, Object& obj) { * 64-bit signed. Won't accept values between INT64_MAX and UINT64_MAX. */ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { - printf("try token as integer %ld %s\n", tok.text.size(), tok.text.c_str()); if (decimal_start(tok.text[0]) && !str_contains(tok.text, '.')) { // determine if we look like a number or not. If we look like a number, but stoll fails, // it means that the number is too big or too small, and we should error @@ -648,18 +645,13 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { return false; } } - - printf("going to try stoll...\n"); uint64_t v = 0; try { std::size_t end = 0; v = std::stoll(tok.text, &end); - printf("stoll didn't throw, got %ld\n", v); if (end != tok.text.size()) { - printf("didn't read whole thing\n"); return false; } - printf("returning object!\n"); obj = Object::make_integer(v); return true; } catch (std::exception& e) { @@ -667,7 +659,6 @@ bool Reader::try_token_as_integer(const Token& tok, Object& obj) { } } return false; - } bool Reader::try_token_as_char(const Token& tok, Object& obj) { diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index b19ddf011c..1561f39899 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include #include "Listener.h" #include "common/versions.h" @@ -74,7 +72,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; + int one = 1; if (setsockopt(socket_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one))) { printf("[Listener] failed to TCP_NODELAY\n"); close(socket_fd); diff --git a/test/test_kernel.cpp b/test/test_kernel.cpp index 5bc2e09670..fb4b17a4c9 100644 --- a/test/test_kernel.cpp +++ b/test/test_kernel.cpp @@ -157,7 +157,7 @@ TEST(Kernel, ftoa) { ftoa(buffer, 1., 1, ' ', 1, 0); EXPECT_EQ("1.0", std::string(buffer)); - float zero = 0.0f; + float zero = 0.0f; ftoa(buffer, 0.f / zero, 1, ' ', 4, 0); EXPECT_EQ("NaN", std::string(buffer)); diff --git a/test/test_listener_deci2.cpp b/test/test_listener_deci2.cpp index 7888a9fd87..d7b65cba2a 100644 --- a/test/test_listener_deci2.cpp +++ b/test/test_listener_deci2.cpp @@ -1,4 +1,4 @@ -#ifdef __unix__ +#ifdef __linux__ #include "gtest/gtest.h" #include "goalc/listener/Listener.h" From d86775878e88fa082194845aa544e454ffdbe68f Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Fri, 4 Sep 2020 19:37:34 -0400 Subject: [PATCH 30/32] Address review feedback --- README.md | 4 +-- game/kernel/asm_funcs.asm | 43 +++++++++++++++++++++++++-- game/kernel/kprint.h | 31 +++++++++++++++++++ game/kernel/kscheme.cpp | 59 ++++++++++++++++++++++++++++++++----- goalc/goos/Reader.cpp | 35 +++++++++++++--------- goalc/goos/Reader.h | 1 - goalc/listener/Listener.cpp | 4 +++ 7 files changed, 150 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 1a6a7ef923..a29e68e62b 100644 --- a/README.md +++ b/README.md @@ -246,7 +246,7 @@ The "runtime" will be a replacement for all of the C/C++ code of the original ga - [x] GOAL Linker - [ ] PS2-specific hardware initialization as required by Sony libraries - [x] GOAL "kheap" allocator - - [ ] Memory card interfaces + - [ ] Memory card interface - [x] GOAL printf (called `format`) implementation - [x] GOAL hash/symbol table implementation - [x] Implementation of some built-in GOAL methods/functions @@ -259,7 +259,7 @@ The "runtime" will be a replacement for all of the C/C++ code of the original ga - [ ] Ramdisk stuff (implemented but totally untested) - The "989_snd" sound driver (no progress has been made here, the rough plan is to do a high level emulation of the sound system) - Sony libraries - - [x] SIF (interfaces between EE/IOP for sending data, receiving data, and making remote procedure calls) + - [x] SIF (interface between EE/IOP for sending data, receiving data, and making remote procedure calls) - [x] IOP Kernel (single-processor non-preemptive multitasking) - [x] stubs for stuff that doesn't really matter diff --git a/game/kernel/asm_funcs.asm b/game/kernel/asm_funcs.asm index e3e39a6034..e0e1f3b0fb 100644 --- a/game/kernel/asm_funcs.asm +++ b/game/kernel/asm_funcs.asm @@ -57,6 +57,45 @@ _format: ;; run this wrapper to call the real format_impl +;; The _call_goal_asm function is used to call a GOAL function from C. +;; It supports up to 3 arguments and a return value. +;; This should be called with the arguments: +;; - first goal arg +;; - second goal arg +;; - third goal arg +;; - address of function to call +;; - address of the symbol table +;; - GOAL memory space offset + +global _call_goal_asm_linux + +_call_goal_asm_linux: + ;; x86 saved registers we need to modify for GOAL should be saved + push r13 + push r14 + push r15 + + ;; RDI - first arg + ;; RSI - second arg + ;; RDX - third arg + ;; RCX - function pointer (goes in r13) + ;; R8 - st (goes in r14) + ;; R9 - off (goes in r15) + + ;; set GOAL function pointer + mov r13, rcx + ;; offset + mov r15, r8 + ;; symbol table + mov r14, r9 + ;; call GOAL by function pointer + call r13 + + ;; retore x86 registers. + pop r15 + pop r14 + pop r13 + ret ;; The _call_goal_asm function is used to call a GOAL function from C. @@ -69,9 +108,9 @@ _format: ;; - address of the symbol table ;; - GOAL memory space offset -global _call_goal_asm +global _call_goal_asm_win32 -_call_goal_asm: +_call_goal_asm_win32: push rdx ; 8 push rbx ; 16 push rbp ; 24 diff --git a/game/kernel/kprint.h b/game/kernel/kprint.h index 049a66d35c..0c4d178b80 100644 --- a/game/kernel/kprint.h +++ b/game/kernel/kprint.h @@ -62,28 +62,59 @@ void output_unload(const char* name); */ void output_segment_load(const char* name, Ptr link_block, u32 flags); +#ifdef __linux__ +/*! + * Print to the GOAL print buffer from C + */ +void cprintf(const char* format, ...) __attribute__((format(printf, 1, 2))); +#elif _WIN32 /*! * Print to the GOAL print buffer from C */ void cprintf(const char* format, ...); +#endif +#ifdef __linux__ +/*! + * 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))); +#elif _WIN32 /*! * Print directly to the C stdout * The "k" parameter is ignored, so this is just like printf */ void Msg(s32 k, const char* format, ...); +#endif +#ifdef __linux__ +/*! + * Print directly to the C stdout + * This is identical to Msg. + */ +void MsgWarn(const char* format, ...) __attribute__((format(printf, 1, 2))); +#elif _WIN32 /*! * Print directly to the C stdout * This is identical to Msg. */ void MsgWarn(const char* format, ...); +#endif +#ifdef __linux__ +/*! + * Print directly to the C stdout + * This is identical to Msg. + */ +void MsgErr(const char* format, ...) __attribute__((format(printf, 1, 2))); +#elif _WIN32 /*! * Print directly to the C stdout * This is identical to Msg. */ void MsgErr(const char* format, ...); +#endif /*! * Reverse string in place. diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index 9981f78f4c..d6f9f7a16e 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -320,6 +320,45 @@ u64 make_string_from_c(const char* c_str) { * The implementation is to create a simple trampoline function which jumps to the C function. */ Ptr make_function_from_c(void* func) { +#ifdef __linux__ + return make_function_from_c_linux(func); +#elif _WIN32 + return make_function_from_c_win32(func); +#endif +} + +Ptr make_function_from_c_linux(void* func) { + // allocate a function object on the global heap + auto mem = Ptr( + alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, *(s7 + FIX_SYM_FUNCTION_TYPE), 0x40)); + auto f = (uint64_t)func; + auto fp = (u8*)&f; + + // we will put the function address in RAX with a movabs rax, imm8 + mem.c()[0] = 0x48; + mem.c()[1] = 0xb8; + for (int i = 0; i < 8; i++) { + mem.c()[2 + i] = fp[i]; + } + + // jmp rax + mem.c()[10] = 0xff; + mem.c()[11] = 0xe0; + + // the C function's ret will return to the caller of this trampoline. + + // CacheFlush(mem, 0x34); + + return mem.cast(); +} + +/*! + * Create a GOAL function from a C function. This doesn't export it as a global function, it just + * creates a function object on the global heap. + * + * The implementation is to create a simple trampoline function which jumps to the C function. + */ +Ptr make_function_from_c_win32(void* func) { // allocate a function object on the global heap auto mem = Ptr( alloc_heap_object(s7.offset + FIX_SYM_GLOBAL_HEAP, *(s7 + FIX_SYM_FUNCTION_TYPE), 0x80)); @@ -354,10 +393,6 @@ Ptr make_function_from_c(void* func) { mem.c()[i++] = x; } - // jmp rax - // mem.c()[10] = 0xff; - // mem.c()[11] = 0xe0; - // the C function's ret will return to the caller of this trampoline. // CacheFlush(mem, 0x34); @@ -911,8 +946,12 @@ u64 method_set(u32 type_, u32 method_id, u32 method) { } extern "C" { -// defined in asm_funcs.nasm -uint64_t _call_goal_asm(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset); +// defined in asm_funcs.asm +#ifdef __linux__ +uint64_t _call_goal_asm_linux(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset); +#elif _WIN32 +uint64_t _call_goal_asm_win32(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* offset); +#endif } /*! @@ -921,7 +960,11 @@ uint64_t _call_goal_asm(u64 a0, u64 a1, u64 a2, void* fptr, void* st_ptr, void* u64 call_goal(Ptr f, u64 a, u64 b, u64 c, u64 st, void* offset) { auto st_ptr = (void*)((uint8_t*)(offset) + st); void* fptr = f.c(); - return _call_goal_asm(a, b, c, fptr, st_ptr, offset); +#ifdef __linux__ + return _call_goal_asm_linux(a, b, c, fptr, st_ptr, offset); +#elif _WIN32 + return _call_goal_asm_win32(a, b, c, fptr, st_ptr, offset); +#endif } /*! @@ -1906,4 +1949,4 @@ s64 load_and_link(const char* filename, char* decode_name, kheapinfo* heap, u32 return (s32)rv.offset; } -// todo, read lcock code \ No newline at end of file +// todo, read lcock code diff --git a/goalc/goos/Reader.cpp b/goalc/goos/Reader.cpp index 33fcc0a6fa..fa77d54996 100644 --- a/goalc/goos/Reader.cpp +++ b/goalc/goos/Reader.cpp @@ -66,8 +66,6 @@ void TextStream::seek_past_whitespace_and_comments() { } } -Reader::~Reader() {} - Reader::Reader() { // third-party library used for a fancy line in linenoise::SetHistoryMaxLen(400); @@ -78,18 +76,27 @@ Reader::Reader() { add_reader_macro(",", "unquote"); add_reader_macro(",@", "unquote-splicing"); - uint8_t valid[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - for (int i = 0; i < 256; i++) { - valid_symbols_chars[i] = valid[i]; + // setup table of which characters are valid for starting a symbol + for (auto& x : valid_symbols_chars) { + x = false; + } + + for (char x = 'a'; x <= 'z'; x++) { + valid_symbols_chars[(int)x] = true; + } + + for (char x = 'A'; x <= 'Z'; x++) { + valid_symbols_chars[(int)x] = true; + } + + for (char x = '0'; x <= '9'; x++) { + valid_symbols_chars[(int)x] = true; + } + + const char bonus[] = "!$%&*+-/\\.,@^_-;:<>?~=#"; + + for (const char* c = bonus; *c; c++) { + valid_symbols_chars[(int)*c] = true; } // find the source directory diff --git a/goalc/goos/Reader.h b/goalc/goos/Reader.h index 06710994b4..1ac7e6a7a1 100644 --- a/goalc/goos/Reader.h +++ b/goalc/goos/Reader.h @@ -68,7 +68,6 @@ struct Token { class Reader { public: Reader(); - ~Reader(); Object read_from_string(const std::string& str); Object read_from_stdin(const std::string& prompt_name); Object read_from_file(const std::string& filename); diff --git a/goalc/listener/Listener.cpp b/goalc/listener/Listener.cpp index 1561f39899..2a53f26612 100644 --- a/goalc/listener/Listener.cpp +++ b/goalc/listener/Listener.cpp @@ -43,6 +43,10 @@ bool Listener::is_connected() const { return m_connected; } +/*! + * Attempt to connect to the target. If the target isn't running, this should fail quickly. + * Returns true if successfully 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!"); From fa40b68a371f8642ce65411f8093b5fc41fd5e14 Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Fri, 4 Sep 2020 19:43:45 -0400 Subject: [PATCH 31/32] Aren't functions hoisted..? --- game/kernel/kscheme.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index d6f9f7a16e..5d32b9e649 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -313,20 +313,6 @@ u64 make_string_from_c(const char* c_str) { return mem; } -/*! - * Create a GOAL function from a C function. This doesn't export it as a global function, it just - * creates a function object on the global heap. - * - * The implementation is to create a simple trampoline function which jumps to the C function. - */ -Ptr make_function_from_c(void* func) { -#ifdef __linux__ - return make_function_from_c_linux(func); -#elif _WIN32 - return make_function_from_c_win32(func); -#endif -} - Ptr make_function_from_c_linux(void* func) { // allocate a function object on the global heap auto mem = Ptr( @@ -400,6 +386,20 @@ Ptr make_function_from_c_win32(void* func) { return mem.cast(); } +/*! + * Create a GOAL function from a C function. This doesn't export it as a global function, it just + * creates a function object on the global heap. + * + * The implementation is to create a simple trampoline function which jumps to the C function. + */ +Ptr make_function_from_c(void* func) { +#ifdef __linux__ + return make_function_from_c_linux(func); +#elif _WIN32 + return make_function_from_c_win32(func); +#endif +} + /*! * Create a GOAL function which does nothing and immediately returns. */ From 7d1625734f00add0b080dbfcc481e354b64ecb1f Mon Sep 17 00:00:00 2001 From: water Date: Fri, 4 Sep 2020 20:00:45 -0400 Subject: [PATCH 32/32] small fixes for linux --- game/CMakeLists.txt | 1 + game/kernel/asm_funcs.asm | 42 +++++++++++++++++++++++++++++++++++--- game/kernel/kscheme.cpp | 13 +++++++++--- game/overlord/fake_iso.cpp | 5 ++++- 4 files changed, 54 insertions(+), 7 deletions(-) diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index a6b6357ee5..59cacdf7af 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -7,6 +7,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) message(STATUS "GCC detected, adding compile flags") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \ + -ggdb \ -Wall \ -Winit-self \ -Wextra \ diff --git a/game/kernel/asm_funcs.asm b/game/kernel/asm_funcs.asm index e0e1f3b0fb..2b41efe59d 100644 --- a/game/kernel/asm_funcs.asm +++ b/game/kernel/asm_funcs.asm @@ -14,8 +14,8 @@ SECTION .TEXT ;; a pointer to this array of GOAL arguments as the argument. The reason for this is that GOAL and ;; the standard System V ABI used in Linux are different for 8 argument function calls. -global _format -_format: +global _format_win32 +_format_win32: ; GOAL will call with regs RDI, RSI, RDX, RCX, R8, R9, R10, R11 ; to make sure the stack frame is aligned @@ -39,6 +39,42 @@ _format: call format_impl add rsp, 32 + ; restore + ; (note - this could probably just be add rsp 72, we don't care about the value of these register) + pop rdi + pop rsi + pop rdx + pop rcx + pop r8 + pop r9 + pop r10 + pop r11 + add rsp, 8 + ret + +global _format_linux +_format_linux: + ; GOAL will call with regs RDI, RSI, RDX, RCX, R8, R9, R10, R11 + + ; to make sure the stack frame is aligned + sub rsp, 8 + + ; push all registers and create the register array on the stack + push r11 + push r10 + push r9 + push r8 + push rcx + push rdx + push rsi + push rdi + + ; set the first argument register to the stack argument array + mov rdi, rsp + + ; call C function to do format, result will go in RAX + call format_impl + ; restore ; (note - this could probably just be add rsp 72, we don't care about the value of these register) pop rdi @@ -148,4 +184,4 @@ _call_goal_asm_win32: pop rbx pop rdx - ret \ No newline at end of file + ret diff --git a/game/kernel/kscheme.cpp b/game/kernel/kscheme.cpp index 5d32b9e649..d2c41a96cb 100644 --- a/game/kernel/kscheme.cpp +++ b/game/kernel/kscheme.cpp @@ -1517,7 +1517,11 @@ s32 test_function(s32 arg0, s32 arg1, s32 arg2, s32 arg3) { extern "C" { // defined in asm_funcs. It calls format_impl and sets up arguments correctly. -void _format(); +#ifdef __linux__ +void _format_linux(); +#elif _WIN32 +void _format_win32(); +#endif } /*! @@ -1769,8 +1773,11 @@ s32 InitHeapAndSymbol() { make_function_symbol_from_c("load", (void*)load); make_function_symbol_from_c("loado", (void*)loado); make_function_symbol_from_c("unload", (void*)unload); - - make_function_symbol_from_c("_format", (void*)_format); +#ifdef __linux__ + make_function_symbol_from_c("_format", (void*)_format_linux); +#elif _WIN32 + make_function_symbol_from_c("_format", (void*)_format_win32); +#endif // allocations make_function_symbol_from_c("malloc", (void*)alloc_heap_memory); diff --git a/game/overlord/fake_iso.cpp b/game/overlord/fake_iso.cpp index 91840ec4f9..f06c22ba83 100644 --- a/game/overlord/fake_iso.cpp +++ b/game/overlord/fake_iso.cpp @@ -194,6 +194,9 @@ static const char* get_file_path(FileRecord* fr) { assert(fr->location < fake_iso_entry_count); static char path_buffer[1024]; strcpy(path_buffer, next_dir); +#ifdef __linux__ + strcat(path_buffer, "/"); +#endif strcat(path_buffer, fake_iso_entries[fr->location].file_path); return path_buffer; } @@ -352,4 +355,4 @@ uint32_t FS_LoadSoundBank(char* name, void* buffer) { (void)name; (void)buffer; assert(false); -} \ No newline at end of file +}