├── .gitignore ├── LICENSE ├── Makefile.retroreversing ├── README.md ├── cd ├── custom_decoder.h ├── exceptions.h ├── iso9660.cpp ├── iso9660.h ├── kaitaistream.cpp ├── kaitaistream.h ├── kaitaistruct.h └── saturn.ksy ├── cdl ├── CD.cpp ├── CDL.hpp ├── CDL_FileWriting.cpp ├── CDL_FileWriting.hpp ├── CDL_JSON.cpp ├── CDL_MemoryMapper.cpp ├── CDL_MemoryMapper.hpp ├── CDL_Util.cpp ├── CDL_interface.cpp ├── Image.cpp ├── InputLogger.cpp ├── Interpreter.cpp ├── Main.cpp ├── Setup.cpp ├── codeDataLogger.cpp ├── codeDataLogger.hpp ├── jarowinkler.c ├── md5.h ├── mustache.hpp └── nlohmann │ └── json.hpp ├── civetweb ├── include │ └── civetweb.h └── src │ ├── civetweb.c │ ├── handle_form.inl │ ├── libRREmscriptenInterface.cpp │ ├── libRRWebInterface.cpp │ └── md5.inl ├── consoles ├── DummyConsole.cpp ├── Famicom.cpp ├── GameBoy.cpp ├── GenesisPlusGX.cpp ├── N64.cpp ├── PS1.cpp ├── PokemonMini.cpp ├── SNES.cpp └── Saturn.cpp ├── constants ├── GameBoy.json ├── GameGear.json └── MasterSystem.json ├── export_templates ├── MasterSystem │ ├── .gitignore │ ├── INSTALL.md │ ├── Makefile │ ├── README.md │ ├── common.asm │ ├── common │ │ ├── constants.asm │ │ └── header.asm │ ├── files.json │ ├── layout.link │ └── tools │ │ ├── Makefile │ │ └── scan_includes.c ├── NES │ ├── .gitignore │ ├── INSTALL.md │ ├── Makefile │ ├── README.md │ ├── common.asm │ ├── common │ │ ├── constants.asm │ │ └── header.asm │ ├── files.json │ ├── layout.link │ └── tools │ │ ├── Makefile │ │ └── scan_includes.c ├── SNES │ ├── .gitignore │ ├── INSTALL.md │ ├── Makefile │ ├── README.md │ ├── common.asm │ ├── common │ │ ├── constants.asm │ │ └── header.asm │ ├── files.json │ ├── layout.link │ └── tools │ │ ├── Makefile │ │ └── scan_includes.c ├── gameboy │ ├── .gitignore │ ├── INSTALL.md │ ├── Makefile │ ├── README.md │ ├── common.asm │ ├── common │ │ ├── constants.asm │ │ ├── header.asm │ │ └── rgbdscheck.asm │ ├── files.json │ ├── layout.link │ └── tools │ │ ├── Makefile │ │ └── scan_includes.c └── gamegear │ ├── .gitignore │ ├── INSTALL.md │ ├── Makefile │ ├── README.md │ ├── common.asm │ ├── common │ ├── constants.asm │ └── header.asm │ ├── files.json │ ├── layout.link │ └── tools │ ├── Makefile │ └── scan_includes.c ├── file_formats └── rnc │ └── rnc.cpp ├── include ├── libRR.h ├── libRR_c.h └── libretro.h ├── interpreter ├── duktape │ ├── LICENSE.txt │ ├── README.rst │ ├── duk_config.h │ ├── duk_source_meta.json │ ├── duktape.c │ └── duktape.h └── mjs │ ├── LICENSE │ ├── README.md │ ├── mjs.c │ └── mjs.h ├── png ├── lodepng.cpp └── lodepng.h ├── source_exporter ├── CommonSourceExport.cpp └── CommonSourceExport.h └── websrc ├── .babelrc ├── .eslintrc.js ├── HomePage.tsx ├── ReadMe.md ├── api └── getEmulatorMetadata.tsx ├── debugger └── PlaySettings.jsx ├── dialogs ├── EditFunctionDialog.jsx ├── ExportFunctionDialog.jsx ├── LoadLinkerMapFileDialog.jsx ├── PauseSaveDialog.jsx └── ResumeDialog.tsx ├── dist ├── CNAME ├── assets │ ├── controller.xcf │ ├── left.png │ ├── loading.png │ ├── loading.xcf │ ├── menu.png │ ├── menu.xcf │ ├── right.png │ ├── showcase.png │ └── showcase.xcf ├── genesisrr.wasm ├── images │ └── controller-icons │ │ ├── Readme.txt │ │ ├── Vita_Select.png │ │ ├── Vita_Start.png │ │ ├── XboxOne_A.png │ │ ├── XboxOne_B.png │ │ ├── XboxOne_Dpad_Down.png │ │ ├── XboxOne_Dpad_Left.png │ │ ├── XboxOne_Dpad_Right.png │ │ ├── XboxOne_Dpad_Up.png │ │ ├── XboxOne_LB.png │ │ ├── XboxOne_LT.png │ │ ├── XboxOne_Left_Stick.png │ │ ├── XboxOne_Left_Stick_Click.png │ │ ├── XboxOne_RB.png │ │ ├── XboxOne_RT.png │ │ ├── XboxOne_Right_Stick.png │ │ ├── XboxOne_Right_Stick_Click.png │ │ ├── XboxOne_X.png │ │ └── XboxOne_Y.png ├── index.html └── libRRUI.bundle.js ├── firebase-config.ts ├── home ├── GameDropZone.tsx ├── database.ts ├── emulators.ts └── matoya.js ├── images └── controller-icons │ ├── Readme.txt │ ├── Vita_Select.png │ ├── Vita_Start.png │ ├── XboxOne_A.png │ ├── XboxOne_B.png │ ├── XboxOne_Dpad_Down.png │ ├── XboxOne_Dpad_Left.png │ ├── XboxOne_Dpad_Right.png │ ├── XboxOne_Dpad_Up.png │ ├── XboxOne_LB.png │ ├── XboxOne_LT.png │ ├── XboxOne_Left_Stick.png │ ├── XboxOne_Left_Stick_Click.png │ ├── XboxOne_RB.png │ ├── XboxOne_RT.png │ ├── XboxOne_Right_Stick.png │ ├── XboxOne_Right_Stick_Click.png │ ├── XboxOne_X.png │ └── XboxOne_Y.png ├── index.html ├── main.tsx ├── main ├── Drawer.jsx ├── PlaythroughSelector.js ├── RRTitleBar.tsx ├── SaveStateList.jsx └── Template.jsx ├── package-lock.json ├── package.json ├── pages ├── CodeOverride │ └── CodeOverride.jsx ├── DataStructures.jsx ├── DataVisualiser │ ├── 8bppXterm.js │ ├── VisualiseViewer.jsx │ ├── visual.css │ └── visual.jsx ├── DisasmViewer │ ├── DisasmViewer.css │ └── DisasmViewer.jsx ├── FunctionList.tsx ├── FunctionViewer │ └── FunctionViewer.jsx ├── GameInformation.jsx ├── HexViewer │ ├── AsciiViewer.jsx │ ├── HexViewer.tsx │ ├── PixelTable.jsx │ └── style.css ├── InputHistory.css ├── InputHistory.tsx ├── MainPage.tsx ├── MemoryViewer.tsx ├── NotesViewer │ └── NotesViewer.jsx ├── ParserViewer.jsx ├── ParserViewer │ ├── binary_parser.js │ ├── binary_unparser.js │ └── context.js ├── ResourceList.tsx ├── StringsViewer │ └── StringsViewer.jsx └── util │ ├── DownloadData.js │ ├── TripeDotDropDownMenu.tsx │ └── VirtualTable.jsx ├── popovers └── FrameHintPopover.jsx ├── server.ts ├── settings.json ├── styles.js ├── tsconfig.json ├── webpack.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | .DS_Store 34 | *.tmp 35 | 36 | websrc/node_modules 37 | websrc/dist/genesis.wasm 38 | websrc/dist/melonds.wasm 39 | websrc/dist/mgba.wasm 40 | websrc/dist/quicknes.wasm 41 | websrc/dist/libRRUI.bundle.js.LICENSE.txt 42 | websrc/dist/snes9x.wasm 43 | websrc/dist/index.html 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 RetroReversing 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile.retroreversing: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | CCFLAGS += -D WIN32 -D _WIN32 -w 3 | # TODO: figure out why -fsanitize=address doesn't work on window (https://stackoverflow.com/questions/55018627/cannot-find-lasan-using-address-sanitizer-in-qt-creator-in-windows-mingw) 4 | CXXFLAGS += -D WIN32 -D _WIN32 -std=c++11 -lstdc++fs -w -lstdc++ 5 | LDFLAGS += -std=c++11 -lstdc++fs -lstdc++ -pthread -lws2_32 6 | ifeq ($(PROCESSOR_ARCHITEW6432),AMD64) 7 | CCFLAGS += -D AMD64 8 | CFLAGS += -D AMD64 9 | else 10 | ifeq ($(PROCESSOR_ARCHITECTURE),AMD64) 11 | CCFLAGS += -D AMD64 12 | CFLAGS += -D AMD64 13 | endif 14 | ifeq ($(PROCESSOR_ARCHITECTURE),x86) 15 | CCFLAGS += -D IA32 16 | CFLAGS += -D IA32 17 | endif 18 | endif 19 | else 20 | UNAME_S := $(shell uname -s) 21 | ifeq ($(UNAME_S),Linux) 22 | CCFLAGS += -D LINUX -w 23 | CFLAGS += -D LINUX -w -lstdc++ 24 | CXXFLAGS += -std=c++11 -lstdc++fs -w 25 | LDFLAGS += -lc++ -std=c++11 -lstdc++fs -lstdc++ -pthread -ldl 26 | endif 27 | ifeq ($(UNAME_S),Darwin) 28 | CCFLAGS += -D OSX -w -MMD 29 | CFLAGS += -D OSX -w -MMD 30 | CXXFLAGS += -std=c++11 -stdlib=libc++ -mmacosx-version-min=13.0 -w -MMD 31 | LDFLAGS += -lc++ -mmacosx-version-min=13.0 32 | # LDFLAGS += -lbfd -L/usr/local/opt/binutils/lib -liberty -lintl -liconv -mmacosx-version-min=10.9 -lc++ 33 | endif 34 | UNAME_P := $(shell uname -p) 35 | ifeq ($(UNAME_P),x86_64) 36 | CCFLAGS += -D AMD64 37 | endif 38 | ifneq ($(filter %86,$(UNAME_P)),) 39 | CCFLAGS += -D IA32 40 | endif 41 | ifneq ($(filter arm%,$(UNAME_P)),) 42 | CCFLAGS += -D ARM 43 | endif 44 | endif 45 | 46 | SOURCES_C_RR += \ 47 | ./libRetroReversing/cdl/jarowinkler.c \ 48 | 49 | SOURCES_CXX_RR += \ 50 | libRetroReversing/cdl/CDL_interface.cpp \ 51 | libRetroReversing/cdl/CDL_JSON.cpp \ 52 | libRetroReversing/cdl/CDL_Util.cpp \ 53 | libRetroReversing/cdl/CDL_FileWriting.cpp \ 54 | libRetroReversing/cdl/InputLogger.cpp \ 55 | libRetroReversing/cdl/Setup.cpp \ 56 | libRetroReversing/cdl/Interpreter.cpp \ 57 | libRetroReversing/cdl/Main.cpp \ 58 | libRetroReversing/cdl/Image.cpp \ 59 | libRetroReversing/cdl/CD.cpp \ 60 | libRetroReversing/png/lodepng.cpp \ 61 | libRetroReversing/source_exporter/CommonSourceExport.cpp \ 62 | libRetroReversing/consoles/${libRetroReversingConsole}.cpp \ 63 | 64 | # Only include civet web if not using emscripten for web 65 | ifeq ($(platform),emscripten) 66 | SOURCES_CXX_RR += \ 67 | ./libRetroReversing/civetweb/src/libRREmscriptenInterface.cpp 68 | 69 | else 70 | SOURCES_C_RR += \ 71 | ./libRetroReversing/civetweb/src/civetweb.c \ 72 | ./libRetroReversing/interpreter/duktape/duktape.c \ 73 | ./libRetroReversing/interpreter/mjs/mjs.c 74 | 75 | SOURCES_CXX_RR += \ 76 | libRetroReversing/civetweb/src/libRRWebInterface.cpp 77 | endif 78 | 79 | # TODO: use a local path instead of /usr/local/opt/nlohmann_json/include 80 | # CFLAGS += -I/usr/local/opt/nlohmann_json/include 81 | # CXXFLAGS += -I/usr/local/opt/nlohmann_json/include -std=c++11 82 | 83 | 84 | 85 | ifeq ($(libRetroReversingMakeType),OBJECTS) 86 | OBJECTS += $(patsubst %.c,$(CORE_DIR)/build/obj/%_libretro.c.o,$(SOURCES_C_RR)) 87 | OBJECTS += $(patsubst %.cpp,$(CORE_DIR)/build/obj/%.cpp.o,$(SOURCES_CXX_RR)) 88 | else 89 | SOURCES_CXX += $(SOURCES_CXX_RR) 90 | SOURCES_C += $(SOURCES_C_RR) 91 | endif 92 | 93 | # TODO: Might need to set CORE_DIR 94 | $(CORE_DIR)/build/obj/libRetroReversing/%.cpp.o: ../libRetroReversing/%.cpp 95 | -@$(MKDIR) -p $(dir $@) 96 | $(CXX) $(CXXFLAGS) $(fpic) -DGB_INTERNAL -c $(OBJOUT)$@ $< 97 | 98 | $(CORE_DIR)/build/obj/libRetroReversing/%.o: ../libRetroReversing/%.c 99 | -@$(MKDIR) -p $(dir $@) 100 | $(CC) $(CFLAGS) $(fpic) -DGB_INTERNAL -c $(OBJOUT)$@ $< 101 | 102 | 103 | -------------------------------------------------------------------------------- /cd/custom_decoder.h: -------------------------------------------------------------------------------- 1 | #ifndef KAITAI_CUSTOM_DECODER_H 2 | #define KAITAI_CUSTOM_DECODER_H 3 | 4 | #include 5 | 6 | namespace kaitai { 7 | 8 | class custom_decoder { 9 | public: 10 | virtual ~custom_decoder() {}; 11 | virtual std::string decode(std::string src) = 0; 12 | }; 13 | 14 | } 15 | 16 | #endif -------------------------------------------------------------------------------- /cd/exceptions.h: -------------------------------------------------------------------------------- 1 | #ifndef KAITAI_EXCEPTIONS_H 2 | #define KAITAI_EXCEPTIONS_H 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | // We need to use "noexcept" in virtual destructor of our exceptions 10 | // subclasses. Different compilers have different ideas on how to 11 | // achieve that: C++98 compilers prefer `throw()`, C++11 and later 12 | // use `noexcept`. We define KS_NOEXCEPT macro for that. 13 | 14 | #if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900) 15 | #define KS_NOEXCEPT noexcept 16 | #else 17 | #define KS_NOEXCEPT throw() 18 | #endif 19 | 20 | namespace kaitai { 21 | 22 | /** 23 | * Common ancestor for all error originating from Kaitai Struct usage. 24 | * Stores KSY source path, pointing to an element supposedly guilty of 25 | * an error. 26 | */ 27 | class kstruct_error: public std::runtime_error { 28 | public: 29 | kstruct_error(const std::string what, const std::string src_path): 30 | std::runtime_error(src_path + ": " + what), 31 | m_src_path(src_path) 32 | { 33 | } 34 | 35 | virtual ~kstruct_error() KS_NOEXCEPT {}; 36 | 37 | protected: 38 | const std::string m_src_path; 39 | }; 40 | 41 | /** 42 | * Error that occurs when default endianness should be decided with 43 | * a switch, but nothing matches (although using endianness expression 44 | * implies that there should be some positive result). 45 | */ 46 | class undecided_endianness_error: public kstruct_error { 47 | public: 48 | undecided_endianness_error(const std::string src_path): 49 | kstruct_error("unable to decide on endianness for a type", src_path) 50 | { 51 | } 52 | 53 | virtual ~undecided_endianness_error() KS_NOEXCEPT {}; 54 | }; 55 | 56 | /** 57 | * Common ancestor for all validation failures. Stores pointer to 58 | * KaitaiStream IO object which was involved in an error. 59 | */ 60 | class validation_failed_error: public kstruct_error { 61 | public: 62 | validation_failed_error(const std::string what, const kstream* io, const std::string src_path): 63 | kstruct_error(std::string("at pos ") + /*std::to_string(io->pos())*/ + ": validation failed:" + what, src_path), 64 | m_io(io) 65 | { 66 | } 67 | 68 | // "at pos #{io.pos}: validation failed: #{msg}" 69 | 70 | virtual ~validation_failed_error() KS_NOEXCEPT {}; 71 | 72 | protected: 73 | const kstream* m_io; 74 | }; 75 | 76 | /** 77 | * Signals validation failure: we required "actual" value to be equal to 78 | * "expected", but it turned out that it's not. 79 | */ 80 | template 81 | class validation_not_equal_error: public validation_failed_error { 82 | public: 83 | validation_not_equal_error(const T& expected, const T& actual, const kstream* io, const std::string src_path): 84 | validation_failed_error("not equal", io, src_path), 85 | m_expected(expected), 86 | m_actual(actual) 87 | { 88 | } 89 | 90 | // "not equal, expected #{expected.inspect}, but got #{actual.inspect}" 91 | 92 | virtual ~validation_not_equal_error() KS_NOEXCEPT {}; 93 | 94 | protected: 95 | const T& m_expected; 96 | const T& m_actual; 97 | }; 98 | 99 | /** 100 | * Signals validation failure: we required "actual" value to be greater 101 | * than or equal to "min", but it turned out that it's not. 102 | */ 103 | template 104 | class validation_less_than_error: public validation_failed_error { 105 | public: 106 | validation_less_than_error(const T& min, const T& actual, const kstream* io, const std::string src_path): 107 | validation_failed_error("not in range", io, src_path), 108 | m_min(min), 109 | m_actual(actual) 110 | { 111 | } 112 | 113 | // "not in range, min #{min.inspect}, but got #{actual.inspect}" 114 | 115 | virtual ~validation_less_than_error() KS_NOEXCEPT {}; 116 | 117 | protected: 118 | const T& m_min; 119 | const T& m_actual; 120 | }; 121 | 122 | /** 123 | * Signals validation failure: we required "actual" value to be less 124 | * than or equal to "max", but it turned out that it's not. 125 | */ 126 | template 127 | class validation_greater_than_error: public validation_failed_error { 128 | public: 129 | validation_greater_than_error(const T& max, const T& actual, const kstream* io, const std::string src_path): 130 | validation_failed_error("not in range", io, src_path), 131 | m_max(max), 132 | m_actual(actual) 133 | { 134 | } 135 | 136 | // "not in range, max #{max.inspect}, but got #{actual.inspect}" 137 | 138 | virtual ~validation_greater_than_error() KS_NOEXCEPT {}; 139 | 140 | protected: 141 | const T& m_max; 142 | const T& m_actual; 143 | }; 144 | 145 | /** 146 | * Signals validation failure: we required "actual" value to be from 147 | * the list, but it turned out that it's not. 148 | */ 149 | template 150 | class validation_not_any_of_error: public validation_failed_error { 151 | public: 152 | validation_not_any_of_error(const T& actual, const kstream* io, const std::string src_path): 153 | validation_failed_error("not any of the list", io, src_path), 154 | m_actual(actual) 155 | { 156 | } 157 | 158 | // "not any of the list, got #{actual.inspect}" 159 | 160 | virtual ~validation_not_any_of_error() KS_NOEXCEPT {}; 161 | 162 | protected: 163 | const T& m_actual; 164 | }; 165 | 166 | } 167 | 168 | #endif -------------------------------------------------------------------------------- /cd/kaitaistruct.h: -------------------------------------------------------------------------------- 1 | #ifndef KAITAI_STRUCT_H 2 | #define KAITAI_STRUCT_H 3 | 4 | #include "kaitaistream.h" 5 | 6 | namespace kaitai { 7 | 8 | class kstruct { 9 | public: 10 | kstruct(kstream *_io) { m__io = _io; } 11 | virtual ~kstruct() {} 12 | protected: 13 | kstream *m__io; 14 | public: 15 | kstream *_io() { return m__io; } 16 | }; 17 | 18 | } 19 | 20 | #endif -------------------------------------------------------------------------------- /cdl/CDL_FileWriting.cpp: -------------------------------------------------------------------------------- 1 | #include "CDL_FileWriting.hpp" 2 | 3 | namespace codeDataLogger { 4 | std::string last_loaded_cdl; 5 | void copyOverOtherStatesDiffContents(std::ostream* file) { 6 | std::ifstream sourcecdlDiff(last_loaded_cdl.c_str(), std::ios_base::binary); 7 | for( std::string line; getline( sourcecdlDiff, line ); ) 8 | { 9 | printf("Line: %s",line.c_str()); 10 | *file << line << "\n"; 11 | } 12 | sourcecdlDiff.close(); 13 | } 14 | 15 | void writeInteger(std::ofstream* file, int num) { 16 | file->write(reinterpret_cast(&num), sizeof(num)); 17 | } 18 | 19 | void writeBlock(std::ofstream* file, const char *cdl_block, int size) { 20 | writeInteger(file,size); 21 | file->write(cdl_block, size); 22 | } 23 | 24 | void writeDataBytes(std::ostream* file, int start_range_address, int range_size, unsigned char* memory) { 25 | //*file << std::hex; 26 | for (int address =start_range_address; address < start_range_address+range_size; address++) { 27 | //*file << "0x"; 28 | *file << (unsigned int)memory[address]; 29 | if (address+1 < start_range_address+range_size) 30 | *file << ","; 31 | } 32 | //*file << std::dec; 33 | } 34 | 35 | // 36 | // # Reading Data 37 | // 38 | 39 | uint8_t readInteger8(std::ifstream* file) { 40 | uint8_t a; 41 | file->read (reinterpret_cast(&a), sizeof(a)); 42 | return a; 43 | } 44 | 45 | uint32_t readInteger32(std::ifstream* file) { 46 | uint32_t a; 47 | file->read (reinterpret_cast(&a), sizeof(a)); 48 | return a; 49 | } 50 | 51 | std::string readString(std::ifstream* file, int num) { 52 | std::string s(num /*bytes*/, '\0' /*initial content - irrelevant*/); 53 | file->read(&s[0], num /*bytes*/); 54 | return s; 55 | } 56 | 57 | void readBlock(std::ifstream* file, char* buffer) { 58 | 59 | uint8_t strSize = readInteger8(file); 60 | printf("string size: %d %d",(int) strSize, (int)file->tellg()); 61 | std::string s = readString(file, strSize); 62 | printf("Block Name: %s",s.c_str()); 63 | 64 | int size = readInteger32(file); 65 | printf("Block Size: %d",(int)size); 66 | file->read(buffer, size); 67 | } 68 | 69 | std::string readFileToString(std::string file_path) { 70 | std::ifstream t(file_path); 71 | std::string str; 72 | if (!t.good()) { return "File not found"; } 73 | 74 | t.seekg(0, std::ios::end); 75 | str.reserve(t.tellg()); 76 | t.seekg(0, std::ios::beg); 77 | 78 | str.assign((std::istreambuf_iterator(t)), 79 | std::istreambuf_iterator()); 80 | return str; 81 | } 82 | 83 | void writeStringToFile(std::string file_path, std::string contents) { 84 | std::ofstream out(file_path); 85 | if (!out.good()) { std::cout << "File not found" << file_path << "\n"; } 86 | out << contents; 87 | out.close(); 88 | } 89 | 90 | void appendStringToFile(std::string file_path, std::string contents) { 91 | std::ofstream out; 92 | out.open(file_path, std::ios_base::app); // append instead of overwrite 93 | if (!out.good()) { std::cout << "File not found" << file_path << "\n"; } 94 | out << contents; 95 | out.close(); 96 | } 97 | 98 | std::string dirnameOf(const std::string& fname) 99 | { 100 | size_t pos = fname.find_last_of("\\/"); 101 | return (std::string::npos == pos) 102 | ? "" 103 | : fname.substr(0, pos); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /cdl/CDL_FileWriting.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CDL_FileWriting_hpp 2 | #define CDL_FileWriting_hpp 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace codeDataLogger { 14 | void copyOverOtherStatesDiffContents(std::ostream* file); 15 | void writeInteger(std::ofstream* file, int num); 16 | void writeBlock(std::ofstream* file, const char *cdl_block, int size); 17 | uint8_t readInteger8(std::ifstream* file); 18 | uint32_t readInteger32(std::ifstream* file); 19 | std::string readString(std::ifstream* file, int num); 20 | std::string readFileToString(std::string file_path); 21 | void writeStringToFile(std::string file_path, std::string contents); 22 | void appendStringToFile(std::string file_path, std::string contents); 23 | void readBlock(std::ifstream* file, char* buffer); 24 | void writeDataBytes(std::ostream* file, int start_range_address, int range_size, unsigned char* memory); 25 | void writeDataBytes(const std::ofstream& file, int start_range_address, int range_size, unsigned char* memory); 26 | std::string dirnameOf(const std::string& fname); 27 | } 28 | #endif /* CDL_FileWriting_hpp */ 29 | -------------------------------------------------------------------------------- /cdl/CDL_JSON.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "nlohmann/json.hpp" 11 | using json = nlohmann::json; 12 | using namespace std; 13 | #include "CDL.hpp" 14 | 15 | 16 | json fileConfig; 17 | json reConfig; 18 | 19 | std::map rsp_reads; 20 | std::map rdram_reads; 21 | std::map tlbs; 22 | std::map dmas = std::map(); 23 | std::map jumps; 24 | std::map audio_address; 25 | std::map audio_samples; 26 | std::map cart_rom_dma_writes; 27 | std::map dma_sp_writes; 28 | std::map labels; // Deprecated: Should now use functions 29 | // cdl_labels functions is not playthrough specific 30 | std::map functions; 31 | 32 | std::map jump_returns; 33 | std::map function_signatures; 34 | std::map cached_jumps; 35 | std::map memory_to_log; 36 | 37 | std::streampos fileSize( const char* filePath ){ 38 | 39 | std::streampos fsize = 0; 40 | std::ifstream file( filePath, std::ios::binary ); 41 | 42 | fsize = file.tellg(); 43 | file.seekg( 0, std::ios::end ); 44 | fsize = file.tellg() - fsize; 45 | file.close(); 46 | 47 | return fsize; 48 | } 49 | 50 | void readJsonToObject(string filename, json& json_object, string default_json) { 51 | // printf("readJsonToObject %s", filename.c_str()); 52 | long sizeOfFile = fileSize(filename.c_str()); 53 | if (sizeOfFile < 0) { 54 | printf("WARN: Size of file was Negative: %d \n", sizeOfFile); 55 | json_object = json::parse(default_json); 56 | return; 57 | } 58 | std::ifstream i(filename); 59 | if (!i.good()) { 60 | printf("WARNING: readJsonToObject Failed to load file: %s \n", filename.c_str()); 61 | json_object = json::parse(default_json); 62 | return; 63 | } 64 | json temp_json = {}; 65 | try { 66 | i >> temp_json; 67 | } catch(...) { 68 | std::cerr << "WARNING: json error with file:" << filename << std::endl; 69 | json_object = json::parse("{}"); 70 | return; 71 | } 72 | if (temp_json == NULL) { 73 | return; 74 | } 75 | string dump = temp_json.dump(); 76 | if (temp_json != NULL && dump != "null") { 77 | // printf("Loading %s as: %s \n", dump.c_str(), filename.c_str()); 78 | json_object = temp_json; 79 | } 80 | } 81 | 82 | void saveJsonToFile(string filename, json& json_object) { 83 | // cout << "Saving: " << filename << std::endl; 84 | string dump = json_object.dump(2); 85 | if (dump == "null" || dump == "{}") { 86 | cout << "WARN: Nothing to write for file" + filename; 87 | return; 88 | } 89 | std::ofstream o(filename); 90 | if (o.good()) { 91 | o << dump; 92 | } else { 93 | cout << "ERROR: Failed to write file: " + filename << std::endl; 94 | } 95 | cout << "INFO: Save Successful: " + filename; 96 | // cout << "Saved this:" << dump << std::endl; //Used for debugging only 97 | } 98 | 99 | void save_dram_rw_to_json() { 100 | // Note if you save it here you might want to also update readJsonFromFile() 101 | fileConfig["rsp_reads"] = rsp_reads; 102 | fileConfig["rdram_reads"] = rdram_reads; 103 | fileConfig["tlbs"] = tlbs; 104 | fileConfig["dmas"] = dmas; 105 | fileConfig["jumps"] = jumps; 106 | //fileConfig["jump_data"] = jump_data; 107 | fileConfig["audio_samples"] = audio_samples; 108 | fileConfig["cart_rom_dma_writes"] = cart_rom_dma_writes; 109 | fileConfig["dma_sp_writes"] = dma_sp_writes; 110 | fileConfig["labels"] = labels; 111 | fileConfig["function_signatures"] = function_signatures; 112 | fileConfig["cached_jumps"] = cached_jumps; 113 | fileConfig["memory_to_log"] = memory_to_log; 114 | fileConfig["audio_address"] = audio_address; 115 | // fileConfig["addresses"] = addresses; 116 | } -------------------------------------------------------------------------------- /cdl/CDL_MemoryMapper.cpp: -------------------------------------------------------------------------------- 1 | // #include "gambatte.h" 2 | // #include "mem/cartridge.h" 3 | #include "CDL_MemoryMapper.hpp" 4 | 5 | void CDL_PrintMemoryLoc(uint32_t address) {//, void* mem_base) { 6 | unsigned char* bytes = ((uint8_t*) address); 7 | // printf("\nBytes: %x %x %x %x ",bytes[3], bytes[2], bytes[1], bytes[0]); 8 | // printf("\nBytes: %x %x %x %x ",mem[3], mem[2], mem[1], mem[0]); 9 | // printf("\nAddress: %d ",268435456-address); 10 | // mem_base = MEM_BASE_PTR(mem_base); 11 | // if (address < RDRAM_MAX_SIZE) { 12 | // printf("RDRAM: %d \n", address); 13 | // //mem = (uint32_t*)((uint8_t*)mem_base + (address - MM_RDRAM_DRAM + MB_RDRAM_DRAM)); 14 | // } 15 | // else if (address >= MM_CART_ROM) { 16 | // printf("CART ROM %d \n", address); 17 | // } 18 | // else if ((address & UINT32_C(0xfe000000)) == MM_DD_ROM) { 19 | // printf("DD ROM %d \n", address); 20 | // } 21 | // else if ((address & UINT32_C(0xffffe000)) == MM_RSP_MEM) { 22 | // printf("Reality Signal Processor MEM %d \n", address); 23 | // } 24 | // else { 25 | // printf("UNKNOWN: %d \n", address); 26 | // } 27 | } 28 | 29 | namespace codeDataLogger { 30 | // P is address of memory we want to access 31 | // cart is CDL_Platform to access memory 32 | CDMapResult CDMap(const unsigned P, CDL_Platform* cart) 33 | { 34 | printf("TODO: map P"); 35 | CDMapResult ret = { eCDLog_AddrType_None }; 36 | return ret; 37 | // if(P<0x4000) 38 | // { 39 | // // 40 | // // First ROM Bank (fixed) 41 | // // 42 | // CDMapResult ret = { eCDLog_AddrType_ROM, P }; 43 | // return ret; 44 | // } 45 | // else if(P<0x8000) 46 | // { 47 | // // 48 | // // Switchable ROM bank 1+ 49 | // // 50 | // unsigned bank = cart->rmem(P>>12) - cart->rmem(0); 51 | // unsigned addr = P+bank; 52 | // CDMapResult ret = { eCDLog_AddrType_ROM, addr }; 53 | // return ret; 54 | // } 55 | // else if (P<0x9800) { 56 | // // 57 | // // Character RAM (Tiles) 58 | // // 59 | // CDMapResult ret = {eCDLog_AddrType_TileRAM, P}; 60 | // return ret; 61 | // } 62 | // else if (P< 0x9C00) { 63 | // // 64 | // // BG Map Data 1 65 | // // 66 | // CDMapResult ret = {eCDLog_AddrType_BGMap, P}; 67 | // return ret; 68 | 69 | // } 70 | // else if(P<0xA000) { 71 | // // 72 | // // BG Map Data 2 73 | // CDMapResult ret = {eCDLog_AddrType_BGMap, P}; 74 | // return ret; 75 | // } 76 | // else if(P<0xC000) 77 | // { 78 | // // Extendible RAM on cartridge 79 | // if(cart->wsrambankptr()) 80 | // { 81 | // //not bankable. but. we're not sure how much might be here 82 | // unsigned char *data; 83 | // int length; 84 | // bool has = cart->getMemoryArea(3,&data,&length); 85 | // unsigned addr = P&(length-1); 86 | // if(has && length!=0) 87 | // { 88 | // CDMapResult ret = { eCDLog_AddrType_CartRAM, addr }; 89 | // return ret; 90 | // } 91 | // } 92 | // } 93 | // else if(P<0xE000) 94 | // { 95 | // // Working RAM (multiple banks) 96 | // unsigned bank = cart->wramdata(P >> 12 & 1) - cart->wramdata(0); 97 | // unsigned addr = (P&0xFFF)+bank; 98 | // CDMapResult ret = { eCDLog_AddrType_WRAM, addr }; 99 | // return ret; 100 | // } 101 | // else if (P>=0xFE00 && P<=0xFE9F) { 102 | // CDMapResult ret = {eCDLog_AddrType_OAM, P}; 103 | // return ret; 104 | // } 105 | // else if (P>=0xFF10 && P<=0xFF26) { 106 | // CDMapResult ret = {eCDLog_AddrType_Sound, P}; 107 | // return ret; 108 | // } 109 | 110 | // else if (P>=0xFF26 && P<=0xFF3F) { 111 | // CDMapResult ret = {eCDLog_AddrType_Sound, P}; 112 | // return ret; 113 | // } 114 | // else if(P<0xFF80) {} 115 | // else 116 | // { 117 | // ////this is just for debugging, really, it's pretty useless 118 | // // CDMapResult ret = { eCDLog_AddrType_HRAM, (P-0xFF80) }; 119 | // // return ret; 120 | // } 121 | 122 | // CDMapResult ret = { eCDLog_AddrType_None }; 123 | // return ret; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /cdl/CDL_MemoryMapper.hpp: -------------------------------------------------------------------------------- 1 | #ifndef CDL_MemoryMapper_hpp 2 | #define CDL_MemoryMapper_hpp 3 | 4 | #include 5 | #include "codeDataLogger.hpp" 6 | namespace codeDataLogger { 7 | // 8 | // # CodeDataLogger Mapping (which memory address is being referenced) 9 | // 10 | struct CDMapResult 11 | { 12 | eCDLog_AddrType type; 13 | unsigned addr; 14 | }; 15 | 16 | // 17 | // # CDL_Platform 18 | // 19 | struct CDL_Platform 20 | { 21 | char* platformName; 22 | unsigned memory; 23 | }; 24 | 25 | CDMapResult CDMap(const unsigned P, CDL_Platform* cart); 26 | 27 | } 28 | 29 | #endif /* CDL_MemoryMapper_hpp */ 30 | -------------------------------------------------------------------------------- /cdl/Image.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../civetweb/include/civetweb.h" 3 | #include "../include/libRR.h" 4 | #include "../png/lodepng.h" 5 | #include "CDL.hpp" 6 | #ifdef _WIN32 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | extern "C" 13 | { 14 | enum retro_pixel_format libRR_core_pixel_format = RETRO_PIXEL_FORMAT_XRGB8888; 15 | 16 | void libRR_create_png(string filename, libRR_frame_buffer libRR_current_frame_buffer) 17 | { 18 | unsigned int pitch = libRR_current_frame_buffer.pitch; 19 | unsigned int width = libRR_current_frame_buffer.width; 20 | unsigned int height = libRR_current_frame_buffer.height; 21 | unsigned char *data = (unsigned char *)libRR_current_frame_buffer.fb; 22 | if (data == NULL) 23 | { 24 | printf("Warning data was NULL \n"); 25 | return; 26 | } 27 | std::vector image; 28 | int png_bytes_per_pixel = 4; 29 | image.resize(width * height * png_bytes_per_pixel); 30 | 31 | if (libRR_core_pixel_format == RETRO_PIXEL_FORMAT_XRGB8888) { 32 | 33 | for (unsigned y = 0; y < height; y++) { 34 | for (unsigned x = 0; x < width; x++) 35 | { 36 | image[png_bytes_per_pixel * width * y + png_bytes_per_pixel * x + 0] = data[pitch * y + png_bytes_per_pixel * x + 2]; // Red 37 | image[png_bytes_per_pixel * width * y + png_bytes_per_pixel * x + 1] = data[pitch * y + png_bytes_per_pixel * x + 1]; // Green 38 | image[png_bytes_per_pixel * width * y + png_bytes_per_pixel * x + 2] = data[pitch * y + png_bytes_per_pixel * x + 0]; // Blue 39 | image[png_bytes_per_pixel * width * y + png_bytes_per_pixel * x + 3] = 255; // Alpha 40 | } 41 | } 42 | } else if (libRR_core_pixel_format == RETRO_PIXEL_FORMAT_RGB565) { 43 | pitch = pitch/2; 44 | for (unsigned y = 0; y < height; y++) { 45 | 46 | for (unsigned x = 0; x < width; x++) 47 | { 48 | uint16_t pixel = ((uint16_t*)data)[pitch * y + 1 * x + 0]; 49 | uint8_t b = (pixel >> 0) & 0x1f; 50 | uint8_t g = (pixel >> 5) & 0x3f; 51 | uint8_t r = (pixel >> 11) & 0x1f; 52 | 53 | image[(png_bytes_per_pixel * width * y) + (png_bytes_per_pixel * x) + 0] = (r << 3) | (r >> 2); // Red 54 | image[png_bytes_per_pixel * width * y + png_bytes_per_pixel * x + 1] = (g << 2) | (g >> 4); // Green 55 | image[png_bytes_per_pixel * width * y + png_bytes_per_pixel * x + 2] = (b << 3) | (b >> 2); // Blue 56 | image[png_bytes_per_pixel * width * y + png_bytes_per_pixel * x + 3] = 255; // Alpha 57 | 58 | } 59 | } 60 | 61 | } else { 62 | printf("ERROR: Can't generate PNG due to unsupported pixel formart in core\n"); 63 | } 64 | 65 | 66 | //Encode the image 67 | unsigned error = lodepng::encode(filename, image, width, height); 68 | 69 | //if there's an error, display it 70 | if (error) 71 | std::cout << "encoder error " << error << ": " << lodepng_error_text(error) << std::endl; 72 | } 73 | } -------------------------------------------------------------------------------- /cdl/Interpreter.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/libRR.h" 2 | #include 3 | #include "CDL.hpp" 4 | 5 | #ifdef EMSCRIPTEN 6 | // Emscripten doesn't need a javascript parser 7 | #else 8 | #include "../interpreter/duktape/duktape.h" 9 | #include "../interpreter/mjs/mjs.h" 10 | #endif 11 | 12 | #ifdef EMSCRIPTEN 13 | 14 | void run_in_duktape(string code) { 15 | // Emscripten version, call out to JS 16 | } 17 | 18 | void run_in_mjs(string code) { 19 | // Emscripten version, call out to JS 20 | } 21 | 22 | #else 23 | static duk_ret_t native_print(duk_context *ctx) { 24 | printf("%s\n", duk_to_string(ctx, 0)); 25 | return 0; /* no return value (= undefined) */ 26 | } 27 | 28 | void run_in_duktape(string code) { 29 | printf("About to run code: %s in DUKTAPE \n", code.c_str()); 30 | duk_context *ctx = duk_create_heap_default(); 31 | 32 | duk_push_c_function(ctx, native_print, 1 /*nargs*/); 33 | duk_put_global_string(ctx, "print"); 34 | 35 | duk_eval_string(ctx, code.c_str()); 36 | printf("%s=%d\n", code.c_str(), (int) duk_get_int(ctx, -1)); 37 | 38 | duk_eval_string_noresult(ctx, "function abc() { return 'hi';}; print('hello '+abc());"); 39 | 40 | duk_destroy_heap(ctx); 41 | } 42 | 43 | void *my_dlsym(void *handle, const char *name) { 44 | if (strcmp(name, "libRR_get_current_lba") == 0) return (void*)libRR_get_current_lba; 45 | if (strcmp(name, "libRR_get_current_buffer") == 0) return (void*)libRR_get_current_buffer; 46 | if (strcmp(name, "memset") == 0) return (void*)memset; 47 | if (strcmp(name, "libRR_memset") == 0) return (void*)libRR_memset; 48 | if (strcmp(name, "libRR_replace_lba_buffer") == 0) return (void*)libRR_replace_lba_buffer; 49 | 50 | return NULL; 51 | } 52 | 53 | void run_in_mjs(string code) { 54 | struct mjs *mjs = mjs_create(); 55 | mjs_set_ffi_resolver(mjs, my_dlsym); 56 | mjs_exec(mjs, code.c_str(), NULL); 57 | } 58 | #endif 59 | 60 | #define ENGINE_DUKTAPE 0 61 | #define ENGINE_MJS 1 62 | int current_engine = ENGINE_MJS; 63 | 64 | string code_prefix = "let lba = ffi('int libRR_get_current_lba()')(); let buffer = ffi('void* libRR_get_current_buffer()')(); let memset = ffi('void libRR_memset(int, int, int)'); let replace_lba = ffi('void libRR_replace_lba_buffer(int)');"; 65 | 66 | void libRR_run_script(string code) { 67 | // printf("About to run code: %s \n", (code_prefix+code).c_str()); 68 | if (current_engine == ENGINE_DUKTAPE) { 69 | run_in_duktape(code_prefix+code); 70 | } else if (current_engine == ENGINE_MJS) { 71 | run_in_mjs(code_prefix+code); 72 | } 73 | } -------------------------------------------------------------------------------- /cdl/Main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../civetweb/include/civetweb.h" 3 | #include "../include/libRR.h" 4 | #include "CDL.hpp" 5 | #include //for using the function sleep 6 | #ifdef _WIN32 7 | #include 8 | #else 9 | #include 10 | #endif 11 | 12 | // Common Variables 13 | int l_CurrentFrame; 14 | bool isPaused = false; 15 | extern retro_environment_t environ_cb; 16 | extern double libRR_playback_speed; 17 | 18 | extern "C" { 19 | unsigned int RRCurrentFrame = 0; 20 | long long total_time_elapsed = 0; 21 | 22 | void frame_time_callback(retro_usec_t usec) { 23 | total_time_elapsed += usec; 24 | } 25 | 26 | bool already_setup_timing = false; 27 | retro_frame_time_callback frame_cb = {}; 28 | void setup_frame_timing() { 29 | frame_cb.callback = &frame_time_callback; 30 | frame_cb.reference = 1000000; 31 | environ_cb(RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK, &frame_cb); 32 | already_setup_timing = true; 33 | } 34 | 35 | #ifdef EMSCRIPTEN 36 | __attribute__((export_name("libRR_run_frame"))) 37 | #endif 38 | bool libRR_run_frame() { 39 | if (libRR_playback_speed != 100) { 40 | // This allows us to control playback speed from the core 41 | if (!already_setup_timing) { 42 | setup_frame_timing(); 43 | } 44 | double fps = 60 * (libRR_playback_speed/100.0); 45 | double target_time_per_frame = 1000000.0/fps; 46 | if (total_time_elapsed < target_time_per_frame) { 47 | #ifdef _WIN32 48 | Sleep(1); 49 | #else 50 | sleep(1); 51 | #endif 52 | return false; 53 | } 54 | total_time_elapsed = 0; 55 | } 56 | 57 | 58 | // Check if reached end of what player wants to run 59 | if (libRR_settings["endAt"] == RRCurrentFrame) { 60 | // should now check the action to see if we pause or loop 61 | if (libRR_settings["loopFrame"] == 0) { 62 | // restart game 63 | libRR_reset(0); 64 | retro_reset(); 65 | } 66 | else if (libRR_settings["loopFrame"] > 0) { 67 | printf("Time to loop back to state: %d\n", (int)libRR_settings["loopFrame"]); 68 | libRR_load_save_state(libRR_settings["loopFrame"]); 69 | return !libRR_settings["paused"]; 70 | } else { 71 | printf("User wanted to pause after this frame\n"); 72 | libRR_settings["paused"] = true; 73 | } 74 | } 75 | 76 | // Check if paused from the UI 77 | if (!libRR_settings["paused"]) { 78 | // printf("libRR_run_frame number:%u Settings: %s \n", RRCurrentFrame, libRR_settings.dump().c_str()); // useful for debugging 79 | RRCurrentFrame++; 80 | } else { 81 | #ifdef _WIN32 82 | Sleep(1); 83 | #else 84 | sleep(10000); 85 | #endif 86 | } 87 | // printf("Current frame: %d\n", RRCurrentFrame); 88 | return !libRR_settings["paused"]; 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /cdl/codeDataLogger.hpp: -------------------------------------------------------------------------------- 1 | #ifndef codeDataLogger_hpp 2 | #define codeDataLogger_hpp 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace codeDataLogger { 14 | bool writeExample(); 15 | bool writeCDL( const std::string &filename, const std::string cdlpath); 16 | bool loadCDL( const std::string &filename, const std::string &cdlpath); 17 | void differenceBetweenCurrentAndPreviousMemory(std::ostream* file, bool dumpWholeROM, int memory_size, unsigned char* current_memory, unsigned char* old_memory, bool (*shouldWriteBlock)(int,int,int,int,int), unsigned char* non_mask_memory); 18 | 19 | void calculateCDLStatistics(const std::string &filename, bool writeToFile, bool wholeROM); 20 | 21 | enum eCDLog_AddrType 22 | { 23 | eCDLog_AddrType_ROM, eCDLog_AddrType_HRAM, eCDLog_AddrType_WRAM, eCDLog_AddrType_CartRAM, 24 | eCDLog_AddrType_None, eCDLog_AddrType_TileRAM, eCDLog_AddrType_BGMap,eCDLog_AddrType_OAM, 25 | eCDLog_AddrType_Sound 26 | }; 27 | 28 | enum eCodeLog_Flags 29 | { 30 | eCodeLog_Flags_Jump_True = 1, 31 | eCodeLog_Flags_Jump_False = 2 32 | }; 33 | 34 | // Might also be useful to count the cycles for each byte of code 35 | 36 | enum eCDLog_Flags 37 | { 38 | eCDLog_Flags_ExecFirst = 1, 39 | eCDLog_Flags_ExecOperand = 2, 40 | eCDLog_Flags_Data = 4, 41 | eCDLog_Flags_BlockEnd = 8, 42 | //eCDLog_Flags_BlockStart = 8, 43 | //eCDLog_Flags_BlockEnd = 16, 44 | eCDLog_Flags_Graphics = 16, 45 | eCDLog_Flags_BGMap = 32, 46 | eCDLog_Flags_OAM = 64, 47 | eCDLog_Flags_Sound = 128, 48 | eCDLog_Flags_None = 99 49 | }; 50 | typedef void (*CDCallback)(int32_t addr, eCDLog_AddrType addrtype, eCDLog_Flags flags); 51 | } 52 | 53 | #endif /* codeDataLogger_hpp */ 54 | -------------------------------------------------------------------------------- /cdl/jarowinkler.c: -------------------------------------------------------------------------------- 1 | /* c: jarowinkler.c 2 | * Copyright (C) 2011 Miguel Serrano 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | 20 | #define SCALING_FACTOR 0.1 21 | 22 | static int max(int x, int y) { 23 | return x > y ? x : y; 24 | } 25 | 26 | static int min(int x, int y) { 27 | return x < y ? x : y; 28 | } 29 | 30 | double jaro_winkler_distance(const char *s, const char *a) { 31 | int i, j, l; 32 | int m = 0, t = 0; 33 | int sl = strlen(s); 34 | int al = strlen(a); 35 | int sflags[sl], aflags[al]; 36 | int range = max(0, max(sl, al) / 2 - 1); 37 | double dw; 38 | 39 | if (!sl || !al) 40 | return 0.0; 41 | 42 | for (i = 0; i < al; i++) 43 | aflags[i] = 0; 44 | 45 | for (i = 0; i < sl; i++) 46 | sflags[i] = 0; 47 | 48 | /* calculate matching characters */ 49 | for (i = 0; i < al; i++) { 50 | for (j = max(i - range, 0), l = min(i + range + 1, sl); j < l; j++) { 51 | if (a[i] == s[j] && !sflags[j]) { 52 | sflags[j] = 1; 53 | aflags[i] = 1; 54 | m++; 55 | break; 56 | } 57 | } 58 | } 59 | 60 | if (!m) 61 | return 0.0; 62 | 63 | /* calculate character transpositions */ 64 | l = 0; 65 | for (i = 0; i < al; i++) { 66 | if (aflags[i] == 1) { 67 | for (j = l; j < sl; j++) { 68 | if (sflags[j] == 1) { 69 | l = j + 1; 70 | break; 71 | } 72 | } 73 | if (a[i] != s[j]) 74 | t++; 75 | } 76 | } 77 | t /= 2; 78 | 79 | /* Jaro distance */ 80 | dw = (((double)m / sl) + ((double)m / al) + ((double)(m - t) / m)) / 3.0; 81 | 82 | /* calculate common string prefix up to 4 chars */ 83 | l = 0; 84 | for (i = 0; i < min(min(sl, al), 4); i++) 85 | if (s[i] == a[i]) 86 | l++; 87 | 88 | /* Jaro-Winkler distance */ 89 | dw = dw + (l * SCALING_FACTOR * (1 - dw)); 90 | 91 | return dw; 92 | } -------------------------------------------------------------------------------- /civetweb/src/libRREmscriptenInterface.cpp: -------------------------------------------------------------------------------- 1 | #include "../../cdl/CDL.hpp" 2 | #include 3 | #include "../../include/libRR.h" 4 | #include 5 | 6 | void setup_web_server() { 7 | printf("Setting up web server not required with Emscripten \n"); 8 | } 9 | 10 | void stop_web_server() { 11 | // Not required with Emscripten 12 | } -------------------------------------------------------------------------------- /consoles/DummyConsole.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../civetweb/include/civetweb.h" 3 | #include "../include/libRR.h" 4 | #include "../cdl/CDL.hpp" 5 | #include "../cdl/CDL_FileWriting.hpp" 6 | #include "../source_exporter/CommonSourceExport.h" 7 | 8 | extern "C" { 9 | 10 | string get_slot_for_address(int32_t offset) { 11 | return "0"; 12 | } 13 | 14 | string write_console_asm_header() { 15 | string contents = ""; 16 | return contents; 17 | } 18 | 19 | void libRR_direct_serialize(void *data, size_t size) { 20 | // TODO: implement this as a save function that is called internally just to save 21 | retro_serialize(data, size); 22 | } 23 | 24 | bool libRR_direct_unserialize(const void *data, size_t size) { 25 | // TODO: implement this properly 26 | retro_unserialize(data, size); 27 | } 28 | 29 | // The following are only needed for consoles with CDs 30 | string retro_cd_base_directory = "libRR_RememberToSetCDBase"; 31 | string retro_cd_path = "libRR_RememberToSetCDPATH"; 32 | string retro_cd_base_name = "libRR_RememberToBaseName"; 33 | 34 | const char* libRR_console = "Dummy"; 35 | 36 | struct retro_memory_map libRR_retromap = { 0 }; 37 | 38 | struct retro_memory_descriptor libRR_mmap[0]; 39 | int libRR_mmap_descriptors = 0; 40 | int libRR_emulated_hardware = 0; // only used for emulators that support multiple consoles e.g GameGear/MasterSystem 41 | 42 | // Delay slot variables 43 | uint32_t libRR_delay_slot_pc = 0; 44 | bool libRR_isDelaySlot = false; 45 | 46 | // Bank switching 47 | uint32_t libRR_bank_size = 0; 48 | uint16_t libRR_current_bank_slot_0 = 1; 49 | uint16_t libRR_current_bank_slot_1 = 2; 50 | uint16_t libRR_current_bank_slot_2 = 3; 51 | uint32_t libRR_slot_0_max_addr = 0x4000; 52 | uint32_t libRR_slot_1_max_addr = 0x7fff; 53 | uint32_t libRR_slot_2_max_addr = 0x7fff; 54 | bool libRR_bank_switching_available = false; 55 | 56 | uint32_t libRR_pc_lookahead = 0; 57 | 58 | void libRR_setup_console_details(retro_environment_t environ_cb) { 59 | printf("TODO: Setup setting such as libRR_define_console_memory_region for this console\n"); 60 | // libRR_set_retro_memmap(environ_cb); 61 | } 62 | 63 | // libRR_set_retro_memmap should be called to setup memory ranges in a function such as retro_set_memory_maps 64 | void libRR_set_retro_memmap(retro_memory_descriptor* descs, int num_descriptors) 65 | { 66 | for (int i=0; i<=10; i++) { 67 | libRR_mmap[i] = descs[i]; 68 | } 69 | libRR_retromap.descriptors = libRR_mmap; 70 | libRR_retromap.num_descriptors = num_descriptors; 71 | } 72 | 73 | int get_current_bank_number_for_address(uint32_t addr) { 74 | return 0; 75 | } 76 | 77 | void console_log_jump_return(int take_jump, uint32_t jump_target, uint32_t pc, uint32_t ra, int64_t* registers, void* r4300) { 78 | printf("%d\n",1); 79 | } 80 | 81 | void main_state_load(const char *filename) 82 | { 83 | // TODO: actually load the state here 84 | } 85 | 86 | void main_state_save(int format, const char *filename) 87 | { 88 | // TODO: actually load the state here 89 | } 90 | 91 | void add_console_specific_game_json() { 92 | // TODO: Add special value to game_json e.g: 93 | // game_json["VDP2"]["TVMD"]["DisplayOn"] = VDP2::DisplayOn; 94 | } 95 | 96 | void write_rom_mapping() { 97 | } 98 | 99 | void libRR_export_all_files() { 100 | printf("Dummy: Export All files to Reversing Project, depends on which core we are using"); 101 | } 102 | 103 | } 104 | 105 | -------------------------------------------------------------------------------- /consoles/PS1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../civetweb/include/civetweb.h" 3 | #include "../include/libRR.h" 4 | #include "../cdl/CDL.hpp" 5 | #include "../cdl/CDL_FileWriting.hpp" 6 | #include "../source_exporter/CommonSourceExport.h" 7 | 8 | extern "C" { 9 | 10 | string get_slot_for_address(int32_t offset) { 11 | return "0"; 12 | } 13 | 14 | string write_console_asm_header() { 15 | string contents = ""; 16 | return contents; 17 | } 18 | 19 | void libRR_direct_serialize(void *data, size_t size) { 20 | // TODO: implement this as a save function that is called internally just to save 21 | retro_serialize(data, size); 22 | } 23 | 24 | bool libRR_direct_unserialize(const void *data, size_t size) { 25 | // TODO: implement this properly 26 | retro_unserialize(data, size); 27 | } 28 | 29 | // The following are only needed for consoles with CDs 30 | string retro_cd_path = "libRR_RememberToSetCDPATH"; 31 | 32 | const char* libRR_console = "PS1"; 33 | 34 | struct retro_memory_map libRR_retromap = { 0 }; 35 | 36 | struct retro_memory_descriptor libRR_mmap[0]; 37 | int libRR_mmap_descriptors = 0; 38 | int libRR_emulated_hardware = 0; // only used for emulators that support multiple consoles e.g GameGear/MasterSystem 39 | 40 | // Delay slot variables 41 | uint32_t libRR_delay_slot_pc = 0; 42 | bool libRR_isDelaySlot = false; 43 | 44 | // Bank switching 45 | uint32_t libRR_bank_size = 0; 46 | uint16_t libRR_current_bank_slot_0 = 1; 47 | uint16_t libRR_current_bank_slot_1 = 2; 48 | uint16_t libRR_current_bank_slot_2 = 3; 49 | uint32_t libRR_slot_0_max_addr = 0x4000; 50 | uint32_t libRR_slot_1_max_addr = 0x7fff; 51 | uint32_t libRR_slot_2_max_addr = 0x7fff; 52 | bool libRR_bank_switching_available = false; 53 | 54 | uint32_t libRR_pc_lookahead = 0; 55 | 56 | void libRR_setup_console_details(retro_environment_t environ_cb) { 57 | printf("TODO: Setup setting such as libRR_define_console_memory_region for this console\n"); 58 | // libRR_set_retro_memmap(environ_cb); 59 | } 60 | 61 | // libRR_set_retro_memmap should be called to setup memory ranges in a function such as retro_set_memory_maps 62 | void libRR_set_retro_memmap(retro_memory_descriptor* descs, int num_descriptors) 63 | { 64 | for (int i=0; i<=10; i++) { 65 | libRR_mmap[i] = descs[i]; 66 | } 67 | libRR_retromap.descriptors = libRR_mmap; 68 | libRR_retromap.num_descriptors = num_descriptors; 69 | } 70 | 71 | int get_current_bank_number_for_address(uint32_t addr) { 72 | return 0; 73 | } 74 | 75 | void console_log_jump_return(int take_jump, uint32_t jump_target, uint32_t pc, uint32_t ra, int64_t* registers, void* r4300) { 76 | printf("%d\n",1); 77 | } 78 | 79 | void main_state_load(const char *filename) 80 | { 81 | // TODO: actually load the state here 82 | } 83 | 84 | void main_state_save(int format, const char *filename) 85 | { 86 | // TODO: actually load the state here 87 | } 88 | 89 | void add_console_specific_game_json() { 90 | // TODO: Add special value to game_json e.g: 91 | // game_json["VDP2"]["TVMD"]["DisplayOn"] = VDP2::DisplayOn; 92 | } 93 | 94 | void write_rom_mapping() { 95 | } 96 | 97 | void libRR_export_all_files() { 98 | printf("Dummy: Export All files to Reversing Project, depends on which core we are using"); 99 | } 100 | 101 | } 102 | 103 | -------------------------------------------------------------------------------- /consoles/Saturn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../civetweb/include/civetweb.h" 3 | #include "../include/libRR.h" 4 | #include "../cdl/CDL.hpp" 5 | 6 | // Common Variables 7 | 8 | namespace VDP2 9 | { 10 | extern uint16_t* RawRegs; 11 | // TVMD Registers - TV Mode 12 | extern bool BorderMode; 13 | extern bool DisplayOn; 14 | extern uint8_t InterlaceMode; 15 | extern uint8_t HRes, VRes; 16 | 17 | // Exten registers - Extension? 18 | extern bool ExSyncEnable; 19 | extern bool ExLatchEnable; 20 | extern bool ExBGEnable; 21 | extern bool DispAreaSelect; 22 | 23 | extern bool VRAMSize; 24 | 25 | extern uint16_t RAMCTL_Raw; 26 | extern uint8_t CRAM_Mode; 27 | } 28 | 29 | extern "C" { 30 | 31 | void libRR_direct_serialize(void *data, size_t size) { 32 | // TODO: implement this as a save function that is called internally just to save 33 | retro_serialize(data, size); 34 | } 35 | 36 | bool libRR_direct_unserialize(const void *data, size_t size) { 37 | // TODO: implement this properly 38 | retro_unserialize(data, size); 39 | } 40 | 41 | void libRR_log_branch(uint32_t current_pc, uint32_t target_pc) { 42 | 43 | } 44 | const char* libRR_console = "Saturn"; 45 | 46 | // libRR_pc_lookahead is used to subtract from the Program counter in order to get the actual location of the Return instruction 47 | // For saturn we remove 2 from the program counter, but this will vary per console 48 | // we only want to return 2 and not 4 because we want to include the delay slot instruction 49 | uint32_t libRR_pc_lookahead = 2; 50 | 51 | // Delay slot variables 52 | uint32_t libRR_delay_slot_pc = 0; 53 | bool libRR_isDelaySlot = false; 54 | 55 | struct retro_memory_map libRR_retromap = { 0 }; 56 | 57 | // Bank switching 58 | uint32_t libRR_bank_size = 0; 59 | uint16_t libRR_current_bank_slot_0 = 1; 60 | uint16_t libRR_current_bank_slot_1 = 2; 61 | uint16_t libRR_current_bank_slot_2 = 3; 62 | uint32_t libRR_slot_0_max_addr = 0x4000; 63 | uint32_t libRR_slot_1_max_addr = 0x7fff; 64 | uint32_t libRR_slot_2_max_addr = 0x7fff; 65 | bool libRR_bank_switching_available = false; 66 | 67 | void console_log_jump_return(int take_jump, uint32_t jump_target, uint32_t pc, uint32_t ra, int64_t* registers, void* r4300) { 68 | printf("%d\n",1); 69 | } 70 | 71 | int get_current_bank_number_for_address(uint32_t addr) { 72 | return 0; 73 | } 74 | 75 | void libRR_setup_console_details(retro_environment_t environ_cb) { 76 | printf("TODO: Setup setting such as libRR_define_console_memory_region for this console\n"); 77 | // libRR_set_retro_memmap(environ_cb); 78 | } 79 | 80 | void write_rom_mapping() { 81 | 82 | } 83 | 84 | void main_state_save(int format, const char *filename) 85 | { 86 | // TODO: actually load the state here 87 | } 88 | 89 | void main_state_load(const char *filename) 90 | { 91 | // TODO: actually load the state here 92 | } 93 | 94 | void add_console_specific_game_json() { 95 | // more info on VDP2 regs: https://segaretro.org/images/8/89/TUTORIAL.pdf 96 | // game_json["VDP2"]["RawRegs"] = printBytesToDecimalJSArray((uint8_t*)VDP2::RawRegs, 0x100); 97 | 98 | // TVMD - TV Mode registers 99 | // game_json["VDP2"]["TVMD"]["DisplayOn"] = VDP2::DisplayOn; 100 | // game_json["VDP2"]["TVMD"]["BorderMode"] = VDP2::BorderMode; 101 | // game_json["VDP2"]["TVMD"]["InterlaceMode"] = VDP2::InterlaceMode; 102 | // game_json["VDP2"]["TVMD"]["HRes"] = VDP2::HRes; 103 | // game_json["VDP2"]["TVMD"]["VRes"] = VDP2::VRes; 104 | 105 | // // EXTEN - 106 | // game_json["VDP2"]["EXTEN"]["ExSyncEnable"] = VDP2::ExSyncEnable; 107 | // game_json["VDP2"]["EXTEN"]["ExLatchEnable"] = VDP2::ExLatchEnable; 108 | // game_json["VDP2"]["EXTEN"]["ExBGEnable"] = VDP2::ExBGEnable; 109 | // game_json["VDP2"]["EXTEN"]["DispAreaSelect"] = VDP2::DispAreaSelect; 110 | 111 | // game_json["VDP2"]["VRAMSize"] = VDP2::VRAMSize; 112 | // game_json["VDP2"]["RAMCTL_Raw"] = VDP2::RAMCTL_Raw; 113 | // game_json["VDP2"]["CRAM_Mode"] = VDP2::CRAM_Mode; 114 | // Documentation only needs to be added once 115 | game_json["Documentation"]["Memory"]["VDP2CRAM"] = "Colour RAM for VDP2 - basically the palette for the background layer"; 116 | } 117 | 118 | void libRR_export_all_files() { 119 | printf("Saturn: Export All files to Reversing Project, depends on which core we are using"); 120 | } 121 | 122 | string get_slot_for_address(int32_t offset) { 123 | return "0"; 124 | } 125 | 126 | string write_console_asm_header() { 127 | string contents = ""; 128 | return contents; 129 | } 130 | 131 | } -------------------------------------------------------------------------------- /constants/GameBoy.json: -------------------------------------------------------------------------------- 1 | { 2 | "addresses": { 3 | "0091": "LY_VBLANK", 4 | "FF0F": "rIF", 5 | "FF00": "JOYPAD", 6 | "FF40": "LCD_CONTROL", 7 | "FFFF": "INTERRUPT_ENABLE" 8 | } 9 | } -------------------------------------------------------------------------------- /constants/GameGear.json: -------------------------------------------------------------------------------- 1 | { 2 | "addresses": { 3 | "0008": "RST1", 4 | "0010": "RST2", 5 | "0018": "RST3", 6 | "0020": "RST4", 7 | "0028": "RST5", 8 | "0030": "RST6", 9 | "0038": "RST7", 10 | "0006": "PSG", 11 | "003e": "YM2413", 12 | "003f": "JOYSTICK_IO_CTRL", 13 | "007e": "V_COUNTER", 14 | "007f": "H_COUNTER", 15 | "00be": "VDP_DATA", 16 | "00bf": "VDP_CTRL", 17 | "00dc": "IO_PORT_A_B", 18 | "00dd": "IO_PORT_B_MISC" 19 | } 20 | } -------------------------------------------------------------------------------- /constants/MasterSystem.json: -------------------------------------------------------------------------------- 1 | { 2 | "addresses": { 3 | "0008": "RST1", 4 | "0010": "RST2", 5 | "0018": "RST3", 6 | "0020": "RST4", 7 | "0028": "RST5", 8 | "0030": "RST6", 9 | "0038": "RST7", 10 | "0006": "PSG", 11 | "003e": "YM2413", 12 | "003f": "JOYSTICK_IO_CTRL", 13 | "007e": "V_COUNTER", 14 | "007f": "H_COUNTER", 15 | "00be": "VDP_DATA", 16 | "00bf": "VDP_CTRL", 17 | "00dc": "IO_PORT_A_B", 18 | "00dd": "IO_PORT_B_MISC" 19 | } 20 | } -------------------------------------------------------------------------------- /export_templates/MasterSystem/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled objects 2 | *.o 3 | 4 | # compiled graphics 5 | *.1bpp 6 | *.2bpp 7 | *.pic 8 | 9 | # compiled roms 10 | *.gbc 11 | *.gb 12 | 13 | # rgbds extras 14 | *.map 15 | *.sym 16 | 17 | # tool binaries 18 | *.exe 19 | 20 | # precompiled python 21 | *.pyc 22 | *$py.class 23 | 24 | # save game files 25 | *.sgm 26 | *.sav 27 | *.rtc 28 | *.sn* 29 | *.sa* 30 | *.sg1 -------------------------------------------------------------------------------- /export_templates/MasterSystem/Makefile: -------------------------------------------------------------------------------- 1 | roms := {{ GAME_NAME }}_rr.sms 2 | 3 | rom_obj := \ 4 | data.o \ 5 | main.o \ 6 | # common.o \ 7 | # jumps.o \ 8 | 9 | game_obj := $(rom_obj:.o=_rr.o) 10 | 11 | 12 | 13 | ### Build tools 14 | 15 | ifeq (,$(shell which sha1sum)) 16 | SHA1 := shasum 17 | else 18 | SHA1 := sha1sum 19 | endif 20 | 21 | WLA ?= 22 | ASM ?= $(WLA)wla-z80 23 | RGBFIX ?= $(WLA)rgbfix 24 | RGBGFX ?= $(WLA)rgbgfx 25 | LINKER ?= $(WLA)wlalink 26 | 27 | 28 | ### Build targets 29 | 30 | .SUFFIXES: 31 | .SECONDEXPANSION: 32 | .PRECIOUS: 33 | .SECONDARY: 34 | .PHONY: all red clean tidy compare 35 | 36 | all: $(roms) 37 | game: {{ GAME_NAME }}.gb 38 | 39 | clean: tidy 40 | find gfx \( -iname '*.1bpp' -o -iname '*.2bpp' -o -iname '*.pic' \) -delete 41 | 42 | tidy: 43 | rm -f $(roms) $(game_obj) $(roms:.gb=.map) $(roms:.gb=.sym) 44 | $(MAKE) clean -C tools/ 45 | 46 | compare: $(roms) 47 | @$(SHA1) -c roms.sha1 48 | 49 | 50 | ASMFLAGS = -v 51 | 52 | $(gameobj): ASMFLAGS += -D _libRR 53 | 54 | # The dep rules have to be explicit or else missing files won't be reported. 55 | # As a side effect, they're evaluated immediately instead of when the rule is invoked. 56 | # It doesn't look like $(shell) can be deferred so there might not be a better way. 57 | define DEP 58 | $1: $2 $$(shell tools/scan_includes $2) 59 | $$(ASM) $$(ASMFLAGS) -o $$@ $$< 60 | endef 61 | 62 | # Build tools when building the rom. 63 | # This has to happen before the rules are processed, since that's when scan_includes is run. 64 | ifeq (,$(filter clean tidy tools,$(MAKECMDGOALS))) 65 | 66 | $(info $(shell $(MAKE) -C tools)) 67 | 68 | # Dependencies for objects (drop _red and _blue from asm file basenames) 69 | $(foreach obj, $(game_obj), $(eval $(call DEP,$(obj),$(obj:_rr.o=.asm)))) 70 | 71 | endif 72 | 73 | 74 | %.asm: ; 75 | 76 | 77 | game_pad = 0x00 78 | 79 | game_opt = -jsv -n 0 -k 01 -l 0x33 -m 0x13 -r 03 -t "{{ GAME_NAME }}" 80 | 81 | %.sms: $$(game_obj) 82 | #echo "[objects]\n$(filter %.o,$^)">{{ GAME_NAME }}.link 83 | $(LINKER) -s -S layout.link $@ 84 | #$(RGBFIX) -p $(game_pad) $(game_opt) $@ 85 | 86 | 87 | ### Misc file-specific graphics rules 88 | gfx/tilesets/%.2bpp: tools/gfx += --trim-whitespace 89 | 90 | 91 | ### Catch-all graphics rules 92 | 93 | %.png: ; 94 | 95 | %.2bpp: %.png 96 | $(RGBGFX) $(rgbgfx) -o $@ $< 97 | $(if $(tools/gfx),\ 98 | tools/gfx $(tools/gfx) -o $@ $@) 99 | 100 | %.1bpp: %.png 101 | $(RGBGFX) $(rgbgfx) -d1 -o $@ $< 102 | $(if $(tools/gfx),\ 103 | tools/gfx $(tools/gfx) -d1 -o $@ $@) 104 | 105 | %.pic: %.2bpp 106 | tools/pkmncompress $< $@ -------------------------------------------------------------------------------- /export_templates/MasterSystem/README.md: -------------------------------------------------------------------------------- 1 | # {{ GAME_NAME }} 2 | 3 | This is a disassembly of {{ GAME_NAME }}. 4 | 5 | It builds the following ROMs: 6 | 7 | - {{ GAME_NAME }}.gb `sha1: {{ ROM_SHA1 }}` 8 | 9 | To set up the repository, see [**INSTALL.md**](INSTALL.md). 10 | 11 | This was auto generated by libRetroReversing for GameGear -------------------------------------------------------------------------------- /export_templates/MasterSystem/common.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "./common/constants.asm" 2 | 3 | 4 | SECTION "NULL", ROM0 5 | NULL:: 6 | 7 | z_UNCALLED_FUNCTION:: 8 | 9 | INCLUDE "./common/header.asm" 10 | 11 | 12 | -------------------------------------------------------------------------------- /export_templates/MasterSystem/common/constants.asm: -------------------------------------------------------------------------------- 1 | ; TODO: Add gamegear constants here 2 | 3 | .MACRO z_UNTAKEN_JUMP_2 4 | .REPT 2 5 | NOP 6 | .ENDR 7 | .ENDM 8 | 9 | .MACRO z_UNTAKEN_JUMP_3 10 | .REPT 3 11 | NOP 12 | .ENDR 13 | .ENDM 14 | 15 | -------------------------------------------------------------------------------- /export_templates/MasterSystem/common/header.asm: -------------------------------------------------------------------------------- 1 | ; rst vectors (unused) 2 | 3 | ;SECTION "rst0", ROM0[$0000] 4 | ; rst $38 5 | ; 6 | ; ds $08 - @, 0 ; unused 7 | ; 8 | ;SECTION "rst8", ROM0[$0008] 9 | ; rst $38 10 | ; 11 | ; ds $10 - @, 0 ; unused 12 | ; 13 | ;SECTION "rst10", ROM0[$0010] 14 | ; rst $38 15 | ; 16 | ; ds $18 - @, 0 ; unused 17 | ; 18 | ;SECTION "rst18", ROM0[$0018] 19 | ; rst $38 20 | ; 21 | ; ds $20 - @, 0 ; unused 22 | ; 23 | ;SECTION "rst20", ROM0[$0020] 24 | ; rst $38 25 | ; 26 | ; ds $28 - @, 0 ; unused 27 | ; 28 | ;SECTION "rst28", ROM0[$0028] 29 | ; rst $38 30 | ; 31 | ; ds $30 - @, 0 ; unused 32 | ; 33 | ;SECTION "rst30", ROM0[$0030] 34 | ; rst $38 35 | ; 36 | ; ds $38 - @, 0 ; unused 37 | ; 38 | ;SECTION "rst38", ROM0[$0038] 39 | ; rst $38 40 | ; 41 | ; ds $40 - @, 0 ; unused 42 | ; 43 | 44 | ; Game Boy hardware interrupts 45 | 46 | ;SECTION "vblank", ROM0[$0040] 47 | ;jp VBlank 48 | ; nop 49 | ; nop 50 | ; nop 51 | 52 | ; ds $48 - @, 0 ; unused 53 | 54 | ;SECTION "lcd", ROM0[$0048] 55 | ; rst $38 56 | ; 57 | ; ds $50 - @, 0 ; unused 58 | 59 | ;SECTION "timer", ROM0[$0050] 60 | ;jp Timer 61 | ; nop 62 | ; nop 63 | ; nop 64 | 65 | ; ds $58 - @, 0 ; unused 66 | 67 | ;SECTION "serial", ROM0[$0058] 68 | ; ;jp Serial 69 | ; nop 70 | ; nop 71 | ; nop 72 | ; ds $60 - @, 0 ; unused 73 | 74 | ;SECTION "joypad", ROM0[$0060] 75 | ; reti 76 | 77 | 78 | ;SECTION "Header", ROM0[$0100] 79 | 80 | ;Start:: 81 | ; Nintendo requires all Game Boy ROMs to begin with a nop ($00) and a jp ($C3) 82 | ; to the starting address. 83 | ; nop 84 | ; jp _Start 85 | 86 | 87 | ; The Game Boy cartridge header data is patched over by rgbfix. 88 | ; This makes sure it doesn't get used for anything else. 89 | 90 | ; ds $0150 - @ 91 | 92 | ;_Start:: 93 | ; nop 94 | 95 | -------------------------------------------------------------------------------- /export_templates/MasterSystem/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Master System WLA-DX Source Exporter", 3 | "dirs": [ 4 | "common" 5 | ], 6 | "files": [ 7 | "Makefile", 8 | "README.md", 9 | "INSTALL.md", 10 | ".gitignore", 11 | "common.asm", 12 | "layout.link", 13 | "common/header.asm", 14 | "common/constants.asm", 15 | "tools/scan_includes.c", 16 | "tools/Makefile" 17 | ], 18 | "main": "main.asm", 19 | "asm_extenstion": ".asm" 20 | } -------------------------------------------------------------------------------- /export_templates/MasterSystem/layout.link: -------------------------------------------------------------------------------- 1 | [objects] 2 | main_rr.o 3 | data_rr.o 4 | -------------------------------------------------------------------------------- /export_templates/MasterSystem/tools/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | CC := gcc 4 | CFLAGS := -O3 -std=c99 -Wall -Wextra -pedantic 5 | 6 | tools := scan_includes #gfx pkmncompress 7 | 8 | all: $(tools) 9 | @: 10 | 11 | clean: 12 | rm -f $(tools) 13 | 14 | gfx: common.h 15 | %: %.c 16 | $(CC) $(CFLAGS) -o $@ $< -------------------------------------------------------------------------------- /export_templates/MasterSystem/tools/scan_includes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void usage(void) { 8 | printf("Usage: scan_includes [-h] [-s] filename\n" 9 | "-h, --help\n" 10 | " Print usage and exit\n" 11 | "-s, --strict\n" 12 | " Fail if a file cannot be read\n"); 13 | } 14 | 15 | struct Options { 16 | bool help; 17 | bool strict; 18 | }; 19 | 20 | struct Options Options = {0}; 21 | 22 | void scan_file(char* filename) { 23 | FILE *f = fopen(filename, "rb"); 24 | if (!f) { 25 | if (Options.strict) { 26 | fprintf(stderr, "Could not open file: '%s'\n", filename); 27 | exit(1); 28 | } else { 29 | return; 30 | } 31 | } 32 | 33 | fseek(f, 0, SEEK_END); 34 | long size = ftell(f); 35 | rewind(f); 36 | 37 | char *buffer = malloc(size + 1); 38 | char *orig = buffer; 39 | size = fread(buffer, 1, size, f); 40 | buffer[size] = '\0'; 41 | fclose(f); 42 | 43 | for (; buffer && (buffer - orig < size); buffer++) { 44 | bool is_include = false; 45 | bool is_incbin = false; 46 | switch (*buffer) { 47 | case ';': 48 | buffer = strchr(buffer, '\n'); 49 | if (!buffer) { 50 | fprintf(stderr, "%s: no newline at end of file\n", filename); 51 | break; 52 | } 53 | break; 54 | 55 | case '"': 56 | buffer++; 57 | buffer = strchr(buffer, '"'); 58 | if (!buffer) { 59 | fprintf(stderr, "%s: unterminated string\n", filename); 60 | break; 61 | } 62 | buffer++; 63 | break; 64 | 65 | case 'i': 66 | case 'I': 67 | if ((strncmp(buffer, "INCBIN", 6) == 0) || (strncmp(buffer, "incbin", 6) == 0)) { 68 | is_incbin = true; 69 | } else if ((strncmp(buffer, "INCLUDE", 7) == 0) || (strncmp(buffer, "include", 7) == 0)) { 70 | is_include = true; 71 | } 72 | if (is_incbin || is_include) { 73 | buffer = strchr(buffer, '"'); 74 | if (!buffer) { 75 | break; 76 | } 77 | buffer++; 78 | int length = strcspn(buffer, "\""); 79 | char *include = malloc(length + 1); 80 | strncpy(include, buffer, length); 81 | include[length] = '\0'; 82 | printf("%s ", include); 83 | if (is_include) { 84 | scan_file(include); 85 | } 86 | free(include); 87 | buffer = strchr(buffer, '"'); 88 | } 89 | break; 90 | 91 | } 92 | if (!buffer) { 93 | break; 94 | } 95 | 96 | } 97 | 98 | free(orig); 99 | } 100 | 101 | int main(int argc, char* argv[]) { 102 | int i = 0; 103 | struct option long_options[] = { 104 | {"strict", no_argument, 0, 's'}, 105 | {"help", no_argument, 0, 'h'}, 106 | {0} 107 | }; 108 | int opt = -1; 109 | while ((opt = getopt_long(argc, argv, "sh", long_options, &i)) != -1) { 110 | switch (opt) { 111 | case 's': 112 | Options.strict = true; 113 | break; 114 | case 'h': 115 | Options.help = true; 116 | break; 117 | default: 118 | usage(); 119 | exit(1); 120 | break; 121 | } 122 | } 123 | argc -= optind; 124 | argv += optind; 125 | if (Options.help) { 126 | usage(); 127 | return 0; 128 | } 129 | if (argc < 1) { 130 | usage(); 131 | exit(1); 132 | } 133 | scan_file(argv[0]); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /export_templates/NES/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled objects 2 | *.o 3 | 4 | # compiled graphics 5 | *.1bpp 6 | *.2bpp 7 | *.pic 8 | 9 | # compiled roms 10 | *.gbc 11 | *.gb 12 | 13 | # rgbds extras 14 | *.map 15 | *.sym 16 | 17 | # tool binaries 18 | *.exe 19 | 20 | # precompiled python 21 | *.pyc 22 | *$py.class 23 | 24 | # save game files 25 | *.sgm 26 | *.sav 27 | *.rtc 28 | *.sn* 29 | *.sa* 30 | *.sg1 -------------------------------------------------------------------------------- /export_templates/NES/Makefile: -------------------------------------------------------------------------------- 1 | roms := {{ GAME_NAME }}_rr.nes 2 | 3 | rom_obj := \ 4 | main.o \ 5 | # data.o \ 6 | 7 | 8 | game_obj := $(rom_obj:.o=_rr.o) 9 | 10 | 11 | 12 | ### Build tools 13 | 14 | ifeq (,$(shell which sha1sum)) 15 | SHA1 := shasum 16 | else 17 | SHA1 := sha1sum 18 | endif 19 | 20 | WLA ?= 21 | ASM ?= $(WLA)wla-6502 22 | RGBFIX ?= $(WLA)rgbfix 23 | RGBGFX ?= $(WLA)rgbgfx 24 | LINKER ?= $(WLA)wlalink 25 | 26 | 27 | ### Build targets 28 | 29 | .SUFFIXES: 30 | .SECONDEXPANSION: 31 | .PRECIOUS: 32 | .SECONDARY: 33 | .PHONY: all red clean tidy compare 34 | 35 | all: $(roms) 36 | game: {{ GAME_NAME }}.gb 37 | 38 | clean: tidy 39 | find gfx \( -iname '*.1bpp' -o -iname '*.2bpp' -o -iname '*.pic' \) -delete 40 | 41 | tidy: 42 | rm -f $(roms) $(game_obj) $(roms:.gb=.map) $(roms:.gb=.sym) 43 | $(MAKE) clean -C tools/ 44 | 45 | compare: $(roms) 46 | @$(SHA1) -c roms.sha1 47 | 48 | 49 | ASMFLAGS = -v 50 | 51 | $(gameobj): ASMFLAGS += -D _libRR 52 | 53 | # The dep rules have to be explicit or else missing files won't be reported. 54 | # As a side effect, they're evaluated immediately instead of when the rule is invoked. 55 | # It doesn't look like $(shell) can be deferred so there might not be a better way. 56 | define DEP 57 | $1: $2 $$(shell tools/scan_includes $2) 58 | $$(ASM) $$(ASMFLAGS) -o $$@ $$< 59 | endef 60 | 61 | # Build tools when building the rom. 62 | # This has to happen before the rules are processed, since that's when scan_includes is run. 63 | ifeq (,$(filter clean tidy tools,$(MAKECMDGOALS))) 64 | 65 | $(info $(shell $(MAKE) -C tools)) 66 | 67 | # Dependencies for objects (drop _red and _blue from asm file basenames) 68 | $(foreach obj, $(game_obj), $(eval $(call DEP,$(obj),$(obj:_rr.o=.asm)))) 69 | 70 | endif 71 | 72 | 73 | %.asm: ; 74 | 75 | 76 | game_pad = 0x00 77 | 78 | game_opt = -jsv -n 0 -k 01 -l 0x33 -m 0x13 -r 03 -t "{{ GAME_NAME }}" 79 | 80 | %.nes: $$(game_obj) 81 | $(LINKER) -s -S layout.link $@ 82 | 83 | 84 | ### Misc file-specific graphics rules 85 | gfx/tilesets/%.2bpp: tools/gfx += --trim-whitespace 86 | 87 | 88 | ### Catch-all graphics rules 89 | 90 | %.png: ; 91 | 92 | %.2bpp: %.png 93 | $(RGBGFX) $(rgbgfx) -o $@ $< 94 | $(if $(tools/gfx),\ 95 | tools/gfx $(tools/gfx) -o $@ $@) 96 | 97 | %.1bpp: %.png 98 | $(RGBGFX) $(rgbgfx) -d1 -o $@ $< 99 | $(if $(tools/gfx),\ 100 | tools/gfx $(tools/gfx) -d1 -o $@ $@) 101 | 102 | %.pic: %.2bpp 103 | tools/pkmncompress $< $@ -------------------------------------------------------------------------------- /export_templates/NES/README.md: -------------------------------------------------------------------------------- 1 | # {{ GAME_NAME }} 2 | 3 | This is a disassembly of {{ GAME_NAME }}. 4 | 5 | It builds the following ROMs: 6 | 7 | - {{ GAME_NAME }}.gb `sha1: {{ ROM_SHA1 }}` 8 | 9 | To set up the repository, see [**INSTALL.md**](INSTALL.md). 10 | 11 | This was auto generated by libRetroReversing for NES -------------------------------------------------------------------------------- /export_templates/NES/common.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "./common/constants.asm" 2 | 3 | 4 | SECTION "NULL", ROM0 5 | NULL:: 6 | 7 | z_UNCALLED_FUNCTION:: 8 | 9 | INCLUDE "./common/header.asm" 10 | 11 | 12 | -------------------------------------------------------------------------------- /export_templates/NES/common/constants.asm: -------------------------------------------------------------------------------- 1 | ; Add any SNES constants here 2 | 3 | .MACRO z_UNTAKEN_JUMP_2 4 | .REPT 2 5 | NOP 6 | .ENDR 7 | .ENDM 8 | 9 | .MACRO z_UNTAKEN_JUMP_3 10 | .REPT 3 11 | NOP 12 | .ENDR 13 | .ENDM 14 | 15 | -------------------------------------------------------------------------------- /export_templates/NES/common/header.asm: -------------------------------------------------------------------------------- 1 | ; Add any SNES headers here 2 | -------------------------------------------------------------------------------- /export_templates/NES/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NES WLA-DX Source Exporter", 3 | "dirs": [ 4 | "common" 5 | ], 6 | "files": [ 7 | "Makefile", 8 | "README.md", 9 | "INSTALL.md", 10 | ".gitignore", 11 | "common.asm", 12 | "layout.link", 13 | "common/header.asm", 14 | "common/constants.asm", 15 | "tools/scan_includes.c", 16 | "tools/Makefile" 17 | ], 18 | "main": "main.asm", 19 | "asm_extenstion": ".asm" 20 | } -------------------------------------------------------------------------------- /export_templates/NES/layout.link: -------------------------------------------------------------------------------- 1 | [objects] 2 | main_rr.o 3 | [header] 4 | iNES.bin 5 | -------------------------------------------------------------------------------- /export_templates/NES/tools/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | CC := gcc 4 | CFLAGS := -O3 -std=c99 -Wall -Wextra -pedantic 5 | 6 | tools := scan_includes #gfx pkmncompress 7 | 8 | all: $(tools) 9 | @: 10 | 11 | clean: 12 | rm -f $(tools) 13 | 14 | gfx: common.h 15 | %: %.c 16 | $(CC) $(CFLAGS) -o $@ $< -------------------------------------------------------------------------------- /export_templates/NES/tools/scan_includes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void usage(void) { 8 | printf("Usage: scan_includes [-h] [-s] filename\n" 9 | "-h, --help\n" 10 | " Print usage and exit\n" 11 | "-s, --strict\n" 12 | " Fail if a file cannot be read\n"); 13 | } 14 | 15 | struct Options { 16 | bool help; 17 | bool strict; 18 | }; 19 | 20 | struct Options Options = {0}; 21 | 22 | void scan_file(char* filename) { 23 | FILE *f = fopen(filename, "rb"); 24 | if (!f) { 25 | if (Options.strict) { 26 | fprintf(stderr, "Could not open file: '%s'\n", filename); 27 | exit(1); 28 | } else { 29 | return; 30 | } 31 | } 32 | 33 | fseek(f, 0, SEEK_END); 34 | long size = ftell(f); 35 | rewind(f); 36 | 37 | char *buffer = malloc(size + 1); 38 | char *orig = buffer; 39 | size = fread(buffer, 1, size, f); 40 | buffer[size] = '\0'; 41 | fclose(f); 42 | 43 | for (; buffer && (buffer - orig < size); buffer++) { 44 | bool is_include = false; 45 | bool is_incbin = false; 46 | switch (*buffer) { 47 | case ';': 48 | buffer = strchr(buffer, '\n'); 49 | if (!buffer) { 50 | fprintf(stderr, "%s: no newline at end of file\n", filename); 51 | break; 52 | } 53 | break; 54 | 55 | case '"': 56 | buffer++; 57 | buffer = strchr(buffer, '"'); 58 | if (!buffer) { 59 | fprintf(stderr, "%s: unterminated string\n", filename); 60 | break; 61 | } 62 | buffer++; 63 | break; 64 | 65 | case 'i': 66 | case 'I': 67 | if ((strncmp(buffer, "INCBIN", 6) == 0) || (strncmp(buffer, "incbin", 6) == 0)) { 68 | is_incbin = true; 69 | } else if ((strncmp(buffer, "INCLUDE", 7) == 0) || (strncmp(buffer, "include", 7) == 0)) { 70 | is_include = true; 71 | } 72 | if (is_incbin || is_include) { 73 | buffer = strchr(buffer, '"'); 74 | if (!buffer) { 75 | break; 76 | } 77 | buffer++; 78 | int length = strcspn(buffer, "\""); 79 | char *include = malloc(length + 1); 80 | strncpy(include, buffer, length); 81 | include[length] = '\0'; 82 | printf("%s ", include); 83 | if (is_include) { 84 | scan_file(include); 85 | } 86 | free(include); 87 | buffer = strchr(buffer, '"'); 88 | } 89 | break; 90 | 91 | } 92 | if (!buffer) { 93 | break; 94 | } 95 | 96 | } 97 | 98 | free(orig); 99 | } 100 | 101 | int main(int argc, char* argv[]) { 102 | int i = 0; 103 | struct option long_options[] = { 104 | {"strict", no_argument, 0, 's'}, 105 | {"help", no_argument, 0, 'h'}, 106 | {0} 107 | }; 108 | int opt = -1; 109 | while ((opt = getopt_long(argc, argv, "sh", long_options, &i)) != -1) { 110 | switch (opt) { 111 | case 's': 112 | Options.strict = true; 113 | break; 114 | case 'h': 115 | Options.help = true; 116 | break; 117 | default: 118 | usage(); 119 | exit(1); 120 | break; 121 | } 122 | } 123 | argc -= optind; 124 | argv += optind; 125 | if (Options.help) { 126 | usage(); 127 | return 0; 128 | } 129 | if (argc < 1) { 130 | usage(); 131 | exit(1); 132 | } 133 | scan_file(argv[0]); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /export_templates/SNES/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled objects 2 | *.o 3 | 4 | # compiled graphics 5 | *.1bpp 6 | *.2bpp 7 | *.pic 8 | 9 | # compiled roms 10 | *.gbc 11 | *.gb 12 | 13 | # rgbds extras 14 | *.map 15 | *.sym 16 | 17 | # tool binaries 18 | *.exe 19 | 20 | # precompiled python 21 | *.pyc 22 | *$py.class 23 | 24 | # save game files 25 | *.sgm 26 | *.sav 27 | *.rtc 28 | *.sn* 29 | *.sa* 30 | *.sg1 -------------------------------------------------------------------------------- /export_templates/SNES/Makefile: -------------------------------------------------------------------------------- 1 | roms := {{ GAME_NAME }}_rr.sfc 2 | 3 | rom_obj := \ 4 | main.o \ 5 | # data.o \ 6 | 7 | 8 | game_obj := $(rom_obj:.o=_rr.o) 9 | 10 | 11 | 12 | ### Build tools 13 | 14 | ifeq (,$(shell which sha1sum)) 15 | SHA1 := shasum 16 | else 17 | SHA1 := sha1sum 18 | endif 19 | 20 | WLA ?= 21 | ASM ?= $(WLA)wla-65816 22 | RGBFIX ?= $(WLA)rgbfix 23 | RGBGFX ?= $(WLA)rgbgfx 24 | LINKER ?= $(WLA)wlalink 25 | 26 | 27 | ### Build targets 28 | 29 | .SUFFIXES: 30 | .SECONDEXPANSION: 31 | .PRECIOUS: 32 | .SECONDARY: 33 | .PHONY: all red clean tidy compare 34 | 35 | all: $(roms) 36 | game: {{ GAME_NAME }}.gb 37 | 38 | clean: tidy 39 | find gfx \( -iname '*.1bpp' -o -iname '*.2bpp' -o -iname '*.pic' \) -delete 40 | 41 | tidy: 42 | rm -f $(roms) $(game_obj) $(roms:.gb=.map) $(roms:.gb=.sym) 43 | $(MAKE) clean -C tools/ 44 | 45 | compare: $(roms) 46 | @$(SHA1) -c roms.sha1 47 | 48 | 49 | ASMFLAGS = -v 50 | 51 | $(gameobj): ASMFLAGS += -D _libRR 52 | 53 | # The dep rules have to be explicit or else missing files won't be reported. 54 | # As a side effect, they're evaluated immediately instead of when the rule is invoked. 55 | # It doesn't look like $(shell) can be deferred so there might not be a better way. 56 | define DEP 57 | $1: $2 $$(shell tools/scan_includes $2) 58 | $$(ASM) $$(ASMFLAGS) -o $$@ $$< 59 | endef 60 | 61 | # Build tools when building the rom. 62 | # This has to happen before the rules are processed, since that's when scan_includes is run. 63 | ifeq (,$(filter clean tidy tools,$(MAKECMDGOALS))) 64 | 65 | $(info $(shell $(MAKE) -C tools)) 66 | 67 | # Dependencies for objects (drop _red and _blue from asm file basenames) 68 | $(foreach obj, $(game_obj), $(eval $(call DEP,$(obj),$(obj:_rr.o=.asm)))) 69 | 70 | endif 71 | 72 | 73 | %.asm: ; 74 | 75 | 76 | game_pad = 0x00 77 | 78 | game_opt = -jsv -n 0 -k 01 -l 0x33 -m 0x13 -r 03 -t "{{ GAME_NAME }}" 79 | 80 | %.sfc: $$(game_obj) 81 | $(LINKER) -s -S layout.link $@ 82 | 83 | 84 | ### Misc file-specific graphics rules 85 | gfx/tilesets/%.2bpp: tools/gfx += --trim-whitespace 86 | 87 | 88 | ### Catch-all graphics rules 89 | 90 | %.png: ; 91 | 92 | %.2bpp: %.png 93 | $(RGBGFX) $(rgbgfx) -o $@ $< 94 | $(if $(tools/gfx),\ 95 | tools/gfx $(tools/gfx) -o $@ $@) 96 | 97 | %.1bpp: %.png 98 | $(RGBGFX) $(rgbgfx) -d1 -o $@ $< 99 | $(if $(tools/gfx),\ 100 | tools/gfx $(tools/gfx) -d1 -o $@ $@) 101 | 102 | %.pic: %.2bpp 103 | tools/pkmncompress $< $@ -------------------------------------------------------------------------------- /export_templates/SNES/README.md: -------------------------------------------------------------------------------- 1 | # {{ GAME_NAME }} 2 | 3 | This is a disassembly of {{ GAME_NAME }}. 4 | 5 | It builds the following ROMs: 6 | 7 | - {{ GAME_NAME }}.gb `sha1: {{ ROM_SHA1 }}` 8 | 9 | To set up the repository, see [**INSTALL.md**](INSTALL.md). 10 | 11 | This was auto generated by libRetroReversing for GameGear -------------------------------------------------------------------------------- /export_templates/SNES/common.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "./common/constants.asm" 2 | 3 | 4 | SECTION "NULL", ROM0 5 | NULL:: 6 | 7 | z_UNCALLED_FUNCTION:: 8 | 9 | INCLUDE "./common/header.asm" 10 | 11 | 12 | -------------------------------------------------------------------------------- /export_templates/SNES/common/constants.asm: -------------------------------------------------------------------------------- 1 | ; Add any SNES constants here 2 | 3 | .MACRO z_UNTAKEN_JUMP_2 4 | .REPT 2 5 | NOP 6 | .ENDR 7 | .ENDM 8 | 9 | .MACRO z_UNTAKEN_JUMP_3 10 | .REPT 3 11 | NOP 12 | .ENDR 13 | .ENDM 14 | 15 | -------------------------------------------------------------------------------- /export_templates/SNES/common/header.asm: -------------------------------------------------------------------------------- 1 | ; Add any SNES headers here 2 | -------------------------------------------------------------------------------- /export_templates/SNES/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SNES WLA-DX Source Exporter", 3 | "dirs": [ 4 | "common" 5 | ], 6 | "files": [ 7 | "Makefile", 8 | "README.md", 9 | "INSTALL.md", 10 | ".gitignore", 11 | "common.asm", 12 | "layout.link", 13 | "common/header.asm", 14 | "common/constants.asm", 15 | "tools/scan_includes.c", 16 | "tools/Makefile" 17 | ], 18 | "main": "main.asm", 19 | "asm_extenstion": ".asm" 20 | } -------------------------------------------------------------------------------- /export_templates/SNES/layout.link: -------------------------------------------------------------------------------- 1 | [objects] 2 | main_rr.o 3 | 4 | -------------------------------------------------------------------------------- /export_templates/SNES/tools/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | CC := gcc 4 | CFLAGS := -O3 -std=c99 -Wall -Wextra -pedantic 5 | 6 | tools := scan_includes #gfx pkmncompress 7 | 8 | all: $(tools) 9 | @: 10 | 11 | clean: 12 | rm -f $(tools) 13 | 14 | gfx: common.h 15 | %: %.c 16 | $(CC) $(CFLAGS) -o $@ $< -------------------------------------------------------------------------------- /export_templates/SNES/tools/scan_includes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void usage(void) { 8 | printf("Usage: scan_includes [-h] [-s] filename\n" 9 | "-h, --help\n" 10 | " Print usage and exit\n" 11 | "-s, --strict\n" 12 | " Fail if a file cannot be read\n"); 13 | } 14 | 15 | struct Options { 16 | bool help; 17 | bool strict; 18 | }; 19 | 20 | struct Options Options = {0}; 21 | 22 | void scan_file(char* filename) { 23 | FILE *f = fopen(filename, "rb"); 24 | if (!f) { 25 | if (Options.strict) { 26 | fprintf(stderr, "Could not open file: '%s'\n", filename); 27 | exit(1); 28 | } else { 29 | return; 30 | } 31 | } 32 | 33 | fseek(f, 0, SEEK_END); 34 | long size = ftell(f); 35 | rewind(f); 36 | 37 | char *buffer = malloc(size + 1); 38 | char *orig = buffer; 39 | size = fread(buffer, 1, size, f); 40 | buffer[size] = '\0'; 41 | fclose(f); 42 | 43 | for (; buffer && (buffer - orig < size); buffer++) { 44 | bool is_include = false; 45 | bool is_incbin = false; 46 | switch (*buffer) { 47 | case ';': 48 | buffer = strchr(buffer, '\n'); 49 | if (!buffer) { 50 | fprintf(stderr, "%s: no newline at end of file\n", filename); 51 | break; 52 | } 53 | break; 54 | 55 | case '"': 56 | buffer++; 57 | buffer = strchr(buffer, '"'); 58 | if (!buffer) { 59 | fprintf(stderr, "%s: unterminated string\n", filename); 60 | break; 61 | } 62 | buffer++; 63 | break; 64 | 65 | case 'i': 66 | case 'I': 67 | if ((strncmp(buffer, "INCBIN", 6) == 0) || (strncmp(buffer, "incbin", 6) == 0)) { 68 | is_incbin = true; 69 | } else if ((strncmp(buffer, "INCLUDE", 7) == 0) || (strncmp(buffer, "include", 7) == 0)) { 70 | is_include = true; 71 | } 72 | if (is_incbin || is_include) { 73 | buffer = strchr(buffer, '"'); 74 | if (!buffer) { 75 | break; 76 | } 77 | buffer++; 78 | int length = strcspn(buffer, "\""); 79 | char *include = malloc(length + 1); 80 | strncpy(include, buffer, length); 81 | include[length] = '\0'; 82 | printf("%s ", include); 83 | if (is_include) { 84 | scan_file(include); 85 | } 86 | free(include); 87 | buffer = strchr(buffer, '"'); 88 | } 89 | break; 90 | 91 | } 92 | if (!buffer) { 93 | break; 94 | } 95 | 96 | } 97 | 98 | free(orig); 99 | } 100 | 101 | int main(int argc, char* argv[]) { 102 | int i = 0; 103 | struct option long_options[] = { 104 | {"strict", no_argument, 0, 's'}, 105 | {"help", no_argument, 0, 'h'}, 106 | {0} 107 | }; 108 | int opt = -1; 109 | while ((opt = getopt_long(argc, argv, "sh", long_options, &i)) != -1) { 110 | switch (opt) { 111 | case 's': 112 | Options.strict = true; 113 | break; 114 | case 'h': 115 | Options.help = true; 116 | break; 117 | default: 118 | usage(); 119 | exit(1); 120 | break; 121 | } 122 | } 123 | argc -= optind; 124 | argv += optind; 125 | if (Options.help) { 126 | usage(); 127 | return 0; 128 | } 129 | if (argc < 1) { 130 | usage(); 131 | exit(1); 132 | } 133 | scan_file(argv[0]); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /export_templates/gameboy/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled objects 2 | *.o 3 | 4 | # compiled graphics 5 | *.1bpp 6 | *.2bpp 7 | *.pic 8 | 9 | # compiled roms 10 | *.gbc 11 | *.gb 12 | 13 | # rgbds extras 14 | *.map 15 | *.sym 16 | 17 | # tool binaries 18 | *.exe 19 | 20 | # precompiled python 21 | *.pyc 22 | *$py.class 23 | 24 | # save game files 25 | *.sgm 26 | *.sav 27 | *.rtc 28 | *.sn* 29 | *.sa* 30 | *.sg1 -------------------------------------------------------------------------------- /export_templates/gameboy/Makefile: -------------------------------------------------------------------------------- 1 | roms := {{ GAME_NAME }}_rr.gb 2 | 3 | rom_obj := \ 4 | data.o \ 5 | main.o \ 6 | common.o \ 7 | # jumps.o \ 8 | 9 | game_obj := $(rom_obj:.o=_rr.o) 10 | 11 | 12 | 13 | ### Build tools 14 | 15 | ifeq (,$(shell which sha1sum)) 16 | SHA1 := shasum 17 | else 18 | SHA1 := sha1sum 19 | endif 20 | 21 | RGBDS ?= 22 | RGBASM ?= $(RGBDS)rgbasm 23 | RGBFIX ?= $(RGBDS)rgbfix 24 | RGBGFX ?= $(RGBDS)rgbgfx 25 | RGBLINK ?= $(RGBDS)rgblink 26 | 27 | 28 | ### Build targets 29 | 30 | .SUFFIXES: 31 | .SECONDEXPANSION: 32 | .PRECIOUS: 33 | .SECONDARY: 34 | .PHONY: all red clean tidy compare tools 35 | 36 | all: $(roms) 37 | game: {{ GAME_NAME }}.gb 38 | 39 | clean: tidy 40 | find gfx \( -iname '*.1bpp' -o -iname '*.2bpp' -o -iname '*.pic' \) -delete 41 | 42 | tidy: 43 | rm -f $(roms) $(game_obj) $(roms:.gb=.map) $(roms:.gb=.sym) rgbdscheck.o 44 | $(MAKE) clean -C tools/ 45 | 46 | compare: $(roms) 47 | @$(SHA1) -c roms.sha1 48 | 49 | tools: 50 | $(MAKE) -C tools/ 51 | 52 | 53 | RGBASMFLAGS = -h -L -Weverything 54 | # Create a sym/map for debug purposes if `make` run with `DEBUG=1` 55 | ifeq ($(DEBUG),1) 56 | RGBASMFLAGS += -E 57 | endif 58 | 59 | $(gameobj): RGBASMFLAGS += -D _libRR 60 | 61 | rgbdscheck.o: common/rgbdscheck.asm 62 | $(RGBASM) -o $@ $< 63 | 64 | # The dep rules have to be explicit or else missing files won't be reported. 65 | # As a side effect, they're evaluated immediately instead of when the rule is invoked. 66 | # It doesn't look like $(shell) can be deferred so there might not be a better way. 67 | define DEP 68 | $1: $2 $$(shell tools/scan_includes $2) | rgbdscheck.o 69 | $$(RGBASM) $$(RGBASMFLAGS) -o $$@ $$< 70 | endef 71 | 72 | # Build tools when building the rom. 73 | # This has to happen before the rules are processed, since that's when scan_includes is run. 74 | ifeq (,$(filter clean tidy tools,$(MAKECMDGOALS))) 75 | 76 | $(info $(shell $(MAKE) -C tools)) 77 | 78 | # Dependencies for objects (drop _red and _blue from asm file basenames) 79 | $(foreach obj, $(game_obj), $(eval $(call DEP,$(obj),$(obj:_rr.o=.asm)))) 80 | 81 | endif 82 | 83 | 84 | %.asm: ; 85 | 86 | 87 | game_pad = 0x00 88 | 89 | game_opt = -jsv -n 0 -k 01 -l 0x33 -m 0x13 -r 03 -t "{{ GAME_NAME }}" 90 | 91 | %.gb: $$(game_obj) layout.link 92 | $(RGBLINK) -p $(game_pad) -d -m $*.map -n $*.sym -l layout.link -o $@ $(filter %.o,$^) 93 | $(RGBFIX) -p $(game_pad) $(game_opt) $@ 94 | 95 | %.gbc: $$(game_obj) layout.link 96 | $(RGBLINK) -p $(game_pad) -d -m $*.map -n $*.sym -l layout.link -o $@ $(filter %.o,$^) 97 | $(RGBFIX) -p $(game_pad) $(game_opt) $@ 98 | 99 | 100 | ### Misc file-specific graphics rules 101 | gfx/tilesets/%.2bpp: tools/gfx += --trim-whitespace 102 | 103 | 104 | ### Catch-all graphics rules 105 | 106 | %.png: ; 107 | 108 | %.2bpp: %.png 109 | $(RGBGFX) $(rgbgfx) -o $@ $< 110 | $(if $(tools/gfx),\ 111 | tools/gfx $(tools/gfx) -o $@ $@) 112 | 113 | %.1bpp: %.png 114 | $(RGBGFX) $(rgbgfx) -d1 -o $@ $< 115 | $(if $(tools/gfx),\ 116 | tools/gfx $(tools/gfx) -d1 -o $@ $@) 117 | 118 | %.pic: %.2bpp 119 | tools/pkmncompress $< $@ -------------------------------------------------------------------------------- /export_templates/gameboy/README.md: -------------------------------------------------------------------------------- 1 | # {{ GAME_NAME }} 2 | 3 | This is a disassembly of {{ GAME_NAME }}. 4 | 5 | It builds the following ROMs: 6 | 7 | - {{ GAME_NAME }}.gb `sha1: {{ ROM_SHA1 }}` 8 | 9 | To set up the repository, see [**INSTALL.md**](INSTALL.md). 10 | 11 | This was auto generated by libRetroReversing for GameBoy -------------------------------------------------------------------------------- /export_templates/gameboy/common.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "./common/constants.asm" 2 | 3 | 4 | SECTION "NULL", ROM0 5 | NULL:: 6 | 7 | z_UNCALLED_FUNCTION:: 8 | 9 | INCLUDE "./common/header.asm" 10 | 11 | 12 | -------------------------------------------------------------------------------- /export_templates/gameboy/common/constants.asm: -------------------------------------------------------------------------------- 1 | ; From http://nocash.emubase.de/pandocs.htm. 2 | 3 | GBC EQU $11 4 | 5 | ; UNTAKEN_JUMP EQU $01 6 | z_UNTAKEN_JUMP_2: MACRO 7 | nop 8 | nop 9 | ENDM 10 | z_UNTAKEN_LONG_JUMP: MACRO 11 | nop 12 | nop 13 | nop 14 | ENDM 15 | 16 | ; memory map 17 | VRAM_Begin EQU $8000 18 | VRAM_End EQU $a000 19 | SRAM_Begin EQU $a000 20 | SRAM_End EQU $c000 21 | WRAM0_Begin EQU $c000 22 | WRAM0_End EQU $d000 23 | WRAM1_Begin EQU $d000 24 | WRAM1_End EQU $e000 25 | ; hardware registers $ff00-$ff80 (see below) 26 | HRAM_Begin EQU $ff80 27 | HRAM_End EQU $ffff 28 | 29 | ; MBC1 30 | MBC1SRamEnable EQU $0000 31 | MBC1RomBank EQU $2000 32 | MBC1SRamBank EQU $4000 33 | MBC1SRamBankingMode EQU $6000 34 | 35 | SRAM_DISABLE EQU $00 36 | SRAM_ENABLE EQU $0a 37 | 38 | NUM_SRAM_BANKS EQU 4 39 | 40 | ; interrupt flags 41 | VBLANK EQU 0 42 | LCD_STAT EQU 1 43 | TIMER EQU 2 44 | SERIAL EQU 3 45 | JOYPAD EQU 4 46 | 47 | LY_VBLANK EQU 145 48 | 49 | ; serial 50 | START_TRANSFER_EXTERNAL_CLOCK EQU $80 51 | START_TRANSFER_INTERNAL_CLOCK EQU $81 52 | 53 | ; Hardware registers 54 | rJOYP EQU $ff00 ; Joypad (R/W) 55 | rSB EQU $ff01 ; Serial transfer data (R/W) 56 | rSC EQU $ff02 ; Serial Transfer Control (R/W) 57 | rSC_ON EQU 7 58 | rSC_CGB EQU 1 59 | rSC_CLOCK EQU 0 60 | rDIV EQU $ff04 ; Divider Register (R/W) 61 | rTIMA EQU $ff05 ; Timer counter (R/W) 62 | rTMA EQU $ff06 ; Timer Modulo (R/W) 63 | rTAC EQU $ff07 ; Timer Control (R/W) 64 | rTAC_ON EQU 2 65 | rTAC_4096_HZ EQU 0 66 | rTAC_262144_HZ EQU 1 67 | rTAC_65536_HZ EQU 2 68 | rTAC_16384_HZ EQU 3 69 | rIF EQU $ff0f ; Interrupt Flag (R/W) 70 | rNR10 EQU $ff10 ; Channel 1 Sweep register (R/W) 71 | rNR11 EQU $ff11 ; Channel 1 Sound length/Wave pattern duty (R/W) 72 | rNR12 EQU $ff12 ; Channel 1 Volume Envelope (R/W) 73 | rNR13 EQU $ff13 ; Channel 1 Frequency lo (Write Only) 74 | rNR14 EQU $ff14 ; Channel 1 Frequency hi (R/W) 75 | rNR21 EQU $ff16 ; Channel 2 Sound Length/Wave Pattern Duty (R/W) 76 | rNR22 EQU $ff17 ; Channel 2 Volume Envelope (R/W) 77 | rNR23 EQU $ff18 ; Channel 2 Frequency lo data (W) 78 | rNR24 EQU $ff19 ; Channel 2 Frequency hi data (R/W) 79 | rNR30 EQU $ff1a ; Channel 3 Sound on/off (R/W) 80 | rNR31 EQU $ff1b ; Channel 3 Sound Length 81 | rNR32 EQU $ff1c ; Channel 3 Select output level (R/W) 82 | rNR33 EQU $ff1d ; Channel 3 Frequency's lower data (W) 83 | rNR34 EQU $ff1e ; Channel 3 Frequency's higher data (R/W) 84 | rNR41 EQU $ff20 ; Channel 4 Sound Length (R/W) 85 | rNR42 EQU $ff21 ; Channel 4 Volume Envelope (R/W) 86 | rNR43 EQU $ff22 ; Channel 4 Polynomial Counter (R/W) 87 | rNR44 EQU $ff23 ; Channel 4 Counter/consecutive; Initial (R/W) 88 | rNR50 EQU $ff24 ; Channel control / ON-OFF / Volume (R/W) 89 | rNR51 EQU $ff25 ; Selection of Sound output terminal (R/W) 90 | rNR52 EQU $ff26 ; Sound on/off 91 | rWave_0 EQU $ff30 92 | rWave_1 EQU $ff31 93 | rWave_2 EQU $ff32 94 | rWave_3 EQU $ff33 95 | rWave_4 EQU $ff34 96 | rWave_5 EQU $ff35 97 | rWave_6 EQU $ff36 98 | rWave_7 EQU $ff37 99 | rWave_8 EQU $ff38 100 | rWave_9 EQU $ff39 101 | rWave_a EQU $ff3a 102 | rWave_b EQU $ff3b 103 | rWave_c EQU $ff3c 104 | rWave_d EQU $ff3d 105 | rWave_e EQU $ff3e 106 | rWave_f EQU $ff3f 107 | rLCDC EQU $ff40 ; LCD Control (R/W) 108 | rLCDC_ENABLE EQU 7 109 | rLCDC_ENABLE_MASK EQU 1 << rLCDC_ENABLE 110 | rSTAT EQU $ff41 ; LCDC Status (R/W) 111 | rSCY EQU $ff42 ; Scroll Y (R/W) 112 | rSCX EQU $ff43 ; Scroll X (R/W) 113 | rLY EQU $ff44 ; LCDC Y-Coordinate (R) 114 | rLYC EQU $ff45 ; LY Compare (R/W) 115 | rDMA EQU $ff46 ; DMA Transfer and Start Address (W) 116 | rBGP EQU $ff47 ; BG Palette Data (R/W) - Non CGB Mode Only 117 | rOBP0 EQU $ff48 ; Object Palette 0 Data (R/W) - Non CGB Mode Only 118 | rOBP1 EQU $ff49 ; Object Palette 1 Data (R/W) - Non CGB Mode Only 119 | rWY EQU $ff4a ; Window Y Position (R/W) 120 | rWX EQU $ff4b ; Window X Position minus 7 (R/W) 121 | rKEY1 EQU $ff4d ; CGB Mode Only - Prepare Speed Switch 122 | rVBK EQU $ff4f ; CGB Mode Only - VRAM Bank 123 | rHDMA1 EQU $ff51 ; CGB Mode Only - New DMA Source, High 124 | rHDMA2 EQU $ff52 ; CGB Mode Only - New DMA Source, Low 125 | rHDMA3 EQU $ff53 ; CGB Mode Only - New DMA Destination, High 126 | rHDMA4 EQU $ff54 ; CGB Mode Only - New DMA Destination, Low 127 | rHDMA5 EQU $ff55 ; CGB Mode Only - New DMA Length/Mode/Start 128 | rRP EQU $ff56 ; CGB Mode Only - Infrared Communications Port 129 | rBGPI EQU $ff68 ; CGB Mode Only - Background Palette Index 130 | rBGPD EQU $ff69 ; CGB Mode Only - Background Palette Data 131 | rOBPI EQU $ff6a ; CGB Mode Only - Sprite Palette Index 132 | rOBPD EQU $ff6b ; CGB Mode Only - Sprite Palette Data 133 | rUNKNOWN1 EQU $ff6c ; (FEh) Bit 0 (Read/Write) - CGB Mode Only 134 | rSVBK EQU $ff70 ; CGB Mode Only - WRAM Bank 135 | rUNKNOWN2 EQU $ff72 ; (00h) - Bit 0-7 (Read/Write) 136 | rUNKNOWN3 EQU $ff73 ; (00h) - Bit 0-7 (Read/Write) 137 | rUNKNOWN4 EQU $ff74 ; (00h) - Bit 0-7 (Read/Write) - CGB Mode Only 138 | rUNKNOWN5 EQU $ff75 ; (8Fh) - Bit 4-6 (Read/Write) 139 | rUNKNOWN6 EQU $ff76 ; (00h) - Always 00h (Read Only) 140 | rUNKNOWN7 EQU $ff77 ; (00h) - Always 00h (Read Only) 141 | rIE EQU $ffff ; Interrupt Enable (R/W) 142 | 143 | 144 | -------------------------------------------------------------------------------- /export_templates/gameboy/common/header.asm: -------------------------------------------------------------------------------- 1 | ; rst vectors (unused) 2 | 3 | ;SECTION "rst0", ROM0[$0000] 4 | ; rst $38 5 | ; 6 | ; ds $08 - @, 0 ; unused 7 | ; 8 | ;SECTION "rst8", ROM0[$0008] 9 | ; rst $38 10 | ; 11 | ; ds $10 - @, 0 ; unused 12 | ; 13 | ;SECTION "rst10", ROM0[$0010] 14 | ; rst $38 15 | ; 16 | ; ds $18 - @, 0 ; unused 17 | ; 18 | ;SECTION "rst18", ROM0[$0018] 19 | ; rst $38 20 | ; 21 | ; ds $20 - @, 0 ; unused 22 | ; 23 | ;SECTION "rst20", ROM0[$0020] 24 | ; rst $38 25 | ; 26 | ; ds $28 - @, 0 ; unused 27 | ; 28 | ;SECTION "rst28", ROM0[$0028] 29 | ; rst $38 30 | ; 31 | ; ds $30 - @, 0 ; unused 32 | ; 33 | ;SECTION "rst30", ROM0[$0030] 34 | ; rst $38 35 | ; 36 | ; ds $38 - @, 0 ; unused 37 | ; 38 | ;SECTION "rst38", ROM0[$0038] 39 | ; rst $38 40 | ; 41 | ; ds $40 - @, 0 ; unused 42 | ; 43 | 44 | ; Game Boy hardware interrupts 45 | 46 | ;SECTION "vblank", ROM0[$0040] 47 | ;jp VBlank 48 | ; nop 49 | ; nop 50 | ; nop 51 | 52 | ; ds $48 - @, 0 ; unused 53 | 54 | ;SECTION "lcd", ROM0[$0048] 55 | ; rst $38 56 | ; 57 | ; ds $50 - @, 0 ; unused 58 | 59 | ;SECTION "timer", ROM0[$0050] 60 | ;jp Timer 61 | ; nop 62 | ; nop 63 | ; nop 64 | 65 | ; ds $58 - @, 0 ; unused 66 | 67 | ;SECTION "serial", ROM0[$0058] 68 | ; ;jp Serial 69 | ; nop 70 | ; nop 71 | ; nop 72 | ; ds $60 - @, 0 ; unused 73 | 74 | ;SECTION "joypad", ROM0[$0060] 75 | ; reti 76 | 77 | 78 | ;SECTION "Header", ROM0[$0100] 79 | 80 | ;Start:: 81 | ; Nintendo requires all Game Boy ROMs to begin with a nop ($00) and a jp ($C3) 82 | ; to the starting address. 83 | ; nop 84 | ; jp _Start 85 | 86 | 87 | ; The Game Boy cartridge header data is patched over by rgbfix. 88 | ; This makes sure it doesn't get used for anything else. 89 | 90 | ; ds $0150 - @ 91 | 92 | ;_Start:: 93 | ; nop 94 | 95 | -------------------------------------------------------------------------------- /export_templates/gameboy/common/rgbdscheck.asm: -------------------------------------------------------------------------------- 1 | ; game requires rgbds 0.4.2 or newer. 2 | MAJOR EQU 0 3 | MINOR EQU 4 4 | PATCH EQU 2 5 | 6 | IF !DEF(__RGBDS_MAJOR__) || !DEF(__RGBDS_MINOR__) || !DEF(__RGBDS_PATCH__) 7 | fail "NOT defined:game requires rgbds 0.4.2 or newer." 8 | ELSE 9 | IF (__RGBDS_MAJOR__ < MAJOR) || \ 10 | (__RGBDS_MAJOR__ == MAJOR && __RGBDS_MINOR__ < MINOR) 11 | ; || (__RGBDS_MAJOR__ == MAJOR && __RGBDS_MINOR__ == MINOR && __RGBDS_PATCH__ < PATCH) 12 | fail "game requires rgbds 0.4.2 or newer." 13 | ENDC 14 | ENDC 15 | -------------------------------------------------------------------------------- /export_templates/gameboy/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Gameboy RGBDS Source Exporter", 3 | "dirs": [ 4 | "common" 5 | ], 6 | "files": [ 7 | "Makefile", 8 | "README.md", 9 | "INSTALL.md", 10 | ".gitignore", 11 | "layout.link", 12 | "common.asm", 13 | "common/rgbdscheck.asm", 14 | "common/header.asm", 15 | "common/constants.asm", 16 | "tools/scan_includes.c", 17 | "tools/Makefile" 18 | ], 19 | "main": "main.asm", 20 | "asm_extenstion": ".asm" 21 | } -------------------------------------------------------------------------------- /export_templates/gameboy/layout.link: -------------------------------------------------------------------------------- 1 | ROM0 2 | org $0000 3 | "NULL" 4 | ; org $0000 5 | ; "rst0" 6 | ; org $0008 7 | ; "rst8" 8 | ; org $0010 9 | ; "rst10" 10 | ; org $0018 11 | ; "rst18" 12 | ; org $0020 13 | ; "rst20" 14 | ; org $0028 15 | ; "rst28" 16 | ; org $0030 17 | ; "rst30" 18 | ; org $0038 19 | ; "rst38" 20 | ; org $0040 21 | ; "vblank" 22 | ; org $0048 23 | ; "lcd" 24 | ; org $0050 25 | ; "timer" 26 | ; org $0058 27 | ; "serial" 28 | ; org $0060 29 | ; "joypad" 30 | ; $0061 31 | ; "High Home" 32 | ; org $100 33 | ; "Header" 34 | ; org $150 35 | ; "Home" 36 | ROMX $1 37 | ; "bank1" 38 | ROMX $2 39 | ; "Sound Effect Headers 1" 40 | ; "Music Headers 1" 41 | ; "Sound Effects 1" 42 | ; "Audio Engine 1" 43 | ; "Music 1" 44 | ;ROMX $3 45 | ; "bank3" 46 | ;ROMX $4 47 | ; "NPC Sprites 1" 48 | ; "Font Graphics" 49 | ; "Battle Engine 1" 50 | ;ROMX $5 51 | ; "NPC Sprites 2" 52 | ; "Battle Engine 2" 53 | ;ROMX $6 54 | ; "Maps 1" 55 | ; "Play Time" 56 | ; "Maps 2" 57 | ; "Doors and Ledges" 58 | ;ROMX $7 59 | ; "Maps 3" 60 | ; "Pokémon Names" 61 | ; "Maps 4" 62 | ; "Hidden Objects 1" 63 | ;ROMX $8 64 | ; "Sound Effect Headers 2" 65 | ; "Music Headers 2" 66 | ; "Sound Effects 2" 67 | ; "Low Health Alarm (Audio Engine 2)" 68 | ; "Bill's PC" 69 | ; "Audio Engine 2" 70 | ; "Music 2" 71 | ;ROMX $9 72 | ; "Pics 1" 73 | ; "Battle Engine 3" 74 | ;ROMX $A 75 | ; "Pics 2" 76 | ; "Battle Engine 4" 77 | ;ROMX $B 78 | ; "Pics 3" 79 | ; "Battle Engine 5" 80 | ;ROMX $C 81 | ; "Pics 4" 82 | ; "Battle Engine 6" 83 | ;ROMX $D 84 | ; "Pics 5" 85 | ; "Slot Machines" 86 | ;ROMX $E 87 | ; "Battle Engine 7" 88 | ;ROMX $F 89 | ; "Battle Core" 90 | ;ROMX $10 91 | ; "bank10" 92 | ;ROMX $11 93 | ; "Maps 5" 94 | ; "Pokédex Rating" 95 | ; "Maps 6" 96 | ; "Hidden Objects Core" 97 | ;ROMX $12 98 | ; "Maps 7" 99 | ; "Screen Effects" 100 | ; "Maps 8" 101 | ;ROMX $13 102 | ; "Pics 6" 103 | ; "Maps 9" 104 | ; "Predefs" 105 | ;ROMX $14 106 | ; "Maps 10" 107 | ; "Battle Engine 8" 108 | ; "Hidden Objects 2" 109 | ;ROMX $15 110 | ; "Maps 11" 111 | ; "Battle Engine 9" 112 | ; "Maps 12" 113 | ; "Diploma" 114 | ; "Trainer Sight" 115 | ;ROMX $16 116 | ; "Maps 13" 117 | ; "Battle Engine 10" 118 | ; "Maps 14" 119 | ; "Saffron Guards" 120 | ;ROMX $17 121 | ; "Maps 15" 122 | ; "Starter Dex" 123 | ; "Maps 16" 124 | ; "Hidden Objects 3" 125 | ;ROMX $18 126 | ; "Maps 17" 127 | ; "Cinnabar Lab Fossils" 128 | ; "Maps 18" 129 | ; "Hidden Objects 4" 130 | ;ROMX $19 131 | ; "Tilesets 1" 132 | ;ROMX $1A 133 | ; "Battle Engine 11" 134 | ; "Tilesets 2" 135 | ;ROMX $1B 136 | ; "Tilesets 3" 137 | ;ROMX $1C 138 | ; "bank1C" 139 | ;ROMX $1D 140 | ; "Maps 19" 141 | ; "Itemfinder 1" 142 | ; "Maps 20" 143 | ; "Vending Machine" 144 | ; "Maps 21" 145 | ; "Itemfinder 2" 146 | ;ROMX $1E 147 | ; "bank1E" 148 | ;ROMX $1F 149 | ; "Sound Effect Headers 3" 150 | ; "Music Headers 3" 151 | ; "Sound Effects 3" 152 | ; "Audio Engine 3" 153 | ; "Music 3" 154 | ;ROMX $20 155 | ; "Text 1" 156 | ;ROMX $21 157 | ; "Text 2" 158 | ;ROMX $22 159 | ; "Text 3" 160 | ;ROMX $23 161 | ; "Text 4" 162 | ;ROMX $24 163 | ; "Text 5" 164 | ;ROMX $25 165 | ; "Text 6" 166 | ;ROMX $26 167 | ; "Text 7" 168 | ;ROMX $27 169 | ; "Text 8" 170 | ;ROMX $28 171 | ; "Text 9" 172 | ;ROMX $29 173 | ; "Text 10" 174 | ;ROMX $2A 175 | ; "Text 11" 176 | ;ROMX $2B 177 | ; "Pokédex Text" 178 | ;ROMX $2C 179 | ; "Move Names" 180 | ;WRAM0 181 | ; "WRAM" 182 | ; org $c100 183 | ; "Sprite State Data" 184 | ; "OAM Buffer" 185 | ; org $dfff 186 | ; "Stack" 187 | ;VRAM 188 | ; "VRAM" 189 | ;SRAM $0 190 | ; "Sprite Buffers" 191 | ;SRAM $1 192 | ; "Save Data" 193 | ;SRAM $2 194 | ; "Saved Boxes 1" 195 | ;SRAM $3 196 | ; "Saved Boxes 2" 197 | ;HRAM 198 | ; "OAM DMA" 199 | ; "HRAM" -------------------------------------------------------------------------------- /export_templates/gameboy/tools/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | CC := gcc 4 | CFLAGS := -O3 -std=c99 -Wall -Wextra -pedantic 5 | 6 | tools := scan_includes #gfx pkmncompress 7 | 8 | all: $(tools) 9 | @: 10 | 11 | clean: 12 | rm -f $(tools) 13 | 14 | gfx: common.h 15 | %: %.c 16 | $(CC) $(CFLAGS) -o $@ $< -------------------------------------------------------------------------------- /export_templates/gameboy/tools/scan_includes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void usage(void) { 8 | printf("Usage: scan_includes [-h] [-s] filename\n" 9 | "-h, --help\n" 10 | " Print usage and exit\n" 11 | "-s, --strict\n" 12 | " Fail if a file cannot be read\n"); 13 | } 14 | 15 | struct Options { 16 | bool help; 17 | bool strict; 18 | }; 19 | 20 | struct Options Options = {0}; 21 | 22 | void scan_file(char* filename) { 23 | FILE *f = fopen(filename, "rb"); 24 | if (!f) { 25 | if (Options.strict) { 26 | fprintf(stderr, "Could not open file: '%s'\n", filename); 27 | exit(1); 28 | } else { 29 | return; 30 | } 31 | } 32 | 33 | fseek(f, 0, SEEK_END); 34 | long size = ftell(f); 35 | rewind(f); 36 | 37 | char *buffer = malloc(size + 1); 38 | char *orig = buffer; 39 | size = fread(buffer, 1, size, f); 40 | buffer[size] = '\0'; 41 | fclose(f); 42 | 43 | for (; buffer && (buffer - orig < size); buffer++) { 44 | bool is_include = false; 45 | bool is_incbin = false; 46 | switch (*buffer) { 47 | case ';': 48 | buffer = strchr(buffer, '\n'); 49 | if (!buffer) { 50 | fprintf(stderr, "%s: no newline at end of file\n", filename); 51 | break; 52 | } 53 | break; 54 | 55 | case '"': 56 | buffer++; 57 | buffer = strchr(buffer, '"'); 58 | if (!buffer) { 59 | fprintf(stderr, "%s: unterminated string\n", filename); 60 | break; 61 | } 62 | buffer++; 63 | break; 64 | 65 | case 'i': 66 | case 'I': 67 | if ((strncmp(buffer, "INCBIN", 6) == 0) || (strncmp(buffer, "incbin", 6) == 0)) { 68 | is_incbin = true; 69 | } else if ((strncmp(buffer, "INCLUDE", 7) == 0) || (strncmp(buffer, "include", 7) == 0)) { 70 | is_include = true; 71 | } 72 | if (is_incbin || is_include) { 73 | buffer = strchr(buffer, '"'); 74 | if (!buffer) { 75 | break; 76 | } 77 | buffer++; 78 | int length = strcspn(buffer, "\""); 79 | char *include = malloc(length + 1); 80 | strncpy(include, buffer, length); 81 | include[length] = '\0'; 82 | printf("%s ", include); 83 | if (is_include) { 84 | scan_file(include); 85 | } 86 | free(include); 87 | buffer = strchr(buffer, '"'); 88 | } 89 | break; 90 | 91 | } 92 | if (!buffer) { 93 | break; 94 | } 95 | 96 | } 97 | 98 | free(orig); 99 | } 100 | 101 | int main(int argc, char* argv[]) { 102 | int i = 0; 103 | struct option long_options[] = { 104 | {"strict", no_argument, 0, 's'}, 105 | {"help", no_argument, 0, 'h'}, 106 | {0} 107 | }; 108 | int opt = -1; 109 | while ((opt = getopt_long(argc, argv, "sh", long_options, &i)) != -1) { 110 | switch (opt) { 111 | case 's': 112 | Options.strict = true; 113 | break; 114 | case 'h': 115 | Options.help = true; 116 | break; 117 | default: 118 | usage(); 119 | exit(1); 120 | break; 121 | } 122 | } 123 | argc -= optind; 124 | argv += optind; 125 | if (Options.help) { 126 | usage(); 127 | return 0; 128 | } 129 | if (argc < 1) { 130 | usage(); 131 | exit(1); 132 | } 133 | scan_file(argv[0]); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /export_templates/gamegear/.gitignore: -------------------------------------------------------------------------------- 1 | # compiled objects 2 | *.o 3 | 4 | # compiled graphics 5 | *.1bpp 6 | *.2bpp 7 | *.pic 8 | 9 | # compiled roms 10 | *.gbc 11 | *.gb 12 | 13 | # rgbds extras 14 | *.map 15 | *.sym 16 | 17 | # tool binaries 18 | *.exe 19 | 20 | # precompiled python 21 | *.pyc 22 | *$py.class 23 | 24 | # save game files 25 | *.sgm 26 | *.sav 27 | *.rtc 28 | *.sn* 29 | *.sa* 30 | *.sg1 -------------------------------------------------------------------------------- /export_templates/gamegear/Makefile: -------------------------------------------------------------------------------- 1 | roms := {{ GAME_NAME }}_rr.gg 2 | 3 | rom_obj := \ 4 | data.o \ 5 | main.o \ 6 | # common.o \ 7 | # jumps.o \ 8 | 9 | game_obj := $(rom_obj:.o=_rr.o) 10 | 11 | 12 | 13 | ### Build tools 14 | 15 | ifeq (,$(shell which sha1sum)) 16 | SHA1 := shasum 17 | else 18 | SHA1 := sha1sum 19 | endif 20 | 21 | WLA ?= 22 | ASM ?= $(WLA)wla-z80 23 | RGBFIX ?= $(WLA)rgbfix 24 | RGBGFX ?= $(WLA)rgbgfx 25 | LINKER ?= $(WLA)wlalink 26 | 27 | 28 | ### Build targets 29 | 30 | .SUFFIXES: 31 | .SECONDEXPANSION: 32 | .PRECIOUS: 33 | .SECONDARY: 34 | .PHONY: all red clean tidy compare 35 | 36 | all: $(roms) 37 | game: {{ GAME_NAME }}.gb 38 | 39 | clean: tidy 40 | find gfx \( -iname '*.1bpp' -o -iname '*.2bpp' -o -iname '*.pic' \) -delete 41 | 42 | tidy: 43 | rm -f $(roms) $(game_obj) $(roms:.gb=.map) $(roms:.gb=.sym) 44 | $(MAKE) clean -C tools/ 45 | 46 | compare: $(roms) 47 | @$(SHA1) -c roms.sha1 48 | 49 | 50 | ASMFLAGS = -v 51 | 52 | $(gameobj): ASMFLAGS += -D _libRR 53 | 54 | # The dep rules have to be explicit or else missing files won't be reported. 55 | # As a side effect, they're evaluated immediately instead of when the rule is invoked. 56 | # It doesn't look like $(shell) can be deferred so there might not be a better way. 57 | define DEP 58 | $1: $2 $$(shell tools/scan_includes $2) 59 | $$(ASM) $$(ASMFLAGS) -o $$@ $$< 60 | endef 61 | 62 | # Build tools when building the rom. 63 | # This has to happen before the rules are processed, since that's when scan_includes is run. 64 | ifeq (,$(filter clean tidy tools,$(MAKECMDGOALS))) 65 | 66 | $(info $(shell $(MAKE) -C tools)) 67 | 68 | # Dependencies for objects (drop _red and _blue from asm file basenames) 69 | $(foreach obj, $(game_obj), $(eval $(call DEP,$(obj),$(obj:_rr.o=.asm)))) 70 | 71 | endif 72 | 73 | 74 | %.asm: ; 75 | 76 | 77 | game_pad = 0x00 78 | 79 | game_opt = -jsv -n 0 -k 01 -l 0x33 -m 0x13 -r 03 -t "{{ GAME_NAME }}" 80 | 81 | %.gg: $$(game_obj) 82 | #echo "[objects]\n$(filter %.o,$^)">{{ GAME_NAME }}.link 83 | $(LINKER) -s -S layout.link $@ 84 | #$(RGBFIX) -p $(game_pad) $(game_opt) $@ 85 | 86 | 87 | ### Misc file-specific graphics rules 88 | gfx/tilesets/%.2bpp: tools/gfx += --trim-whitespace 89 | 90 | 91 | ### Catch-all graphics rules 92 | 93 | %.png: ; 94 | 95 | %.2bpp: %.png 96 | $(RGBGFX) $(rgbgfx) -o $@ $< 97 | $(if $(tools/gfx),\ 98 | tools/gfx $(tools/gfx) -o $@ $@) 99 | 100 | %.1bpp: %.png 101 | $(RGBGFX) $(rgbgfx) -d1 -o $@ $< 102 | $(if $(tools/gfx),\ 103 | tools/gfx $(tools/gfx) -d1 -o $@ $@) 104 | 105 | %.pic: %.2bpp 106 | tools/pkmncompress $< $@ -------------------------------------------------------------------------------- /export_templates/gamegear/README.md: -------------------------------------------------------------------------------- 1 | # {{ GAME_NAME }} 2 | 3 | This is a disassembly of {{ GAME_NAME }}. 4 | 5 | It builds the following ROMs: 6 | 7 | - {{ GAME_NAME }}.gb `sha1: {{ ROM_SHA1 }}` 8 | 9 | To set up the repository, see [**INSTALL.md**](INSTALL.md). 10 | 11 | This was auto generated by libRetroReversing for GameGear -------------------------------------------------------------------------------- /export_templates/gamegear/common.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "./common/constants.asm" 2 | 3 | 4 | SECTION "NULL", ROM0 5 | NULL:: 6 | 7 | z_UNCALLED_FUNCTION:: 8 | 9 | INCLUDE "./common/header.asm" 10 | 11 | 12 | -------------------------------------------------------------------------------- /export_templates/gamegear/common/constants.asm: -------------------------------------------------------------------------------- 1 | ; TODO: Add gamegear constants here 2 | 3 | .MACRO z_UNTAKEN_JUMP_2 4 | .REPT 2 5 | NOP 6 | .ENDR 7 | .ENDM 8 | 9 | .MACRO z_UNTAKEN_JUMP_3 10 | .REPT 3 11 | NOP 12 | .ENDR 13 | .ENDM 14 | 15 | -------------------------------------------------------------------------------- /export_templates/gamegear/common/header.asm: -------------------------------------------------------------------------------- 1 | ; rst vectors (unused) 2 | 3 | ;SECTION "rst0", ROM0[$0000] 4 | ; rst $38 5 | ; 6 | ; ds $08 - @, 0 ; unused 7 | ; 8 | ;SECTION "rst8", ROM0[$0008] 9 | ; rst $38 10 | ; 11 | ; ds $10 - @, 0 ; unused 12 | ; 13 | ;SECTION "rst10", ROM0[$0010] 14 | ; rst $38 15 | ; 16 | ; ds $18 - @, 0 ; unused 17 | ; 18 | ;SECTION "rst18", ROM0[$0018] 19 | ; rst $38 20 | ; 21 | ; ds $20 - @, 0 ; unused 22 | ; 23 | ;SECTION "rst20", ROM0[$0020] 24 | ; rst $38 25 | ; 26 | ; ds $28 - @, 0 ; unused 27 | ; 28 | ;SECTION "rst28", ROM0[$0028] 29 | ; rst $38 30 | ; 31 | ; ds $30 - @, 0 ; unused 32 | ; 33 | ;SECTION "rst30", ROM0[$0030] 34 | ; rst $38 35 | ; 36 | ; ds $38 - @, 0 ; unused 37 | ; 38 | ;SECTION "rst38", ROM0[$0038] 39 | ; rst $38 40 | ; 41 | ; ds $40 - @, 0 ; unused 42 | ; 43 | 44 | ; Game Boy hardware interrupts 45 | 46 | ;SECTION "vblank", ROM0[$0040] 47 | ;jp VBlank 48 | ; nop 49 | ; nop 50 | ; nop 51 | 52 | ; ds $48 - @, 0 ; unused 53 | 54 | ;SECTION "lcd", ROM0[$0048] 55 | ; rst $38 56 | ; 57 | ; ds $50 - @, 0 ; unused 58 | 59 | ;SECTION "timer", ROM0[$0050] 60 | ;jp Timer 61 | ; nop 62 | ; nop 63 | ; nop 64 | 65 | ; ds $58 - @, 0 ; unused 66 | 67 | ;SECTION "serial", ROM0[$0058] 68 | ; ;jp Serial 69 | ; nop 70 | ; nop 71 | ; nop 72 | ; ds $60 - @, 0 ; unused 73 | 74 | ;SECTION "joypad", ROM0[$0060] 75 | ; reti 76 | 77 | 78 | ;SECTION "Header", ROM0[$0100] 79 | 80 | ;Start:: 81 | ; Nintendo requires all Game Boy ROMs to begin with a nop ($00) and a jp ($C3) 82 | ; to the starting address. 83 | ; nop 84 | ; jp _Start 85 | 86 | 87 | ; The Game Boy cartridge header data is patched over by rgbfix. 88 | ; This makes sure it doesn't get used for anything else. 89 | 90 | ; ds $0150 - @ 91 | 92 | ;_Start:: 93 | ; nop 94 | 95 | -------------------------------------------------------------------------------- /export_templates/gamegear/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Game Gear WLA-DX Source Exporter", 3 | "dirs": [ 4 | "common" 5 | ], 6 | "files": [ 7 | "Makefile", 8 | "README.md", 9 | "INSTALL.md", 10 | ".gitignore", 11 | "common.asm", 12 | "layout.link", 13 | "common/header.asm", 14 | "common/constants.asm", 15 | "tools/scan_includes.c", 16 | "tools/Makefile" 17 | ], 18 | "main": "main.asm", 19 | "asm_extenstion": ".asm" 20 | } -------------------------------------------------------------------------------- /export_templates/gamegear/layout.link: -------------------------------------------------------------------------------- 1 | [objects] 2 | main_rr.o 3 | data_rr.o 4 | -------------------------------------------------------------------------------- /export_templates/gamegear/tools/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all clean 2 | 3 | CC := gcc 4 | CFLAGS := -O3 -std=c99 -Wall -Wextra -pedantic 5 | 6 | tools := scan_includes #gfx pkmncompress 7 | 8 | all: $(tools) 9 | @: 10 | 11 | clean: 12 | rm -f $(tools) 13 | 14 | gfx: common.h 15 | %: %.c 16 | $(CC) $(CFLAGS) -o $@ $< -------------------------------------------------------------------------------- /export_templates/gamegear/tools/scan_includes.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | void usage(void) { 8 | printf("Usage: scan_includes [-h] [-s] filename\n" 9 | "-h, --help\n" 10 | " Print usage and exit\n" 11 | "-s, --strict\n" 12 | " Fail if a file cannot be read\n"); 13 | } 14 | 15 | struct Options { 16 | bool help; 17 | bool strict; 18 | }; 19 | 20 | struct Options Options = {0}; 21 | 22 | void scan_file(char* filename) { 23 | FILE *f = fopen(filename, "rb"); 24 | if (!f) { 25 | if (Options.strict) { 26 | fprintf(stderr, "Could not open file: '%s'\n", filename); 27 | exit(1); 28 | } else { 29 | return; 30 | } 31 | } 32 | 33 | fseek(f, 0, SEEK_END); 34 | long size = ftell(f); 35 | rewind(f); 36 | 37 | char *buffer = malloc(size + 1); 38 | char *orig = buffer; 39 | size = fread(buffer, 1, size, f); 40 | buffer[size] = '\0'; 41 | fclose(f); 42 | 43 | for (; buffer && (buffer - orig < size); buffer++) { 44 | bool is_include = false; 45 | bool is_incbin = false; 46 | switch (*buffer) { 47 | case ';': 48 | buffer = strchr(buffer, '\n'); 49 | if (!buffer) { 50 | fprintf(stderr, "%s: no newline at end of file\n", filename); 51 | break; 52 | } 53 | break; 54 | 55 | case '"': 56 | buffer++; 57 | buffer = strchr(buffer, '"'); 58 | if (!buffer) { 59 | fprintf(stderr, "%s: unterminated string\n", filename); 60 | break; 61 | } 62 | buffer++; 63 | break; 64 | 65 | case 'i': 66 | case 'I': 67 | if ((strncmp(buffer, "INCBIN", 6) == 0) || (strncmp(buffer, "incbin", 6) == 0)) { 68 | is_incbin = true; 69 | } else if ((strncmp(buffer, "INCLUDE", 7) == 0) || (strncmp(buffer, "include", 7) == 0)) { 70 | is_include = true; 71 | } 72 | if (is_incbin || is_include) { 73 | buffer = strchr(buffer, '"'); 74 | if (!buffer) { 75 | break; 76 | } 77 | buffer++; 78 | int length = strcspn(buffer, "\""); 79 | char *include = malloc(length + 1); 80 | strncpy(include, buffer, length); 81 | include[length] = '\0'; 82 | printf("%s ", include); 83 | if (is_include) { 84 | scan_file(include); 85 | } 86 | free(include); 87 | buffer = strchr(buffer, '"'); 88 | } 89 | break; 90 | 91 | } 92 | if (!buffer) { 93 | break; 94 | } 95 | 96 | } 97 | 98 | free(orig); 99 | } 100 | 101 | int main(int argc, char* argv[]) { 102 | int i = 0; 103 | struct option long_options[] = { 104 | {"strict", no_argument, 0, 's'}, 105 | {"help", no_argument, 0, 'h'}, 106 | {0} 107 | }; 108 | int opt = -1; 109 | while ((opt = getopt_long(argc, argv, "sh", long_options, &i)) != -1) { 110 | switch (opt) { 111 | case 's': 112 | Options.strict = true; 113 | break; 114 | case 'h': 115 | Options.help = true; 116 | break; 117 | default: 118 | usage(); 119 | exit(1); 120 | break; 121 | } 122 | } 123 | argc -= optind; 124 | argv += optind; 125 | if (Options.help) { 126 | usage(); 127 | return 0; 128 | } 129 | if (argc < 1) { 130 | usage(); 131 | exit(1); 132 | } 133 | scan_file(argv[0]); 134 | return 0; 135 | } 136 | -------------------------------------------------------------------------------- /include/libRR_c.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBRETRO_REVERSING_C_H__ 2 | #define LIBRETRO_REVERSING_C_H__ 3 | #include "./libretro.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | extern const char* libRR_console; 10 | extern int libRR_emulated_hardware; // used if the emulator core supports multiple consoles 11 | 12 | extern bool libRR_full_function_log; 13 | extern bool libRR_finished_boot_rom; 14 | extern enum retro_pixel_format libRR_core_pixel_format; 15 | 16 | // Bank Switching 17 | extern uint16_t libRR_current_bank_slot_0; 18 | extern uint16_t libRR_current_bank_slot_1; 19 | extern uint16_t libRR_current_bank_slot_2; 20 | 21 | int get_current_bank_number_for_address(uint32_t addr); 22 | 23 | // Util 24 | const char* n2hexstr_c(int number, size_t hex_len); 25 | uint16_t two_bytes_to_16bit_value(uint8_t byte1, uint8_t byte2); 26 | uint32_t three_bytes_to_24bit_value(uint8_t byte1, uint8_t byte2, uint8_t byte3); 27 | 28 | 29 | // Trace logging 30 | extern bool libRR_full_trace_log; 31 | void libRR_log_trace(const char* message); 32 | void libRR_log_trace_flush(); 33 | 34 | // DMA logging 35 | void libRR_log_dma(int32_t offset); 36 | 37 | // Jump logging 38 | const char* libRR_log_long_jump(uint32_t current_pc, uint32_t jump_target, const char* type); 39 | 40 | // Call logging 41 | void libRR_log_rst(uint32_t current_pc, uint32_t jump_target); 42 | const char* libRR_log_function_call(uint32_t current_pc, uint32_t target_pc, uint32_t stack_pointer); 43 | void libRR_log_interrupt_call(uint32_t current_pc, uint32_t target_pc); 44 | void libRR_log_return_statement(uint32_t current_pc, uint32_t return_target, uint32_t stack_pointer); 45 | 46 | 47 | // Standard 48 | void libRR_video_cb(const void *fb, unsigned int width, unsigned int height, unsigned int pitch); 49 | extern void libRR_handle_load_game(const struct retro_game_info *info, retro_environment_t environ_cb); 50 | 51 | 52 | // N64 Memory logging 53 | void cdl_log_mem_write(const uint32_t lsaddr, uint32_t pc); 54 | void cdl_log_opcode_error(); 55 | void cdl_log_jump_return(int take_jump, uint32_t jump_target, uint32_t pc, uint32_t ra, int64_t* registers, struct r4300_core* r4300); 56 | uint32_t cdl_get_alternative_jump(uint32_t current_jump); 57 | int cdl_log_jump(int take_jump, uint32_t jump_target, uint8_t* jump_target_memory, uint32_t pc, uint32_t ra); 58 | void cdl_log_opcode(uint32_t program_counter, uint8_t* op_address); 59 | void cdl_log_jump_always(int take_jump, uint32_t jump_target, uint8_t* jump_target_memory, uint32_t ra, uint32_t pc); 60 | 61 | 62 | // ASM instruction logging 63 | const char* libRR_asm_format(); 64 | void libRR_log_instruction(uint32_t current_pc, const char* name, uint32_t instruction_bytes, int number_of_bytes); 65 | void libRR_log_instruction_1string(uint32_t current_pc, const char* c_name, uint32_t instruction_bytes, int number_of_bytes, const char* name); 66 | void libRR_log_instruction_1int_registername(uint32_t current_pc, const char* c_name, uint32_t instruction_bytes, int number_of_bytes, uint32_t operand, const char* register_name); 67 | void libRR_log_instruction_1int(uint32_t current_pc, const char* c_name, uint32_t instruction_bytes, int number_of_bytes, uint32_t operand); 68 | void libRR_log_instruction_2int(uint32_t current_pc, const char* c_name, uint32_t instruction_bytes, int number_of_bytes, uint32_t operand, uint32_t operand2); 69 | void libRR_log_instruction_z80_s_d(uint32_t current_pc, const char* c_name, uint32_t instruction_bytes, int number_of_bytes, const char* source, const char* destination); 70 | const char* libRR_log_jump_label(uint32_t offset, uint32_t current_pc); 71 | void libRR_log_memory_read(int8_t bank, int32_t offset, const char* type, uint8_t byte_size, char* bytes); 72 | void libRR_log_rom_read(int16_t bank, int32_t offset, const char* type, uint8_t byte_size, char* bytes); 73 | void libRR_gameboy_log_memory_read(int32_t offset, const char* type, uint8_t byte_size, char* bytes); 74 | 75 | 76 | void libRR_set_retro_memmap(struct retro_memory_descriptor* descs, int num_descriptors); 77 | //extern struct retro_memory_descriptor libRR_mmap[12]; 78 | extern int libRR_mmap_descriptors; 79 | 80 | void libRR_setInputDescriptor(struct retro_input_descriptor* descriptor, int total); 81 | retro_input_state_t libRR_handle_input(retro_input_state_t input_cb); 82 | extern struct retro_memory_map libRR_retromap; 83 | 84 | // Main 85 | bool libRR_run_frame(); 86 | 87 | // Save states 88 | void libRR_create_save_state_c(const char* name, int frame, bool fast_save); // C version creating the save state and saving screenshot and metadata 89 | void libRR_load_save_state_c(int frame); // C version for loading libRR metadata along with save 90 | 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif -------------------------------------------------------------------------------- /interpreter/duktape/LICENSE.txt: -------------------------------------------------------------------------------- 1 | =============== 2 | Duktape license 3 | =============== 4 | 5 | (http://opensource.org/licenses/MIT) 6 | 7 | Copyright (c) 2013-2019 by Duktape authors (see AUTHORS.rst) 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in 17 | all copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /interpreter/mjs/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2018 Cesanta Software Limited 2 | All rights reserved 3 | 4 | This software is dual-licensed: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License version 2 as 6 | published by the Free Software Foundation. For the terms of this 7 | license, see . 8 | 9 | You are free to use this software under the terms of the GNU General 10 | Public License, but WITHOUT ANY WARRANTY; without even the implied 11 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 12 | See the GNU General Public License for more details. 13 | 14 | Alternatively, you can license this software under a commercial 15 | license, as set out in . 16 | -------------------------------------------------------------------------------- /source_exporter/CommonSourceExport.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBRR_COMMON_SOURCE_EXPORT_H__ 2 | #define LIBRR_COMMON_SOURCE_EXPORT_H__ 3 | 4 | extern json allLabels; 5 | void get_all_assembly_labels(); 6 | string write_callers(json callers); 7 | void get_all_unwritten_labels(); 8 | string get_function_export_path(string offset, json func, string bank); 9 | string get_function_name(string bank, string offset); 10 | string write_asm_until_null(string bank_number, string offset_str, bool is_function, string section_name, json callers); 11 | bool should_stop_writing_asm(int start_offset, uint32_t i, string bank_number); 12 | string write_bank_header_comment(string bank); 13 | string write_section_header(string offset_str, string bank_number, string section_name); 14 | void libRR_export_function_data(); 15 | void libRR_export_rom_data(); 16 | void libRR_export_jump_data(); 17 | 18 | extern string libRR_org_directive; 19 | extern string libRR_bank_directive; 20 | extern string libRR_slot_directive; 21 | extern int libRR_total_banks; 22 | 23 | // console specific 24 | extern "C" { 25 | string get_slot_for_address(int32_t offset); 26 | string write_console_asm_header(); 27 | } 28 | 29 | #endif -------------------------------------------------------------------------------- /websrc/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /websrc/HomePage.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | import Typography from '@material-ui/core/Typography'; 3 | import Container from '@material-ui/core/Container'; 4 | import AppBar from '@material-ui/core/AppBar'; 5 | import Toolbar from '@material-ui/core/Toolbar'; 6 | import { ThemeProvider } from '@material-ui/core/styles'; 7 | import { theme } from './styles'; 8 | import { GameDropZone } from "./home/GameDropZone"; 9 | import { db } from "./firebase-config"; 10 | import { collection, getDocs } from "@firebase/firestore"; 11 | 12 | export function HomePage() { 13 | const [recentGames, setRecentGames] = useState([]); 14 | 15 | const gamesCollectionRef = collection(db, "recentGames"); 16 | 17 | useEffect(()=> { 18 | const getRecentGames = async () => { 19 | const data = await getDocs(gamesCollectionRef); 20 | const mapped = data.docs.map((doc) => ({ ...doc.data(), id: doc.id })); 21 | setRecentGames(mapped); 22 | console.error("Recent Games:", mapped); 23 | } 24 | getRecentGames(); 25 | }, []); 26 | 27 | return
28 | 29 | 30 | 31 | {/* */} 32 | 33 | Reversing Emulator 34 | 35 | 36 | 37 | 38 | Add Games 39 | Welcome to the Online version of the Reversing Emulator, simply drop a ROM into the box below to start Reversing! 40 | 41 | {window["isWASM"]? "WASM Mode": "RetroArch Mode"} 42 | 43 | 44 |
; 45 | } 46 | -------------------------------------------------------------------------------- /websrc/ReadMe.md: -------------------------------------------------------------------------------- 1 | 2 | # Running 3 | ``` 4 | yarn install 5 | yarn dev 6 | ``` 7 | 8 | Now go to: http://localhost:8081 9 | 10 | --- 11 | # Useful Links 12 | * Material-UI (https://v4.mui.com/components/buttons/) 13 | * Icons (https://v4.mui.com/components/material-icons/) -------------------------------------------------------------------------------- /websrc/api/getEmulatorMetadata.tsx: -------------------------------------------------------------------------------- 1 | import { sendActionToServer } from '../server'; 2 | import { EmulatorMetaData } from "../main"; 3 | 4 | 5 | export function getEmulatorMetadata(setEmulatorMetadata, setLoading) { 6 | const payload = { 7 | category: 'emulator_metadata' 8 | }; 9 | sendActionToServer(payload).then((info) => { 10 | if (!info) { return; } 11 | console.error("result: Emulator MetaData:", info.result); 12 | const game_info: EmulatorMetaData = info.result; 13 | setEmulatorMetadata(game_info); 14 | // setAllInformation(info); 15 | // setFullState(info); 16 | // if (info.playerState) { 17 | // setPlayerState({ ...info.playerState, playerState }); 18 | // } 19 | setLoading(false); 20 | }); 21 | } 22 | -------------------------------------------------------------------------------- /websrc/debugger/PlaySettings.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Button from "@material-ui/core/Button"; 4 | import Grid from '@material-ui/core/Grid'; 5 | import PauseIcon from '@material-ui/icons/Pause'; 6 | import PlayArrowIcon from '@material-ui/icons/PlayArrow'; 7 | import RestoreIcon from '@material-ui/icons/Restore'; 8 | import StopIcon from '@material-ui/icons/Stop'; 9 | import SettingsIcon from '@material-ui/icons/Settings'; 10 | import SportsEsportsIcon from '@material-ui/icons/SportsEsports'; 11 | import { sendActionToServer } from '../server'; 12 | 13 | export function PlaySettings( { setCurrentDialog, playerState, setPlayerState }) { 14 | 15 | function play_or_pause() { 16 | if (playerState.paused) { 17 | setCurrentDialog('resume'); 18 | return; 19 | } 20 | 21 | const newPlayerState = {...playerState, paused:!playerState.paused}; 22 | setPlayerState(newPlayerState); 23 | 24 | // we are just about to pause so lets ask if they want to create a save state 25 | setCurrentDialog('pause_save'); 26 | const category = newPlayerState.paused? "pause":"play"; 27 | 28 | const payload = { 29 | category: "pause", 30 | state: newPlayerState 31 | }; 32 | sendActionToServer(payload); 33 | return; 34 | 35 | 36 | 37 | // const category = newPlayerState.paused? "pause":"play"; 38 | 39 | // const payload = { 40 | // category, 41 | // state: newPlayerState 42 | // }; 43 | // sendActionToServer(payload); 44 | } 45 | 46 | function restart() { 47 | const payload = { 48 | category: 'restart', 49 | state: playerState 50 | }; 51 | sendActionToServer(payload); 52 | } 53 | 54 | function stop() { 55 | const payload = { 56 | category: 'stop', 57 | state: playerState 58 | }; 59 | sendActionToServer(payload); 60 | } 61 | 62 | function changeLogButtons() { 63 | const newPlayerState = {...playerState, logButtons:!playerState.logButtons}; 64 | setPlayerState(newPlayerState); 65 | } 66 | 67 | return 68 | 69 | 70 | 73 | 74 | 75 | 76 | 79 | 80 | 81 | 82 | 85 | 86 | 87 | {/* 88 | 91 | */} 92 | 93 | 94 | 97 | 98 | 99 | 100 | } -------------------------------------------------------------------------------- /websrc/dialogs/EditFunctionDialog.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Button from '@material-ui/core/Button'; 3 | import TextField from '@material-ui/core/TextField'; 4 | import Dialog from '@material-ui/core/Dialog'; 5 | import DialogActions from '@material-ui/core/DialogActions'; 6 | import DialogContent from '@material-ui/core/DialogContent'; 7 | import DialogContentText from '@material-ui/core/DialogContentText'; 8 | import DialogTitle from '@material-ui/core/DialogTitle'; 9 | import { sendActionToServer } from '../server'; 10 | import { FormControl, FormLabel, FormGroup, FormControlLabel, Switch } from '@material-ui/core'; 11 | import ChipInput from 'material-ui-chip-input' 12 | 13 | 14 | export default function EditFunctionDialog( { currentDialogParameters, setCurrentDialog, playerState, setPlayerState, open = true }) { 15 | const [functionSettings, setFunctionSettings] = React.useState(currentDialogParameters); 16 | 17 | const handleClose = () => { 18 | setCurrentDialog(''); 19 | }; 20 | 21 | function save() { 22 | 23 | console.error("Going to save with settings:", functionSettings); 24 | // const newPlayerState = {...playerState, paused:false}; 25 | // setPlayerState(newPlayerState); 26 | 27 | const payload = { 28 | category: 'edit_function', 29 | state: functionSettings 30 | }; 31 | sendActionToServer(payload); 32 | handleClose(); 33 | } 34 | 35 | return ( 36 |
37 | 38 | Edit Function 39 | 40 | 41 | 42 | 43 |
44 | setFunctionSettings({...functionSettings, func_name:e.target.value})} value={functionSettings?.func_name} style={{display:'block'}} id="standard-basic" label="Name" fullWidth /> 45 | setFunctionSettings({...functionSettings, export_path:e.target.value})} value={functionSettings?.export_path || "/functions/"+functionSettings?.func_name+".s"} fullWidth style={{display:'block'}} id="standard-basic" label="Export Path" /> 46 | 47 | 48 | 49 | {JSON.stringify(functionSettings)} 50 | 51 |
52 | 53 | 56 | 59 | 60 |
61 |
62 | ); 63 | } -------------------------------------------------------------------------------- /websrc/dialogs/ExportFunctionDialog.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Button from '@material-ui/core/Button'; 3 | import TextField from '@material-ui/core/TextField'; 4 | import Dialog from '@material-ui/core/Dialog'; 5 | import DialogActions from '@material-ui/core/DialogActions'; 6 | import DialogContent from '@material-ui/core/DialogContent'; 7 | import DialogContentText from '@material-ui/core/DialogContentText'; 8 | import DialogTitle from '@material-ui/core/DialogTitle'; 9 | import { sendActionToServer } from '../server'; 10 | import { FormControl, FormLabel, FormGroup, FormControlLabel, Switch } from '@material-ui/core'; 11 | import ChipInput from 'material-ui-chip-input' 12 | import Checkbox from '@material-ui/core/Checkbox'; 13 | 14 | 15 | export default function ExportFunctionDialog( { currentDialogParameters, setCurrentDialog, playerState, setPlayerState, open = true }) { 16 | const [functionSettings, setFunctionSettings] = React.useState(currentDialogParameters); 17 | 18 | const handleClose = () => { 19 | setCurrentDialog(''); 20 | }; 21 | 22 | function save() { 23 | 24 | console.error("Going to save with settings:", functionSettings); 25 | // const newPlayerState = {...playerState, paused:false}; 26 | // setPlayerState(newPlayerState); 27 | 28 | const payload = { 29 | category: 'export_function', 30 | state: functionSettings 31 | }; 32 | sendActionToServer(payload); 33 | handleClose(); 34 | } 35 | 36 | return ( 37 |
38 | 39 | Export Function 40 | 41 | 42 | This will export the assembly source code for the current function to the source folder, which can then be commited to Git. 43 | 44 |
45 | } label="Export Assembly" /> 46 | } label="Export Javascript" /> 47 | } label="Export C" /> 48 | 49 | 50 |
51 | 52 | 55 | 58 | 59 |
60 |
61 | ); 62 | } -------------------------------------------------------------------------------- /websrc/dialogs/PauseSaveDialog.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import Button from '@material-ui/core/Button'; 3 | import TextField from '@material-ui/core/TextField'; 4 | import Dialog from '@material-ui/core/Dialog'; 5 | import DialogActions from '@material-ui/core/DialogActions'; 6 | import DialogContent from '@material-ui/core/DialogContent'; 7 | import DialogContentText from '@material-ui/core/DialogContentText'; 8 | import DialogTitle from '@material-ui/core/DialogTitle'; 9 | import { sendActionToServer, loadState } from '../server'; 10 | 11 | export default function PauseSaveDialog( { fullState, setCurrentDialog, open = true }) { 12 | 13 | const [saveStateName, setSaveStateName] = useState(''); 14 | 15 | const handleClose = () => { 16 | setCurrentDialog(''); 17 | }; 18 | 19 | function saveState() { 20 | if (saveStateName.length < 1) { 21 | 22 | } 23 | console.error("Going to save with name:", saveStateName); 24 | const payload = { 25 | category: 'save_state', 26 | state: { 27 | name: saveStateName 28 | } 29 | }; 30 | sendActionToServer(payload); 31 | handleClose(); 32 | } 33 | 34 | return ( 35 |
36 | 37 | Save State 38 | 39 | 40 | If you would like to save a state here enter a name to describe where you are in the game. 41 | 42 | setSaveStateName(e.target.value)} 51 | /> 52 | 53 | 54 | 64 | 67 | 68 | 69 |
70 | ); 71 | } -------------------------------------------------------------------------------- /websrc/dist/CNAME: -------------------------------------------------------------------------------- 1 | reversingemulator.com -------------------------------------------------------------------------------- /websrc/dist/assets/controller.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/controller.xcf -------------------------------------------------------------------------------- /websrc/dist/assets/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/left.png -------------------------------------------------------------------------------- /websrc/dist/assets/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/loading.png -------------------------------------------------------------------------------- /websrc/dist/assets/loading.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/loading.xcf -------------------------------------------------------------------------------- /websrc/dist/assets/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/menu.png -------------------------------------------------------------------------------- /websrc/dist/assets/menu.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/menu.xcf -------------------------------------------------------------------------------- /websrc/dist/assets/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/right.png -------------------------------------------------------------------------------- /websrc/dist/assets/showcase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/showcase.png -------------------------------------------------------------------------------- /websrc/dist/assets/showcase.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/assets/showcase.xcf -------------------------------------------------------------------------------- /websrc/dist/genesisrr.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/genesisrr.wasm -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/Readme.txt: -------------------------------------------------------------------------------- 1 | Hey there! 2 | 3 | Hope you make good use of this pack. You can use all these assets in any project you want to (be it commercial or not).All of the assets are in the public domain under Creative Commons 0 (CC0) 4 | 5 | In this pack you will find over 500 buttons including: 6 | 7 | Xbox 360 Controller 8 | Xbox One Controller + Diagram 9 | Xbox Series X Controller + Diagram 10 | Play Station 3 Controller 11 | Play Station 4 Controller + Diagram 12 | Play Station 5 Controller + Diagram 13 | Play Station Move 14 | PS Vita 15 | Google Stadia Controller 16 | Vive Controller 17 | Oculus Controllers & Remote 18 | Wii Controller 19 | Wii U Controller 20 | Nintentdo Switch 21 | Steam Controller (Updated to commercial version) 22 | Ouya 23 | Keyboard and mouse buttons (Both in dark and light variants including blanks) 24 | Directional arrows for thumb sticks and movement keys 25 | Touch Screen Gestures 26 | 27 | ---------------------------------- 28 | 29 | I am "Nicolae (Xelu) Berbece", I'm responsible for the development studio "Those Awesome Guys", developers of "Move or Die" and publishers of "Monster Prom". 30 | 31 | You can contact me at nick@thoseawesomeguys.com or @xelubest 32 | 33 | Feel free to credit me in case you use anything in this pack, but don't worry, I won't mind if you don't. ;) 34 | 35 | Please share this pack with other fellow developers in need of such assets! In the spirit of good old chain mail, if you share this pack with 5 fellow devs, your game's steam review score will rise by 7% and a notable twitch streamer will pick it up for their stream. 36 | 37 | Keep making awesome things!!! 38 | 39 | ~Nick 40 | 41 | 42 | 43 | Here is a semi-regularly-updated list of games using these prompts: 44 | ---------------------------- 45 | Mega Man Legacy 46 | Hunt: Showdown 47 | Outter Wilds 48 | Slay The Spire 49 | A hat in Time 50 | Fall Guys 51 | Forager 52 | Wonder Boy the dragon's trap 53 | Postal 2 54 | Postal Redux 55 | RWBY 56 | Shadow Warrior 2 57 | Tiny Metal 58 | Aztez 59 | Disney Afternoon 60 | Heat Signature 61 | Turbo Dismount 62 | Black Future 88 63 | Fallen Legion 64 | PikuNiku 65 | Fru 66 | Blockships 67 | 20XX 68 | Mike Dies 69 | Snake Pass 70 | Danger Scavenger 71 | Roboquest 72 | Rive 73 | Obduction 74 | Fractal Fall 75 | Guild of Ascension 76 | Avaria VS 77 | Blast Zone! Tournament 78 | 100ft Robot Golf 79 | Sockventure 80 | Spellbreak 81 | Zombie Rollerz 82 | B.O.O.M . - You Win 83 | Battle Chef Brigade 84 | De Blob 85 | Phantom Brigade 86 | Wytchwood 87 | Mulaka 88 | Airheart - Tales of broken wings 89 | Redirection 90 | Pull Stay 91 | Death Pedal 92 | Defender's Quest 93 | Akuto "Mad World" 94 | Project Mobius 95 | Whispering Willows 96 | Vostok Inc. 97 | Divine commander 98 | Sbirz 99 | Grashers 100 | Remnants of Naezith 101 | Mothergunship 102 | Roundabout 103 | Hunter of the Disowned 104 | Cosmos Quickstop 105 | West of Dead 106 | Tune Tank 107 | Rain on your Parade 108 | Infinite Adventures 109 | Arena 3D 110 | Chroma Vaders 111 | Hoverloop 112 | Wrestling Revolution 3D 113 | Altero 114 | Super Comboman 115 | Disc Jam 116 | Cooking Simulator 117 | Jelly is Sticky 118 | The Hatching 119 | World to the West 120 | Mayan Death Robots 121 | Sentris 122 | Carto 123 | Unbox 124 | Fort Triumph 125 | Insane Robots 126 | Super Daryl Deluxe 127 | Induction 128 | Pawarumi 129 | The Flock 130 | Binary Trigger 131 | Fractal Space 132 | Deputy dangle 133 | Bubsy: The Woolies Strike Back 134 | Tumblestone 135 | The chronicles of Kyra 136 | Ghost Knight Victis 137 | Solbrain Knight of Darkness 138 | SSMP 139 | Distance 140 | Idarb 141 | Earthlock 142 | Everspace 143 | Pylon Rogue 144 | The Church in the darkness 145 | Sword n' Board -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/Vita_Select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/Vita_Select.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/Vita_Start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/Vita_Start.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_A.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_B.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Dpad_Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Dpad_Down.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Dpad_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Dpad_Left.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Dpad_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Dpad_Right.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Dpad_Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Dpad_Up.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_LB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_LB.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_LT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_LT.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Left_Stick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Left_Stick.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Left_Stick_Click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Left_Stick_Click.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_RB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_RB.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_RT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_RT.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Right_Stick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Right_Stick.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Right_Stick_Click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Right_Stick_Click.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_X.png -------------------------------------------------------------------------------- /websrc/dist/images/controller-icons/XboxOne_Y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/dist/images/controller-icons/XboxOne_Y.png -------------------------------------------------------------------------------- /websrc/dist/index.html: -------------------------------------------------------------------------------- 1 | Retro Reversing Emulator
Loading
-------------------------------------------------------------------------------- /websrc/firebase-config.ts: -------------------------------------------------------------------------------- 1 | // Import the functions you need from the SDKs you need 2 | import { initializeApp } from "firebase/app"; 3 | import { getAnalytics } from "firebase/analytics"; 4 | // TODO: Add SDKs for Firebase products that you want to use 5 | // https://firebase.google.com/docs/web/setup#available-libraries 6 | import { getFirestore} from "@firebase/firestore"; 7 | 8 | // Your web app's Firebase configuration 9 | // For Firebase JS SDK v7.20.0 and later, measurementId is optional 10 | const firebaseConfig = { 11 | apiKey: "AIzaSyAolPRDKHKqwcBrbb6N-9u7uFxN38FQ2KE", 12 | authDomain: "reversingemulator.firebaseapp.com", 13 | projectId: "reversingemulator", 14 | storageBucket: "reversingemulator.appspot.com", 15 | messagingSenderId: "596902357954", 16 | appId: "1:596902357954:web:1a2a2941ce7e3ee008845b", 17 | measurementId: "G-D93PXBB0NH" 18 | }; 19 | 20 | // Initialize Firebase 21 | const app = initializeApp(firebaseConfig); 22 | const analytics = getAnalytics(app); 23 | 24 | export const db = getFirestore(app); -------------------------------------------------------------------------------- /websrc/home/database.ts: -------------------------------------------------------------------------------- 1 | import { MTY_Alloc, mty_b64_to_buf, mty_buf_to_b64, mty_mem, MTY_SetUint32, MTY_StrToJS, MTY_Free } from "./matoya"; 2 | import { openDB, deleteDB, wrap, unwrap } from 'idb'; 3 | 4 | let database; 5 | let files = {}; 6 | 7 | const request = window.indexedDB.open('Junie', 1); 8 | 9 | //Check if a schema update is required 10 | request.onupgradeneeded = event => 11 | { 12 | const database = (event.target as any).result; 13 | 14 | if (event.oldVersion < 1) { 15 | database.createObjectStore('files', { keyPath: 'path', unique: true }); 16 | database.createObjectStore('games', { keyPath: 'path', unique: true }); 17 | } 18 | }; 19 | 20 | //Retrieve all files in memory 21 | request.onsuccess = event => 22 | { 23 | database = (event.target as any).result; 24 | 25 | const transaction = database.transaction('files', 'readwrite'); 26 | const store = transaction.objectStore('files'); 27 | 28 | store.getAll().onsuccess = event => { 29 | for (const file of event.target.result) { 30 | files[file.path] = mty_b64_to_buf(file.data); 31 | } 32 | } 33 | 34 | //Begin: compatibility with older versions 35 | for (let i = 0; i < localStorage.length; ++i) { 36 | const path = localStorage.key(i); 37 | const data = localStorage.getItem(path); 38 | 39 | const entry = { path: `/${path}`, data: data }; 40 | 41 | store.put(entry); 42 | 43 | files[entry.path] = mty_b64_to_buf(entry.data); 44 | } 45 | 46 | localStorage.clear(); 47 | //End: compatibility with older versions 48 | }; 49 | 50 | //Read a file from memory storage 51 | let fileBuffer = null; 52 | export function JUN_ReadFile(path, length) { 53 | // console.error("JUN_ReadFile path name:", MTY_StrToJS(path), length, files); 54 | const file = files[MTY_StrToJS(path)]; 55 | if (!file) 56 | return null; 57 | 58 | if (fileBuffer) { 59 | window["oldFileBuffer"] = fileBuffer; 60 | console.log("Removing Old file Buffer from memory later"); 61 | // MTY_Free(window"oldFileBuffer"]); 62 | } 63 | fileBuffer = MTY_Alloc(file.length, 1); 64 | const view = new Uint8Array(mty_mem(), fileBuffer, file.length); 65 | view.set(file); 66 | 67 | MTY_SetUint32(length, file.length); 68 | 69 | return fileBuffer; 70 | } 71 | 72 | //Write a file to the database 73 | export function JUN_WriteFile(cpath, cdata, length) { 74 | const transaction = database.transaction('files', 'readwrite'); 75 | const store = transaction.objectStore('files'); 76 | 77 | const buffer = new Uint8Array(length); 78 | const data = new Uint8Array(mty_mem(), cdata, length); 79 | buffer.set(data); 80 | 81 | const path = MTY_StrToJS(cpath) 82 | 83 | files[path] = data; 84 | 85 | store.put({ path: path, data: mty_buf_to_b64(data) }); 86 | } 87 | 88 | export async function JUN_WriteFileFromJS(file, system) { 89 | const fileContent = await file.arrayBuffer(); 90 | const transaction = database.transaction('games', 'readwrite'); 91 | const store = transaction.objectStore('games'); 92 | store.put({ path: system+"/"+file.path, data: fileContent }); 93 | // files[file.path] = fileContent; 94 | } 95 | 96 | export async function RE_ReadRomFromJS(file_path) { 97 | let db = await openDB('Junie', 1); 98 | 99 | let tx = db.transaction('games', 'readonly') 100 | let store = tx.objectStore('games') 101 | return await store.get(file_path); 102 | } 103 | 104 | export async function RE_ReadFileFromJS(file_path) { 105 | let db = await openDB('Junie', 1); 106 | 107 | let tx = db.transaction('files', 'readonly') 108 | let store = tx.objectStore('files') 109 | return await store.get(file_path); 110 | } 111 | 112 | export async function RE_getAllLocalGames() { 113 | let db = await openDB('Junie', 1); 114 | 115 | let tx = db.transaction('games', 'readonly') 116 | let store = tx.objectStore('games') 117 | return await store.getAll(); 118 | } -------------------------------------------------------------------------------- /websrc/home/emulators.ts: -------------------------------------------------------------------------------- 1 | //Define cores mapping 2 | export const cores = { 3 | "quicknes": { name: "QuickNES", library: "quicknes" }, 4 | "snes9x": { name: "Snes9x", library: "snes9x" }, 5 | "genesis": { name: "Genesis Plus GX", library: "genesisrr" }, 6 | "mgba": { name: "mGBA", library: "mgba" }, 7 | "melonds": { name: "melonDS", library: "melonds" }, 8 | }; 9 | 10 | //Define systems mapping 11 | export const systems = { 12 | "NES": cores["quicknes"], 13 | "SNES": cores["snes9x"], 14 | "Master System": cores["genesis"], 15 | "Mega Drive": cores["genesis"], 16 | "Game Gear": cores["genesis"], 17 | "Game Boy": cores["mgba"], 18 | "Game Boy Color": cores["mgba"], 19 | "Game Boy Advance": cores["mgba"], 20 | "Nintendo DS": cores["melonds"], 21 | }; 22 | 23 | //Define extensions mapping 24 | export const extensions = { 25 | 'nes': 'NES', 26 | 'smc': 'SNES', 27 | 'sms': 'Master System', 28 | 'gg': 'Game Gear', 29 | 'bin': 'Mega Drive', 30 | 'gb': 'Game Boy', 31 | 'gbc': 'Game Boy Color', 32 | 'gba': 'Game Boy Advance', 33 | 'nds': 'Nintendo DS', 34 | } -------------------------------------------------------------------------------- /websrc/images/controller-icons/Readme.txt: -------------------------------------------------------------------------------- 1 | Hey there! 2 | 3 | Hope you make good use of this pack. You can use all these assets in any project you want to (be it commercial or not).All of the assets are in the public domain under Creative Commons 0 (CC0) 4 | 5 | In this pack you will find over 500 buttons including: 6 | 7 | Xbox 360 Controller 8 | Xbox One Controller + Diagram 9 | Xbox Series X Controller + Diagram 10 | Play Station 3 Controller 11 | Play Station 4 Controller + Diagram 12 | Play Station 5 Controller + Diagram 13 | Play Station Move 14 | PS Vita 15 | Google Stadia Controller 16 | Vive Controller 17 | Oculus Controllers & Remote 18 | Wii Controller 19 | Wii U Controller 20 | Nintentdo Switch 21 | Steam Controller (Updated to commercial version) 22 | Ouya 23 | Keyboard and mouse buttons (Both in dark and light variants including blanks) 24 | Directional arrows for thumb sticks and movement keys 25 | Touch Screen Gestures 26 | 27 | ---------------------------------- 28 | 29 | I am "Nicolae (Xelu) Berbece", I'm responsible for the development studio "Those Awesome Guys", developers of "Move or Die" and publishers of "Monster Prom". 30 | 31 | You can contact me at nick@thoseawesomeguys.com or @xelubest 32 | 33 | Feel free to credit me in case you use anything in this pack, but don't worry, I won't mind if you don't. ;) 34 | 35 | Please share this pack with other fellow developers in need of such assets! In the spirit of good old chain mail, if you share this pack with 5 fellow devs, your game's steam review score will rise by 7% and a notable twitch streamer will pick it up for their stream. 36 | 37 | Keep making awesome things!!! 38 | 39 | ~Nick 40 | 41 | 42 | 43 | Here is a semi-regularly-updated list of games using these prompts: 44 | ---------------------------- 45 | Mega Man Legacy 46 | Hunt: Showdown 47 | Outter Wilds 48 | Slay The Spire 49 | A hat in Time 50 | Fall Guys 51 | Forager 52 | Wonder Boy the dragon's trap 53 | Postal 2 54 | Postal Redux 55 | RWBY 56 | Shadow Warrior 2 57 | Tiny Metal 58 | Aztez 59 | Disney Afternoon 60 | Heat Signature 61 | Turbo Dismount 62 | Black Future 88 63 | Fallen Legion 64 | PikuNiku 65 | Fru 66 | Blockships 67 | 20XX 68 | Mike Dies 69 | Snake Pass 70 | Danger Scavenger 71 | Roboquest 72 | Rive 73 | Obduction 74 | Fractal Fall 75 | Guild of Ascension 76 | Avaria VS 77 | Blast Zone! Tournament 78 | 100ft Robot Golf 79 | Sockventure 80 | Spellbreak 81 | Zombie Rollerz 82 | B.O.O.M . - You Win 83 | Battle Chef Brigade 84 | De Blob 85 | Phantom Brigade 86 | Wytchwood 87 | Mulaka 88 | Airheart - Tales of broken wings 89 | Redirection 90 | Pull Stay 91 | Death Pedal 92 | Defender's Quest 93 | Akuto "Mad World" 94 | Project Mobius 95 | Whispering Willows 96 | Vostok Inc. 97 | Divine commander 98 | Sbirz 99 | Grashers 100 | Remnants of Naezith 101 | Mothergunship 102 | Roundabout 103 | Hunter of the Disowned 104 | Cosmos Quickstop 105 | West of Dead 106 | Tune Tank 107 | Rain on your Parade 108 | Infinite Adventures 109 | Arena 3D 110 | Chroma Vaders 111 | Hoverloop 112 | Wrestling Revolution 3D 113 | Altero 114 | Super Comboman 115 | Disc Jam 116 | Cooking Simulator 117 | Jelly is Sticky 118 | The Hatching 119 | World to the West 120 | Mayan Death Robots 121 | Sentris 122 | Carto 123 | Unbox 124 | Fort Triumph 125 | Insane Robots 126 | Super Daryl Deluxe 127 | Induction 128 | Pawarumi 129 | The Flock 130 | Binary Trigger 131 | Fractal Space 132 | Deputy dangle 133 | Bubsy: The Woolies Strike Back 134 | Tumblestone 135 | The chronicles of Kyra 136 | Ghost Knight Victis 137 | Solbrain Knight of Darkness 138 | SSMP 139 | Distance 140 | Idarb 141 | Earthlock 142 | Everspace 143 | Pylon Rogue 144 | The Church in the darkness 145 | Sword n' Board -------------------------------------------------------------------------------- /websrc/images/controller-icons/Vita_Select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/Vita_Select.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/Vita_Start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/Vita_Start.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_A.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_A.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_B.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_B.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Dpad_Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Dpad_Down.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Dpad_Left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Dpad_Left.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Dpad_Right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Dpad_Right.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Dpad_Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Dpad_Up.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_LB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_LB.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_LT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_LT.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Left_Stick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Left_Stick.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Left_Stick_Click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Left_Stick_Click.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_RB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_RB.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_RT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_RT.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Right_Stick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Right_Stick.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Right_Stick_Click.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Right_Stick_Click.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_X.png -------------------------------------------------------------------------------- /websrc/images/controller-icons/XboxOne_Y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RetroReversing/libRetroReversing/4b7fe0df6a5a1b7ca8952175365e16477e2e9289/websrc/images/controller-icons/XboxOne_Y.png -------------------------------------------------------------------------------- /websrc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Retro Reversing Emulator 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Loading
16 | 18 | -------------------------------------------------------------------------------- /websrc/main/Drawer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | import clsx from 'clsx'; 4 | import CssBaseline from '@material-ui/core/CssBaseline'; 5 | 6 | import Button from "@material-ui/core/Button"; 7 | import AppBar from '@material-ui/core/AppBar'; 8 | import Toolbar from '@material-ui/core/Toolbar'; 9 | import Typography from '@material-ui/core/Typography'; 10 | import Divider from '@material-ui/core/Divider'; 11 | import Drawer from '@material-ui/core/Drawer'; 12 | import List from '@material-ui/core/List'; 13 | import ListItem from '@material-ui/core/ListItem'; 14 | import ListItemIcon from '@material-ui/core/ListItemIcon'; 15 | import ListItemText from '@material-ui/core/ListItemText'; 16 | import Hidden from '@material-ui/core/Hidden'; 17 | import IconButton from '@material-ui/core/IconButton'; 18 | // Icons 19 | import MailIcon from '@material-ui/icons/Mail'; 20 | import MenuIcon from '@material-ui/icons/Menu'; 21 | import InboxIcon from '@material-ui/icons/MoveToInbox'; 22 | import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; 23 | import ChevronRightIcon from '@material-ui/icons/ChevronRight'; 24 | import MemoryIcon from '@material-ui/icons/Memory'; 25 | import FunctionsIcon from '@material-ui/icons/Functions'; 26 | import SportsEsportsIcon from '@material-ui/icons/SportsEsports'; 27 | import StorageIcon from '@material-ui/icons/Storage'; 28 | import InfoIcon from '@material-ui/icons/Info'; 29 | import PermMediaIcon from '@material-ui/icons/PermMedia'; 30 | import AlbumIcon from '@material-ui/icons/Album'; 31 | 32 | import { useStyles } from '../styles'; 33 | 34 | const mainPages = [ 35 | { displayName: 'Main State', name: 'main', icon: }, 36 | { displayName: 'Input History', name: 'input', icon: }, 37 | { displayName: 'Functions', name: 'functions', icon: }, 38 | { displayName: 'Resources', name: 'resources', icon: }, 39 | { displayName: 'Data Structures', name: 'data_structures', icon: }, 40 | { displayName: 'Game Information', name: 'game_info', icon: }, 41 | ]; 42 | 43 | export function RRDrawer( props ) { 44 | const memory_descriptors = props.memory_descriptors || []; 45 | const cd_tracks = props?.allInfo?.cd_tracks || []; 46 | const classes = useStyles(); 47 | 48 | return 57 |
58 | 59 | {props.theme.direction === 'ltr' ? : } 60 | 61 |
62 | 63 | 64 | {mainPages.map((page, index) => ( 65 | props.setCurrentTab(page.name)}> 66 | {page.icon || } 67 | 68 | 69 | ))} 70 | 71 | {cd_tracks.length>0 && } 72 | 73 | {cd_tracks.map((cd_track, index) => ( 74 | props.setCurrentTab("memory_"+cd_track.name)}> 75 | 76 | 77 | 78 | ))} 79 | 80 | 81 | 82 | {memory_descriptors.map((memory_descriptor, index) => ( 83 | props.setCurrentTab("memory_"+memory_descriptor.name)}> 84 | 85 | 86 | 87 | ))} 88 | 89 |
90 | } -------------------------------------------------------------------------------- /websrc/main/PlaythroughSelector.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Select from '@material-ui/core/Select'; 3 | import MenuItem from '@material-ui/core/MenuItem'; 4 | import FormControl from '@material-ui/core/FormControl'; 5 | import InputLabel from '@material-ui/core/InputLabel'; 6 | import TripeDotDropDownMenu from "../pages/util/TripeDotDropDownMenu"; 7 | 8 | export function PlaythroughSelector(props) { 9 | return (
14 | Playthrough
); 24 | } 25 | -------------------------------------------------------------------------------- /websrc/main/RRTitleBar.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import clsx from 'clsx'; 3 | import AppBar from '@material-ui/core/AppBar'; 4 | import Toolbar from '@material-ui/core/Toolbar'; 5 | import Typography from '@material-ui/core/Typography'; 6 | import IconButton from '@material-ui/core/IconButton'; 7 | import MenuIcon from '@material-ui/icons/Menu'; 8 | import { PlaySettings } from "../debugger/PlaySettings"; 9 | import { RRDrawer } from './Drawer'; 10 | 11 | export function RRTitleBar(classes, open, gameInformation, setCurrentDialog, playerState, setPlayerState, setCurrentTab, theme, setOpen) { 12 | 13 | const handleDrawerOpen = () => { 14 | setOpen(true); 15 | }; 16 | 17 | const handleDrawerClose = () => { 18 | setOpen(false); 19 | }; 20 | 21 | return <> 25 | 26 | 33 | 34 | 35 | 36 | {gameInformation?.library_name}RE 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ; 45 | } 46 | -------------------------------------------------------------------------------- /websrc/main/SaveStateList.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import List from '@material-ui/core/List'; 3 | import ListItem from '@material-ui/core/ListItem'; 4 | import Divider from '@material-ui/core/Divider'; 5 | import ListItemText from '@material-ui/core/ListItemText'; 6 | import ListItemAvatar from '@material-ui/core/ListItemAvatar'; 7 | import Avatar from '@material-ui/core/Avatar'; 8 | import Typography from '@material-ui/core/Typography'; 9 | import IconButton from '@material-ui/core/IconButton'; 10 | import CommentIcon from '@material-ui/icons/Comment'; 11 | import ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction'; 12 | import MoreHorizIcon from '@material-ui/icons/MoreHoriz'; 13 | import { reverse, noop, sortBy } from "lodash"; 14 | 15 | import GridList from '@material-ui/core/GridList'; 16 | import GridListTile from '@material-ui/core/GridListTile'; 17 | import GridListTileBar from '@material-ui/core/GridListTileBar'; 18 | import ListSubheader from '@material-ui/core/ListSubheader'; 19 | import InfoIcon from '@material-ui/icons/Info'; 20 | import ReplayIcon from '@material-ui/icons/Replay'; 21 | import DeleteIcon from '@material-ui/icons/Delete'; 22 | import { Grid } from '@material-ui/core'; 23 | 24 | 25 | export function createSaveStateTile(tile, load_state, prefix="", delete_state=noop, playthrough_name="Initial") { 26 | 27 | return ( 28 | {tile.name} 29 | frame: {tile.frame}} 32 | actionIcon={ 33 | 34 | 35 | load_state(tile.frame)} /> 36 | 37 | 38 | delete_state(tile.frame)} /> 39 | 40 | 41 | } 42 | /> 43 | ); 44 | } 45 | export default function SaveStateList({save_states, last_frame, load_state, delete_state }) { 46 | 47 | if (!save_states) { 48 | return null; 49 | } 50 | 51 | const sorted_save_states = sortBy(save_states, (state)=>state.frame); 52 | const save_states_reversed = reverse(sorted_save_states); 53 | 54 | return ( 55 |
56 | 57 | 58 | 59 | 60 | {save_states_reversed.map((el)=>createSaveStateTile(el,load_state, "", delete_state))} 61 | 62 |
63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /websrc/main/Template.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | export function Template() { 5 | return
Test
6 | } -------------------------------------------------------------------------------- /websrc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReversingEmulatorFrontEnd", 3 | "version": "1.0.0", 4 | "description": "Reversing emulator frontend", 5 | "keywords": [], 6 | "homepage": "https://www.retroreversing.com/", 7 | "main": "index.js", 8 | "scripts": { 9 | "dev": "webpack-dev-server", 10 | "production": "webpack --mode production" 11 | }, 12 | "dependencies": { 13 | "@material-ui/core": "^4.9.14", 14 | "@material-ui/icons": "^4.9.1", 15 | "assert": "^2.0.0", 16 | "axios": "^0.21.2", 17 | "buffer": "^6.0.3", 18 | "create-react-class": "^15.6.3", 19 | "firebase": "^9.8.3", 20 | "idb": "^7.0.0", 21 | "lodash": "^4.17.21", 22 | "material-ui-chip-input": "^1.1.0", 23 | "monaco-editor": "^0.20.0", 24 | "process": "^0.11.10", 25 | "react": "^16.13.0", 26 | "react-dom": "^16.13.0", 27 | "react-dropzone": "^11.5.1", 28 | "react-monaco-editor": "^0.36.0", 29 | "react-router": "^5.2.0", 30 | "react-router-dom": "^5.2.0", 31 | "react-use": "^14.2.0", 32 | "react-virtualized": "^9.21.2", 33 | "react-window": "^1.8.5", 34 | "rich-markdown-editor": "^10.0.2-1", 35 | "sha1-uint8array": "^0.10.3", 36 | "typescript": "^4.7.4", 37 | "vm-browserify": "^1.1.2" 38 | }, 39 | "devDependencies": { 40 | "@babel/core": "^7.8.4", 41 | "@babel/preset-env": "^7.8.4", 42 | "@babel/preset-react": "^7.8.3", 43 | "autoprefixer": "^10.4.0", 44 | "babel-loader": "^8.2.3", 45 | "css-loader": "^3.5.3", 46 | "file-loader": "^5.0.2", 47 | "html-webpack-plugin": "^5.5.0", 48 | "monaco-editor-webpack-plugin": "^1.9.0", 49 | "postcss": "^8.3.11", 50 | "source-map-loader": "^3.0.0", 51 | "style-loader": "^1.2.1", 52 | "tailwindcss": "^2.2.19", 53 | "ts-loader": "^9.3.1", 54 | "webpack": "^5.62.1", 55 | "webpack-cli": "^4.9.1", 56 | "webpack-dev-server": "^4.4.0" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /websrc/pages/CodeOverride/CodeOverride.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { TextField, Paper, Grid, Button, Container, FormControlLabel, Switch } from '@material-ui/core'; 4 | import SaveIcon from '@material-ui/icons/Save'; 5 | import { sendActionToServer } from '../../server'; 6 | 7 | export function CodeOverride({ memory }) { 8 | const [enabled, setEnabled] = useState(window.allInformation?.overrides?.CD?.[memory.filename]?.enabled || false); 9 | const [code, setCode] = useState( 10 | window.allInformation?.overrides?.CD?.[memory.filename]?.code || "// You have access to variables: lba, buffer, memset(start, length, value)" 11 | ); 12 | const overrideType = "CD"; 13 | 14 | function saveOverride() { 15 | const start = memory.lba_start || memory.start; 16 | const end = memory.lba_end || memory.end; 17 | const payload = { 18 | category: 'modify_override', 19 | state: { 20 | overrideType, 21 | name: memory.filename || memory.name, 22 | code, 23 | start, end, enabled 24 | }, 25 | }; 26 | sendActionToServer(payload).then((result)=> { 27 | console.error("result:", result); 28 | window.allInformation = result; 29 | }); 30 | } 31 | 32 | useEffect(()=> { 33 | saveOverride(); 34 | }, [enabled]); 35 | 36 | return ( 37 | 38 | { 47 | setCode(e.target.value); 48 | }} 49 | /> 50 | 51 | setEnabled(e.target.checked)} name="enabled" />} 53 | label="Enabled" 54 | /> 55 | 58 | 59 | 60 | ); 61 | // return
Code Override
62 | } 63 | -------------------------------------------------------------------------------- /websrc/pages/DataStructures.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | export function DataStructures() { 5 | return
Data Structures
6 | } -------------------------------------------------------------------------------- /websrc/pages/DataVisualiser/VisualiseViewer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import Paper from '@material-ui/core/Paper'; 4 | import Select from '@material-ui/core/Select'; 5 | import MenuItem from '@material-ui/core/MenuItem'; 6 | import Grid from '@material-ui/core/Grid'; 7 | import FormGroup from '@material-ui/core/FormGroup'; 8 | import FormControlLabel from '@material-ui/core/FormControlLabel'; 9 | import Switch from '@material-ui/core/Switch'; 10 | import { xterm } from './8bppXterm'; 11 | import { padStart, debounce } from "lodash"; 12 | import css from "./visual.css"; 13 | import { visualiseData as originalVisualiseData } from './visual'; 14 | import { TextField } from '@material-ui/core'; 15 | import { FixedSizeList as List } from 'react-window'; 16 | 17 | // const visualiseData = debounce(originalVisualiseData, 2000); 18 | 19 | export function VisualViewer(props) { 20 | const [visualType, setVisualType] = useState('8bpp'); 21 | const [is2D, set2D] = useState(true); 22 | const [pixelsPerLine, setPixelsPerLine] = useState(16); 23 | // const debouncedSetPixelsPerLine = debounce(setPixelsPerLine, 2000); 24 | 25 | let lines = originalVisualiseData(props.buffer, visualType, is2D, "tiles", pixelsPerLine>8?pixelsPerLine:8); 26 | 27 | // useEffect( 28 | // ()=> { 29 | // console.error("Pixels per line changed"); 30 | // lines = visualiseData(props.buffer, visualType, is2D, "tiles", pixelsPerLine); 31 | // }, 32 | // [pixelsPerLine] 33 | // ) 34 | 35 | const displaySelector = ( 36 | 37 | 38 | 57 | setPixelsPerLine(e.target.value)} /> 58 | {/* TODO: Add pixel size zooms */} 59 | set2D(e.target.checked)} name="2D" />} 61 | label="2D" 62 | /> 63 | 64 | 65 | ); 66 | 67 | const createRow = ({ index, style }) => { 68 | const row = lines?.[index]; 69 | return row; 70 | }; 71 | 72 | return ( 73 |
74 | {displaySelector} 75 | 76 | {lines} 77 | {/* 83 | {createRow} 84 | */} 85 | 86 |
87 | ); 88 | } 89 | -------------------------------------------------------------------------------- /websrc/pages/DataVisualiser/visual.css: -------------------------------------------------------------------------------- 1 | .line { 2 | display:flex; 3 | } 4 | 5 | .tile2d { 6 | display: flex; 7 | } -------------------------------------------------------------------------------- /websrc/pages/DisasmViewer/DisasmViewer.css: -------------------------------------------------------------------------------- 1 | .disasmRow { 2 | display: flex; 3 | } 4 | 5 | .disasmHeaderRow { 6 | display: flex; 7 | font-weight: 700; 8 | margin-bottom: 5px; 9 | } 10 | 11 | .disasmColOffset { 12 | font-weight: 700; 13 | } 14 | 15 | .disasmRow div { 16 | padding-left: 5px; 17 | min-width: 200px; 18 | } 19 | 20 | .disasmColBytes { 21 | color: #95AFBA; 22 | } -------------------------------------------------------------------------------- /websrc/pages/FunctionViewer/FunctionViewer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | import PropTypes from 'prop-types'; 4 | import { map, filter, noop } from 'lodash'; 5 | import { MemoryViewer } from '../MemoryViewer'; 6 | import { IconButton } from '@material-ui/core'; 7 | import EditIcon from '@material-ui/icons/Edit'; 8 | import LibraryBooksIcon from '@material-ui/icons/LibraryBooks'; 9 | 10 | function createMemoryViewer(row) { 11 | const offset = parseInt(row.func_offset, 16); 12 | return (); 13 | } 14 | 15 | export function FunctionViewer({ func, setCurrentDialog, setCurrentDialogParameters }) { 16 | // return createMemoryViewer(row[1]) 17 | const playthrough_info = window.allInformation?.function_usage[func?.func_offset] || {}; 18 | return 19 |

{func?.func_name} 20 | { 21 | setCurrentDialogParameters(func); 22 | setCurrentDialog('edit_function'); 23 | } }> 24 | 25 | 26 | { 27 | setCurrentDialogParameters(func); 28 | setCurrentDialog('export_function'); 29 | } }> 30 | 31 | 32 |

33 |

export: {func?.export_path || "/functions/" + func?.func_name + ".s"}

34 | {createMemoryViewer(func)} 35 |
36 | {JSON.stringify(playthrough_info.signatures)} 37 |
38 |
39 | } 40 | -------------------------------------------------------------------------------- /websrc/pages/GameInformation.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | export function GameInformation() { 5 | return
Game Information
6 | } -------------------------------------------------------------------------------- /websrc/pages/HexViewer/AsciiViewer.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var createReactClass = require('create-react-class'); 3 | 4 | 5 | var AsciiCharacter = createReactClass({ 6 | activate: function () { 7 | this.props.activateItem(this.props.itemIndex); 8 | this.props.activateSet(this.props.setIndex); 9 | }, 10 | render: function() { 11 | return (
  • {this.props.character}
  • ); 12 | 13 | } 14 | }); 15 | 16 | function createAsciiCharacterElement (setIndex, byteValue, itemIndex, theSet) { 17 | var characterToDisplay = "·"; 18 | if (byteValue > 31 && byteValue < 127) { 19 | characterToDisplay = String.fromCharCode(byteValue); 20 | } 21 | 22 | if (byteValue == -1) { 23 | characterToDisplay = ""; 24 | } 25 | 26 | var activeCell = this.props.activeSet * (theSet.length) + this.props.activeItem; 27 | var currentCell = setIndex*(theSet.length) + itemIndex; 28 | var classes = ( activeCell == currentCell ) ? 'active' : ''; 29 | 30 | var props = { 31 | setIndex: setIndex, 32 | itemIndex: itemIndex, 33 | currentCell: currentCell, 34 | classes: classes, 35 | character: characterToDisplay, 36 | activateSet: this.props.activateSet, 37 | clearSet: this.props.clearSet, 38 | activateItem: this.props.activateItem 39 | }; 40 | 41 | return (); 42 | } 43 | 44 | export const AsciiSet = createReactClass({ 45 | activate: function () { 46 | this.props.activateSet(this.props.index); 47 | }, 48 | render: function() { 49 | var items = this.props.set.map(createAsciiCharacterElement.bind(this, this.props.setIndex)); 50 | 51 | return ( 52 |
      53 | {items} 54 |
    55 | ); 56 | } 57 | }); -------------------------------------------------------------------------------- /websrc/pages/HexViewer/PixelTable.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var createReactClass = require('create-react-class'); 3 | 4 | 5 | var AsciiCharacter = createReactClass({ 6 | activate: function () { 7 | this.props.activateItem(this.props.itemIndex); 8 | this.props.activateSet(this.props.setIndex); 9 | }, 10 | render: function() { 11 | return (
  • {this.props.character}
  • ); 12 | 13 | } 14 | }); 15 | 16 | function createAsciiCharacterElement (setIndex, byteValue, itemIndex, theSet) { 17 | var characterToDisplay = "·"; 18 | if (byteValue > 31 && byteValue < 127) { 19 | characterToDisplay = String.fromCharCode(byteValue); 20 | } 21 | 22 | if (byteValue == -1) { 23 | characterToDisplay = ""; 24 | } 25 | 26 | var activeCell = this.props.activeSet * (theSet.length) + this.props.activeItem; 27 | var currentCell = setIndex*(theSet.length) + itemIndex; 28 | var classes = ( activeCell == currentCell ) ? 'active' : ''; 29 | 30 | var props = { 31 | setIndex: setIndex, 32 | itemIndex: itemIndex, 33 | currentCell: currentCell, 34 | classes: classes, 35 | character: characterToDisplay, 36 | activateSet: this.props.activateSet, 37 | clearSet: this.props.clearSet, 38 | activateItem: this.props.activateItem 39 | }; 40 | 41 | return (); 42 | } 43 | 44 | var colour_map = { 45 | 0:"rgb("+255+","+255+","+255+")", //white 46 | 1:"rgb("+192+","+192+","+192+")", //light grey 47 | 2:"rgb("+96+","+96+","+96+")", // dark grey 48 | 3:"rgb("+0+","+0+","+0+")" // black 49 | }; 50 | 51 | var cachedPixels = { 52 | }; 53 | 54 | // 2bpp Planar 55 | function draw_row_from_bytes(byte1, byte2) { 56 | if (cachedPixels[byte1] && cachedPixels[byte1][byte2]) 57 | return cachedPixels[byte1][byte2]; 58 | var pixels = []; 59 | // 60 | // # Loop over each bit in the 2 bytes 61 | // 62 | for(var x = 8; x >0; x--) 63 | { 64 | // Find bit index for this pixel 65 | // i.e get a mask which can be applied to a byte, that will return the value of this pixel 66 | var pixelMask = 1 << (7-x); 67 | var colourOfPixel = 0; 68 | 69 | var bitValueOfByte1 = byte1 & pixelMask; 70 | var bitValueOfByte2 = byte2 & pixelMask; 71 | 72 | if (bitValueOfByte1) colourOfPixel+=1; 73 | if (bitValueOfByte2) colourOfPixel+=2; 74 | 75 | var fillStyle = colour_map[colourOfPixel]; 76 | let style = {'background-color': fillStyle}; 77 | pixels.push(
    ); 78 | } 79 | 80 | if (!cachedPixels[byte1]) cachedPixels[byte1] = {}; 81 | cachedPixels[byte1][byte2] = pixels; 82 | return pixels; 83 | 84 | } 85 | 86 | export const PixelSet = createReactClass({ 87 | activate: function () { 88 | this.props.activateSet(this.props.index); 89 | }, 90 | render: function() { 91 | var items = this.props.set.map(createAsciiCharacterElement.bind(this, this.props.setIndex)); 92 | var pixels = []; 93 | var pixels1 = draw_row_from_bytes(this.props.set[0],this.props.set[1]); 94 | var pixels2 = pixels.concat(draw_row_from_bytes(this.props.set[2],this.props.set[3])); 95 | 96 | return ( 97 |
    98 |
    99 |
    100 | {pixels1} 101 |
    102 |
    103 | {pixels2} 104 |
    105 |
    106 |
    107 | ); 108 | } 109 | }); 110 | -------------------------------------------------------------------------------- /websrc/pages/HexViewer/style.css: -------------------------------------------------------------------------------- 1 | .hexviewer { 2 | font-size: 15px; 3 | color: #000; 4 | margin-top: 20px; 5 | } 6 | 7 | .hexviewer .ascii { 8 | color: #555; 9 | } 10 | 11 | .hexviewer div.heading { 12 | font-family: monospace; 13 | width: 4.5em; 14 | float: left; 15 | color: #95AFBA; 16 | } 17 | 18 | .hexviewer div.row { 19 | height: 25px; 20 | line-height: 25px; 21 | justify-content: space-between; 22 | display: flex; 23 | } 24 | 25 | .hexviewer .none { 26 | visibility: hidden; 27 | } 28 | 29 | .hexviewer ul.setAscii, .hexviewer ul.setHex { 30 | float:left; 31 | margin:0;padding:0; 32 | font-family: monospace; 33 | text-align:center; 34 | margin-right:5px; 35 | margin-left: 5px; 36 | } 37 | 38 | .hexviewer ul.setAscii li, .hexviewer ul.setHex li { 39 | margin:0;padding:0; 40 | display: inline-block; 41 | width: 1.5em; 42 | } 43 | 44 | .hexviewer ul.setAscii.active, 45 | .hexviewer ul.setHex.active { 46 | color: #95AFBA; 47 | } 48 | 49 | .hexviewer ul.setAscii li.active, 50 | .hexviewer ul.setHex li.active { 51 | font-weight:bold; 52 | color: white; 53 | background-color: #95AFBA; 54 | } 55 | 56 | 57 | .pixelset { 58 | /* background: #333; */ 59 | height: 100vh; 60 | /* display: flex; */ 61 | display: inline-table; 62 | justify-content: center; 63 | align-items: center; 64 | } 65 | 66 | .codec2bpp { 67 | /* width: 10px; 68 | height: 80px; */ 69 | } 70 | 71 | .pixel { 72 | width: 2px; 73 | height: 2px; 74 | float: left; 75 | box-shadow: 0px 0px 1px #fff; 76 | } 77 | 78 | .pixelRow { 79 | position: relative; 80 | height: 40px; 81 | display: inline-block; 82 | width: 2px; 83 | } -------------------------------------------------------------------------------- /websrc/pages/InputHistory.css: -------------------------------------------------------------------------------- 1 | .inputButton-img { 2 | height: 25px; 3 | padding-bottom: 20px; 4 | } 5 | .inputButton-img:hover { 6 | cursor: pointer; 7 | } 8 | 9 | .inputButton-img.disabled { 10 | opacity: 0.2; 11 | } 12 | -------------------------------------------------------------------------------- /websrc/pages/MainPage.tsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import PropTypes from "prop-types"; 4 | 5 | import Typography from '@material-ui/core/Typography'; 6 | import Card from '@material-ui/core/Card'; 7 | import CardContent from '@material-ui/core/CardContent'; 8 | import Grid from '@material-ui/core/Grid'; 9 | 10 | import SaveStateList from '../main/SaveStateList'; 11 | import { sendActionToServer, loadState } from '../server'; 12 | 13 | export function deleteState({ setFullState, fullState }, frame) { 14 | console.log("About to delete state:", frame); 15 | // TODO: should probably warn if its the latest state (as would need to remove button presses and could invalidate functions) 16 | const payload = { 17 | category: 'delete_state', 18 | state: { 19 | frame 20 | }, 21 | }; 22 | sendActionToServer(payload).then((response) => { 23 | console.info("Delete successful response:", response, "fullstate:", fullState); 24 | setFullState({ ...fullState, playthrough: response }) 25 | }); 26 | }; 27 | 28 | function _MainPage( { fullState, setFullState, playthrough_name="Initial" }) { 29 | 30 | let current_state_card = null; 31 | 32 | if (fullState) { 33 | current_state_card=( 34 | 35 | 36 | 37 | Current State 38 | 39 | {fullState?.playthrough?.current_state?.name} 40 | 41 | {fullState?.playthrough?.current_state?.name} 42 | 43 | 44 | Frame {fullState?.playthrough?.current_state?.frame} out of {fullState?.playthrough?.last_frame} 45 | 46 | 47 | 48 | 49 | ); 50 | } 51 | 52 | 53 | 54 | return ( 55 |
    56 | 57 | 58 | 59 | 60 | History 61 | 62 | 63 | 64 | 65 | {current_state_card} 66 | 67 |
    68 | ); 69 | } 70 | 71 | _MainPage.propTypes = { 72 | 73 | } 74 | 75 | export const MainPage = React.memo(_MainPage); 76 | -------------------------------------------------------------------------------- /websrc/pages/NotesViewer/NotesViewer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Editor from "rich-markdown-editor"; 4 | import { Container, Paper, FormControlLabel, Switch, Button } from '@material-ui/core'; 5 | import SaveIcon from '@material-ui/icons/Save'; 6 | import { sendActionToServer } from '../../server'; 7 | 8 | export function NotesViewer( { memory }) { 9 | 10 | const [notes, setNotes] = useState(window.allInformation?.notes?.CD?.[memory.filename]?.notes || "Notes go here"); 11 | const overrideType = "CD"; 12 | 13 | function saveNote() { 14 | const payload = { 15 | category: 'modify_note', 16 | state: { 17 | overrideType, 18 | name: memory.filename || memory.name, 19 | notes 20 | }, 21 | }; 22 | sendActionToServer(payload); 23 | } 24 | 25 | return ( setNotes(e())} 28 | /> 29 | 30 | 33 | 34 | ) 35 | } -------------------------------------------------------------------------------- /websrc/pages/ParserViewer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | // import MonacoEditor from 'react-monaco-editor'; 4 | import Parser from './ParserViewer/binary_parser'; 5 | var Buffer = require('buffer/').Buffer // note: the trailing slash is important! 6 | // const { Parser, FileUnparser, ReactUnparser, Buffer } = window["binary_unparser"]; 7 | import { FileUnparser, ReactUnparser } from './ParserViewer/binary_unparser'; 8 | 9 | const default_code = ` 10 | // Build an IP packet header Parser 11 | var ipHeader = new Parser.Parser() 12 | .endianess("big") 13 | .bit4("version") 14 | .bit4("headerLength") 15 | .uint8("tos") 16 | .uint16("packetLength") 17 | .uint16("id") 18 | .bit3("offset") 19 | .bit13("fragOffset") 20 | .uint8("ttl") 21 | .uint8("protocol") 22 | .uint16("checksum") 23 | .array("src", { 24 | type: "uint8", 25 | length: 4 26 | }) 27 | .array("dst", { 28 | type: "uint8", 29 | length: 4 30 | }); 31 | 32 | var buf = Buffer.from("450002c5939900002c06ef98adc24f6c850186d1", "hex"); 33 | 34 | // Parse buffer and show result 35 | const result = ipHeader.parse(buf); 36 | console.log('result:',result); 37 | 38 | //var ipHeaderUP = new FileUnparser(ipHeader); 39 | //console.log("Unparsed:",ipHeaderUP.unparse(result, buf)); 40 | return "Done"; 41 | `; 42 | 43 | function runCodeWithDateFunction(obj, data){ 44 | return Function('"use strict";return (' + obj + ')')()( 45 | Parser, FileUnparser, data 46 | ); 47 | } 48 | 49 | 50 | export function ParserViewer() { 51 | 52 | const [code, setCode] = useState(default_code); 53 | 54 | return <>"Enable this in webpack"; 55 | 56 | console.error("Parser is:", Parser) 57 | 58 | var ipHeader = new Parser.Parser() 59 | .endianess("big") 60 | .uint8("version"); 61 | 62 | var buf = Buffer.from("450002c5939900002c06ef98adc24f6c850186d1", "hex"); 63 | window.Buffer = Buffer; 64 | window.React = React; 65 | 66 | // Parse buffer and show result 67 | const result = ipHeader.parse(buf); 68 | console.log('result:',result); 69 | console.log(runCodeWithDateFunction( "function(Parser, FileUnparser, data){ "+code+" \n}")) 70 | 71 | var ipHeaderUP = new ReactUnparser(ipHeader); 72 | const reactBuffer = []; 73 | const reactResult = ipHeaderUP.unparse(result, reactBuffer, React); 74 | console.log("Unparsed:",reactResult); 75 | // eval(code); 76 | 77 | const options = { 78 | selectOnLineNumbers: true 79 | }; 80 | // return ( 81 | //
    82 | // setCode(e.target.value)} 90 | // editorDidMount={()=>console.error("mount")} 91 | // /> 92 | // {reactResult} 93 | //
    94 | // ); 95 | 96 | return
    ParserViewer (enable by commenting back in the Monaco editor)
    97 | } -------------------------------------------------------------------------------- /websrc/pages/ParserViewer/context.js: -------------------------------------------------------------------------------- 1 | //======================================================================================== 2 | // class Context 3 | //======================================================================================== 4 | 5 | //---------------------------------------------------------------------------------------- 6 | // constructor 7 | //---------------------------------------------------------------------------------------- 8 | 9 | var Context = function() { 10 | this.code = ""; 11 | this.scopes = [["vars"]]; 12 | this.isAsync = false; 13 | this.bitFields = []; 14 | this.tmpVariableCount = 0; 15 | this.references = {}; 16 | }; 17 | 18 | //---------------------------------------------------------------------------------------- 19 | // public methods 20 | //---------------------------------------------------------------------------------------- 21 | 22 | Context.prototype.generateVariable = function(name) { 23 | var arr = []; 24 | 25 | Array.prototype.push.apply(arr, this.scopes[this.scopes.length - 1]); 26 | if (name) { 27 | arr.push(name); 28 | } 29 | 30 | return arr.join("."); 31 | }; 32 | 33 | Context.prototype.generateOption = function(val) { 34 | switch(typeof val) { 35 | case 'number': 36 | return val.toString(); 37 | case 'string': 38 | return this.generateVariable(val); 39 | case 'function': 40 | return '(' + val + ').call(' + this.generateVariable() + ', vars)'; 41 | } 42 | }; 43 | 44 | Context.prototype.generateError = function() { 45 | var args = Array.prototype.slice.call(arguments); 46 | var err = Context.interpolate.apply(this, args); 47 | 48 | if (this.isAsync) { 49 | this.pushCode( 50 | "return process.nextTick(function() { callback(new Error(" + 51 | err + 52 | "), vars); });" 53 | ); 54 | } else { 55 | this.pushCode("throw new Error(" + err + ");"); 56 | } 57 | }; 58 | 59 | Context.prototype.generateTmpVariable = function() { 60 | return "$tmp" + this.tmpVariableCount++; 61 | }; 62 | 63 | Context.prototype.pushCode = function() { 64 | var args = Array.prototype.slice.call(arguments); 65 | 66 | this.code += Context.interpolate.apply(this, args) + "\n"; 67 | }; 68 | 69 | Context.prototype.pushPath = function(name) { 70 | if (name) 71 | { 72 | this.scopes[this.scopes.length - 1].push(name); 73 | } 74 | }; 75 | 76 | Context.prototype.popPath = function(name) { 77 | if (name) 78 | { 79 | this.scopes[this.scopes.length - 1].pop(); 80 | } 81 | }; 82 | 83 | Context.prototype.pushScope = function(name) { 84 | this.scopes.push([name]); 85 | }; 86 | 87 | Context.prototype.popScope = function() { 88 | this.scopes.pop(); 89 | }; 90 | 91 | Context.prototype.addReference = function(alias) { 92 | if (this.references[alias]) return; 93 | this.references[alias] = { resolved: false, requested: false }; 94 | }; 95 | 96 | Context.prototype.markResolved = function(alias) { 97 | this.references[alias].resolved = true; 98 | }; 99 | 100 | Context.prototype.markRequested = function(aliasList) { 101 | aliasList.forEach( 102 | function(alias) { 103 | this.references[alias].requested = true; 104 | }.bind(this) 105 | ); 106 | }; 107 | 108 | Context.prototype.getUnresolvedReferences = function() { 109 | var references = this.references; 110 | return Object.keys(this.references).filter(function(alias) { 111 | return !references[alias].resolved && !references[alias].requested; 112 | }); 113 | }; 114 | 115 | //---------------------------------------------------------------------------------------- 116 | // private methods 117 | //---------------------------------------------------------------------------------------- 118 | 119 | Context.interpolate = function(s) { 120 | var re = /{\d+}/g; 121 | var matches = s.match(re); 122 | var params = Array.prototype.slice.call(arguments, 1); 123 | 124 | if (matches) { 125 | matches.forEach(function(match) { 126 | var index = parseInt(match.substr(1, match.length - 2), 10); 127 | s = s.replace(match, params[index].toString()); 128 | }); 129 | } 130 | 131 | return s; 132 | }; 133 | 134 | exports.Context = Context; -------------------------------------------------------------------------------- /websrc/pages/StringsViewer/StringsViewer.jsx: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useState, useEffect } from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | export function StringsViewer() { 5 | 6 | return
    StringsViewer
    7 | } -------------------------------------------------------------------------------- /websrc/pages/util/DownloadData.js: -------------------------------------------------------------------------------- 1 | export function downloadData(data, filename) { 2 | const blob = new Blob([data], {type: 'application/octet-stream'}); 3 | console.error("Bobl", blob); 4 | 5 | const url = window.URL.createObjectURL(blob); 6 | const a = document.createElement('a'); 7 | a.style.display = 'none'; 8 | a.href = url; 9 | // the filename you want 10 | a.download = filename; 11 | document.body.appendChild(a); 12 | a.click(); 13 | window.URL.revokeObjectURL(url); 14 | } -------------------------------------------------------------------------------- /websrc/pages/util/TripeDotDropDownMenu.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import IconButton from '@material-ui/core/IconButton'; 3 | import Menu from '@material-ui/core/Menu'; 4 | import MenuItem from '@material-ui/core/MenuItem'; 5 | import MoreVertIcon from '@material-ui/icons/MoreVert'; 6 | 7 | export default function TripeDotDropDownMenu({ options = [] }) { 8 | const [anchorEl, setAnchorEl] = React.useState(null); 9 | const open = Boolean(anchorEl); 10 | 11 | const handleClick = (event) => { 12 | setAnchorEl(event.currentTarget); 13 | }; 14 | 15 | const handleClose = () => { 16 | setAnchorEl(null); 17 | }; 18 | 19 | return ( 20 |
    21 | 27 | 28 | 29 | 36 | {options.map((option) => ( 37 | 38 | {option} 39 | 40 | ))} 41 | 42 |
    43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /websrc/pages/util/VirtualTable.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import PropTypes from "prop-types"; 3 | import clsx from "clsx"; 4 | import { withStyles } from "@material-ui/core/styles"; 5 | import TableCell from "@material-ui/core/TableCell"; 6 | import Paper from "@material-ui/core/Paper"; 7 | import { AutoSizer, Column, Table } from "react-virtualized"; 8 | import { TableSortLabel } from '@material-ui/core'; 9 | 10 | const headerRenderer = (order,setOrder, orderBy,setOrderBy, headerHeight, columns, { label, columnIndex }) => { 11 | function updateOrder() { 12 | const isAsc = orderBy === label && order === 'asc'; 13 | setOrder(isAsc ? 'desc' : 'asc'); 14 | setOrderBy(label); 15 | } 16 | return ( 17 | 23 | 27 | {label} 28 | 29 | 30 | ); 31 | }; 32 | 33 | const cellRenderer = (columns, rowHeight,{ cellData, columnIndex }) => { 34 | // console.error("cellRenderer", columns, rowHeight, cellData, columnIndex ); 35 | return ( 36 | 46 | {cellData} 47 | 48 | ); 49 | }; 50 | 51 | export default function VirtualizedTable({ 52 | columns, 53 | rowHeight=48, 54 | headerHeight=56, 55 | orderBy, 56 | setOrderBy, 57 | order, 58 | setOrder, 59 | ...tableProps 60 | }) { 61 | 62 | return ( 63 | 64 | {({ height, width }) => ( 65 | 84 | {columns.map(({ dataKey, ...other }, index) => { 85 | return ( 86 | 89 | headerRenderer(order, setOrder, orderBy,setOrderBy, headerHeight, columns,{ 90 | ...headerProps, 91 | columnIndex: index 92 | }) 93 | } 94 | // className={classes.flexContainer} 95 | cellRenderer={(a)=>cellRenderer(columns, rowHeight, a)} 96 | dataKey={dataKey} 97 | {...other} 98 | /> 99 | ); 100 | })} 101 |
    102 | )} 103 |
    104 | ); 105 | }; 106 | -------------------------------------------------------------------------------- /websrc/popovers/FrameHintPopover.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Popover from '@material-ui/core/Popover'; 3 | import Typography from '@material-ui/core/Typography'; 4 | import Button from '@material-ui/core/Button'; 5 | import { each, noop } from 'lodash'; 6 | import { createSaveStateTile } from '../main/SaveStateList'; 7 | import { Grid, GridList, Paper, Popper } from '@material-ui/core'; 8 | import { loadState } from '../server'; 9 | 10 | 11 | function findClosestStates(frame, states, load_state) { 12 | let closest_before = { frame: -1 }; 13 | let closest_after = { frame: 9999999999999 }; 14 | let exact_match = false; 15 | each(states, state => { 16 | if (state.frame === frame) { 17 | exact_match = true; 18 | closest_before = state; 19 | closest_after = state; 20 | return; 21 | } 22 | 23 | if (state.frame < frame) { 24 | // console.log("state.frame < frame, frame:", frame, "<", state.frame, " closest_before:", closest_before.frame, frame > closest_before.frame) 25 | if (state.frame > closest_before.frame) { 26 | closest_before = state; 27 | } 28 | console.log("state.frame < frame, frame:", frame, "<", state.frame, " closest_before:", closest_before.frame, frame > closest_before.frame) 29 | return; 30 | } 31 | if (state.frame > frame) { 32 | if (state.frame < closest_after.frame) { 33 | closest_after = state; 34 | return; 35 | } 36 | // console.log("state frame:", state.frame, "<", frame, "but <", closest_before) 37 | return; 38 | } 39 | console.error("State:", state.frame, frame); 40 | }) 41 | return ( 42 | {createSaveStateTile(closest_before, load_state, "After: ")} 43 | {createSaveStateTile(closest_after, load_state, "But Before: ")} 44 | ) 45 | // return {closest_before, closest_after, exact_match}; 46 | } 47 | 48 | export default function FrameHintPopOver(props) { 49 | const [anchorEl, setAnchorEl] = React.useState(null); 50 | const frame = props?.frame; 51 | 52 | const handleClick = (event) => { 53 | setAnchorEl(event.currentTarget); 54 | }; 55 | 56 | const handleClose = () => { 57 | setAnchorEl(null); 58 | }; 59 | 60 | const open = Boolean(anchorEl); 61 | const id = open ? 'simple-popover' : undefined; 62 | 63 | if (!frame) { return null; } 64 | 65 | const mainElement = ({frame || 0}); 67 | 68 | // if (!open) { 69 | // return mainElement; 70 | // } 71 | let popOver = null; 72 | 73 | if (open && frame) { 74 | popOver = ( 88 | 89 | Closest named frames to {frame} 90 | {findClosestStates(frame, window.allInformation?.playthrough?.states, loadState)} 91 | 92 | ); 93 | } 94 | 95 | return ( 96 |
    97 | {mainElement} 98 | {/* */} 101 | {/* 102 |
    The content of the Popper.
    103 |
    */} 104 | {open?popOver:null} 105 |
    106 | ); 107 | } -------------------------------------------------------------------------------- /websrc/server.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { loadFileFromLocalStorage, sendMessageToCoreFromFrontend } from "./home/GameDropZone"; 3 | 4 | export let gameLoaded = false; 5 | 6 | export function sendActionToServer(payload) { 7 | if (window["isWASM"]) { 8 | const result = sendMessageToCoreFromFrontend(payload); 9 | return Promise.resolve(result); 10 | } 11 | return axios.post('/postresponse', payload) 12 | .then(function (response) { 13 | console.info("Response from emulator:",response); 14 | gameLoaded = true; // TODO: use the response to set this to the correct value 15 | return response.data; 16 | }) 17 | .catch(function errorCallingEmulator(error) { 18 | console.error("Error calling emulator:",error); 19 | console.info("External emulator not found, using internal wasm emulator instead"); 20 | window["isWASM"] = true; 21 | gameLoaded = false; 22 | }); 23 | } 24 | 25 | export function loadState(frame) { 26 | console.log("About to load state:", frame); 27 | const payload = { 28 | category: 'load_state', 29 | state: { 30 | frame 31 | }, 32 | }; 33 | sendActionToServer(payload); 34 | }; 35 | 36 | export function requestFileFromServer(filename, playthrough_name = "Initial") { 37 | // TODO: get file from localstorage 38 | const last_part_of_path = `/playthroughs/${playthrough_name}/${filename}`; 39 | if (window["isWASM"]) { 40 | console.info("We are running in WASM mode to requesting file from localStorage instead") 41 | // TODO: need to get full path such as "/system/Genesis Plus GX/RE_projects/GameGear/MegaManUSA//playthroughs/Initial/button_log.bin" 42 | const full_path = "/system/Genesis Plus GX/RE_projects/GameGear/MegaManUSA/"+ last_part_of_path; 43 | return loadFileFromLocalStorage(full_path, filename); 44 | } 45 | return axios.get("/game" + last_part_of_path, { responseType: 'arraybuffer' }) 46 | .then(function (response) { 47 | console.info("Response from emulator:",response); 48 | return response.data; 49 | }) 50 | .catch(function (error) { 51 | console.error("Error calling emulator:",error); 52 | }); 53 | } -------------------------------------------------------------------------------- /websrc/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "ENGLISH", 3 | "assets": { 4 | "menu": "menu.png", 5 | "left": "left.png", 6 | "right": "right.png", 7 | "loading": "loading.png" 8 | }, 9 | "bindings": { 10 | "A": "X", 11 | "B": "Z", 12 | "X": "S", 13 | "Y": "A", 14 | "UP": "UP", 15 | "DOWN": "DOWN", 16 | "LEFT": "LEFT", 17 | "RIGHT": "RIGHT", 18 | "L": "C", 19 | "R": "D", 20 | "SELECT": "ENTER", 21 | "START": "SPACE" 22 | }, 23 | "melonDS": { 24 | "dependencies": [ 25 | "bios7.bin", 26 | "bios9.bin", 27 | "firmware.bin" 28 | ], 29 | "configurations": { 30 | "melonds_touch_mode": "Touch", 31 | "melonds_randomize_mac_address": "enabled" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /websrc/styles.js: -------------------------------------------------------------------------------- 1 | import { makeStyles, useTheme } from '@material-ui/core/styles'; 2 | import { createMuiTheme } from '@material-ui/core/styles'; 3 | 4 | const drawerWidth = 240; 5 | 6 | export const useRRTheme = useTheme; 7 | 8 | export const theme = createMuiTheme({ 9 | palette: { 10 | primary: { 11 | main: '#333333', 12 | }, 13 | secondary: { 14 | main: '#0079ca', 15 | }, 16 | }, 17 | }); 18 | 19 | export const useStyles = makeStyles((theme) => ({ 20 | root: { 21 | display: 'flex', 22 | }, 23 | appBar: { 24 | transition: theme.transitions.create(['margin', 'width'], { 25 | easing: theme.transitions.easing.sharp, 26 | duration: theme.transitions.duration.leavingScreen, 27 | }), 28 | }, 29 | appBarShift: { 30 | width: `calc(100% - ${drawerWidth}px)`, 31 | marginLeft: drawerWidth, 32 | transition: theme.transitions.create(['margin', 'width'], { 33 | easing: theme.transitions.easing.easeOut, 34 | duration: theme.transitions.duration.enteringScreen, 35 | }), 36 | }, 37 | menuButton: { 38 | marginRight: theme.spacing(2), 39 | }, 40 | hide: { 41 | display: 'none', 42 | }, 43 | drawer: { 44 | width: drawerWidth, 45 | flexShrink: 0, 46 | }, 47 | drawerPaper: { 48 | width: drawerWidth, 49 | }, 50 | drawerHeader: { 51 | display: 'flex', 52 | alignItems: 'center', 53 | padding: theme.spacing(0, 1), 54 | // necessary for content to be below app bar 55 | ...theme.mixins.toolbar, 56 | justifyContent: 'flex-end', 57 | }, 58 | content: { 59 | flexGrow: 1, 60 | padding: theme.spacing(3), 61 | transition: theme.transitions.create('margin', { 62 | easing: theme.transitions.easing.sharp, 63 | duration: theme.transitions.duration.leavingScreen, 64 | }), 65 | marginLeft: -drawerWidth, 66 | }, 67 | contentShift: { 68 | transition: theme.transitions.create('margin', { 69 | easing: theme.transitions.easing.easeOut, 70 | duration: theme.transitions.duration.enteringScreen, 71 | }), 72 | marginLeft: 0, 73 | }, 74 | })); -------------------------------------------------------------------------------- /websrc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./built", 4 | "allowJs": true, 5 | "module": "es6", // specify module code generation 6 | "jsx": "react", // use typescript to transpile jsx to js 7 | "target": "es5", 8 | "moduleResolution": "node", 9 | "allowSyntheticDefaultImports": true, 10 | "strict": false, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true 13 | }, 14 | "include": ["./main/**/*", "./pages/**/*"], 15 | "exclude": ["./node_modules/**/*"] 16 | } -------------------------------------------------------------------------------- /websrc/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const webpack = require('webpack') 3 | 4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 5 | const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); 6 | 7 | module.exports = { 8 | mode: 'development', 9 | entry: { 10 | app: './main', 11 | }, 12 | devtool: 'inline-source-map', 13 | devServer: { 14 | static: path.join(__dirname, './dist/'), // where dev server will look for static files, not compiled 15 | proxy: { 16 | '/postresponse': { 17 | target: 'http://127.0.0.1:1234/', 18 | changeOrigin: true, 19 | }, 20 | '/game': { 21 | target: 'http://127.0.0.1:1234/', 22 | changeOrigin: true, 23 | }, 24 | } 25 | }, 26 | output: { 27 | filename: 'libRRUI.bundle.js', 28 | path: path.resolve(__dirname, './dist/'), // base path where to send compiled assets 29 | publicPath: '/', // base path where referenced files will be look for 30 | }, 31 | resolve: { 32 | extensions: ['*', '.js', '.jsx', '.ts', '.tsx'], 33 | alias: { 34 | '@': path.resolve(__dirname, 'src'), // shortcut to reference src folder from anywhere 35 | }, 36 | fallback: { "vm": require.resolve("vm-browserify") } 37 | }, 38 | module: { 39 | rules: [ 40 | { 41 | test: /\.m?js/, 42 | resolve: { 43 | fullySpecified: false 44 | } 45 | }, 46 | { 47 | // config for es6 jsx 48 | test: /\.(js|jsx)$/, 49 | exclude: /node_modules/, 50 | use: { 51 | // loader: 'babel-loader', 52 | loader: 'ts-loader', 53 | }, 54 | }, 55 | { 56 | // config for es6 jsx 57 | test: /\.(ts|tsx)$/, 58 | exclude: /node_modules/, 59 | use: { 60 | loader: 'ts-loader', 61 | }, 62 | }, 63 | { 64 | test: /\.css$/i, 65 | use: ['style-loader', 'css-loader'], 66 | }, 67 | { 68 | // config for images 69 | test: /\.(png|svg|jpg|jpeg|gif)$/, 70 | use: [ 71 | { 72 | loader: 'file-loader', 73 | options: { 74 | outputPath: 'images', 75 | }, 76 | }, 77 | ], 78 | }, 79 | { 80 | // config for fonts 81 | test: /\.(woff|woff2|eot|ttf|otf)$/, 82 | use: [ 83 | { 84 | loader: 'file-loader', 85 | options: { 86 | outputPath: 'fonts', 87 | }, 88 | }, 89 | ], 90 | }, 91 | ], 92 | }, 93 | plugins: [ 94 | // new MonacoWebpackPlugin(), // reenable this when you want to use parser 95 | new HtmlWebpackPlugin({ 96 | template: './index.html', 97 | filename: 'index.html', 98 | title: 'Reversing Emulator', 99 | }), 100 | // fix "process is not defined" error: 101 | // (do "npm install process" before running the build) 102 | new webpack.ProvidePlugin({ 103 | process: 'process/browser', 104 | Buffer: ['buffer', 'Buffer'], 105 | }), 106 | ], 107 | }; 108 | --------------------------------------------------------------------------------