├── .clang-format ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENCE.txt ├── README.md ├── README.nfo ├── appveyor.yml ├── cd.c ├── cd.h ├── cli ├── etripator.c ├── options.c └── options.h ├── cmake └── FindJansson.cmake ├── comment.c ├── comment.h ├── comment ├── load.c └── save.c ├── config.h ├── decode.c ├── decode.h ├── doxyfile.in ├── examples ├── maerchen_maze │ ├── gfx_unpack.json │ └── labels.json ├── monster_puroresu │ ├── README.md │ ├── labels.json │ └── monster.json ├── sf2 │ ├── joypad.json │ └── labels.json ├── syscard │ ├── bank0.asm │ ├── bank0.json │ ├── labels.json │ └── syscard.inc ├── tadaima │ ├── README.md │ ├── labels.json │ └── mb128.json └── youkai_douchuuki │ ├── comments.json │ ├── labels.json │ ├── password.c │ └── password.json ├── externals └── CMakeLists.txt ├── ipl.c ├── ipl.h ├── irq.c ├── irq.h ├── jsonhelpers.c ├── jsonhelpers.h ├── label.c ├── label.h ├── label ├── load.c └── save.c ├── logo.png ├── memory.c ├── memory.h ├── memory_map.c ├── memory_map.h ├── message.c ├── message.h ├── message ├── console.c ├── console.h ├── file.c └── file.h ├── opcodes.c ├── opcodes.h ├── rom.c ├── rom.h ├── section.c ├── section.h ├── section ├── load.c └── save.c └── test ├── CMakeLists.txt ├── cd.c ├── comment.c ├── data ├── bank0_0.json ├── bank0_1.json ├── comment_0.json ├── comment_1.json ├── label_0.json └── label_1.json ├── ipl.c ├── label.c ├── memory.c ├── memory_map.c ├── message.c ├── opcodes.c ├── rom.c └── section.c /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | ColumnLimit: '120' 3 | IndentWidth: '4' 4 | TabWidth: '4' 5 | UseTab: Never 6 | 7 | ... 8 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: [push] 4 | 5 | env: 6 | BUILD_TYPE: Release 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v4 14 | with: 15 | submodules: 'recursive' 16 | 17 | - name: Setup Dependencies 18 | run: | 19 | sudo apt install -y -qq libjansson-dev 20 | 21 | - name: Configure 22 | shell: bash 23 | working-directory: ${{github.workspace}} 24 | run: cmake -Bbuild -S . -DCMAKE_BUILD_TYPE=$BUILD_TYPE 25 | 26 | - name: Build 27 | working-directory: ${{github.workspace}} 28 | shell: bash 29 | run: cmake --build ./build --config $BUILD_TYPE 30 | 31 | - name: Test 32 | working-directory: ${{github.workspace}} 33 | shell: bash 34 | run: cmake --build ./build --target test 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.o 3 | *.obj 4 | ijunk 5 | .svn 6 | build 7 | *.ncb 8 | *.suo 9 | *.user 10 | ipch 11 | *.sdf 12 | *.opensdf 13 | .DS_Store 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "externals/argparse"] 2 | path = externals/argparse 3 | url = https://github.com/cofyc/argparse.git 4 | [submodule "externals/munit"] 5 | path = externals/munit 6 | url = https://github.com/nemequ/munit.git 7 | [submodule "externals/cwalk"] 8 | path = externals/cwalk 9 | url = https://github.com/likle/cwalk.git 10 | branch=v1.2.9 11 | [submodule "externals/fff"] 12 | path = externals/fff 13 | url = https://github.com/meekrosoft/fff.git 14 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.30) 2 | 3 | project(etripator 4 | VERSION 0.9.0 5 | LANGUAGES C) 6 | 7 | if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") 8 | add_compile_definitions(_XOPEN_SOURCE=700) 9 | endif() 10 | 11 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 12 | 13 | enable_testing() 14 | 15 | include(CheckSymbolExists) 16 | 17 | check_symbol_exists(strdup "string.h" HAVE_STRDUP) 18 | 19 | if(NOT CMAKE_BUILD_TYPE) 20 | message(STATUS, "No build type specified. Force build type to Debug.") 21 | set(CMAKE_BUILD_TYPE "Debug") 22 | endif() 23 | 24 | find_package(Doxygen) 25 | find_package(Jansson) 26 | 27 | set(CMAKE_C_STANDARDS 11) 28 | 29 | add_subdirectory(externals EXCLUDE_FROM_ALL) 30 | 31 | set(etripator_SRC 32 | message.c 33 | message/file.c 34 | message/console.c 35 | jsonhelpers.c 36 | decode.c 37 | section.c 38 | section/load.c 39 | section/save.c 40 | opcodes.c 41 | comment.c 42 | comment/load.c 43 | comment/save.c 44 | label.c 45 | label/load.c 46 | label/save.c 47 | irq.c 48 | memory.c 49 | memory_map.c 50 | rom.c 51 | cd.c 52 | ipl.c 53 | ) 54 | 55 | set(etripator_HDR 56 | config.h 57 | message.h 58 | message/file.h 59 | message/console.h 60 | jsonhelpers.h 61 | decode.h 62 | section.h 63 | opcodes.h 64 | comment.h 65 | label.h 66 | irq.h 67 | memory.h 68 | memory_map.h 69 | rom.h 70 | cd.h 71 | ipl.h 72 | ) 73 | 74 | add_library(etripator STATIC ${etripator_SRC} ${etripator_HDR}) 75 | set_target_properties(etripator PROPERTIES C_STANDARD 11) 76 | target_compile_definitions(etripator PRIVATE _POSIX_C_SOURCE) 77 | target_link_libraries(etripator PUBLIC jansson cwalk) 78 | 79 | add_executable(etripator_cli cli/etripator.c cli/options.c) 80 | set_target_properties(etripator_cli 81 | PROPERTIES 82 | OUTPUT_NAME etripator 83 | C_STANDARD 11 84 | ) 85 | target_include_directories(etripator_cli PRIVATE ${CMAKE_SOURCE_DIR}) 86 | target_include_directories(etripator_cli PUBLIC externals) 87 | target_link_libraries(etripator_cli etripator argparse) 88 | 89 | set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/doxyfile.in) 90 | set(DOXYFILE ${CMAKE_CURRENT_BINARY_DIR}/doxyfile) 91 | 92 | configure_file(${DOXYFILE_IN} ${DOXYFILE} @ONLY IMMEDIATE) 93 | 94 | add_custom_target(doc 95 | COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE} 96 | SOURCES ${DOXYFILE} 97 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 98 | COMMENT "Generating API documentation with Doxygen" 99 | VERBATIM 100 | ) 101 | 102 | add_subdirectory(test) 103 | 104 | install(TARGETS etripator_cli DESTINATION bin) 105 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | os: Visual Studio 2017 2 | configuration: Release 3 | skip_tags: true 4 | 5 | environment: 6 | matrix: 7 | - compiler: msvc-15-seh 8 | build_system: cmake 9 | CMAKE_GENERATOR: Visual Studio 15 2017 Win64 10 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 11 | MSVC_PLATFORM: amd64 12 | BITS: 64 13 | 14 | - compiler: msvc-15-seh 15 | build_system: cmake 16 | CMAKE_GENERATOR: Visual Studio 15 2017 17 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 18 | MSVC_PLATFORM: x86 19 | BITS: 32 20 | 21 | install: 22 | - cd .. 23 | - ps: Invoke-WebRequest "https://github.com/akheron/jansson/archive/v2.12.zip" -OutFile "jansson.zip" 24 | - ps: Expand-Archive jansson.zip -DestinationPath . 25 | - cd jansson-2.12 26 | - md install 27 | - md build 28 | - cd build 29 | - cmake -DJANSSON_BUILD_DOCS=OFF -DJANSSON_WITHOUT_TESTS=ON -G "%CMAKE_GENERATOR%" -DCMAKE_INSTALL_PREFIX=../install .. 30 | - cmake --build . --config Release 31 | - cmake --build . --config Release --target install 32 | - cd ../../Etripator 33 | - git submodule update --init --recursive 34 | 35 | before_build: 36 | - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars%BITS%.bat" 37 | - mkdir install 38 | - mkdir build 39 | - cd build 40 | - cmake -G "%CMAKE_GENERATOR%" -DCMAKE_INSTALL_PREFIX=../install -DJANSSON_INCLUDE_DIR=../../jansson-2.12/install/include -DJANSSON_LIBRARY=../../jansson-2.12/install/lib/jansson.lib .. 41 | 42 | build_script: 43 | - cmake --build . --config Release 44 | - cmake --build . --config Release --target install 45 | 46 | after_build: 47 | - cd ../install 48 | - 7z a ../etripator.zip * -tzip 49 | 50 | artifacts: 51 | - path: etripator.zip 52 | name: etripator-v${appveyor_build_version}-%MSVC_PLATFORM%.zip 53 | 54 | deploy: 55 | release: etripator-v${appveyor_build_version} 56 | description: 'Etripator msvc15 %MSVC_PLATFORM% build' 57 | provider: GitHub 58 | auth_token: 59 | secure: 0Y6wz7NBuwl3+kPo4qFhU0Hh99m+8WWn3/wMk6NnbR284XTjG3Hg4BnnZont+24u 60 | artifact: /etripator.*\.zip/ 61 | draft: false 62 | prerelease: false 63 | on: 64 | branch: master 65 | appveyor_repo_tag: true 66 | 67 | -------------------------------------------------------------------------------- /cd.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "cd.h" 37 | #include "message.h" 38 | 39 | /// Adds CD RAM to memory map. 40 | bool cd_memory_map(MemoryMap *map) { 41 | int i; 42 | bool ret = false; 43 | // Allocate CD RAM 44 | if(!memory_create(&map->memory[PCE_MEMORY_CD_RAM], PCE_CD_RAM_BANK_COUNT * PCE_BANK_SIZE)) { 45 | ERROR_MSG("Failed to allocate cd memory!"); 46 | // Allocate System Card RAM 47 | } else if (!memory_create(&map->memory[PCE_MEMORY_SYSCARD_RAM], PCE_SYSCARD_RAM_BANK_COUNT * PCE_BANK_SIZE)) { 48 | ERROR_MSG("Failed to allocate system card memory!"); 49 | } else { 50 | // CD RAM is mapped to pages 0x80-0x88 (included). 51 | for (i = 0; i <= PCE_CD_RAM_BANK_COUNT; i++) { 52 | map->page[PCE_CD_RAM_FIRST_PAGE + i].id = PCE_MEMORY_CD_RAM; 53 | map->page[PCE_CD_RAM_FIRST_PAGE + i].bank = i; 54 | } 55 | // System Card RAM is mapped to pages 0x68-0x86. 56 | for (i = 0; i < PCE_SYSCARD_RAM_BANK_COUNT; i++) { 57 | map->page[PCE_SYSCARD_RAM_FIRST_PAGE + i].id = PCE_MEMORY_SYSCARD_RAM; 58 | map->page[PCE_SYSCARD_RAM_FIRST_PAGE + i].bank = i; 59 | } 60 | ret = true; 61 | } 62 | 63 | if(ret == false) { 64 | memory_map_destroy(map); 65 | } 66 | return ret; 67 | } 68 | 69 | /// Load CDROM data from file. 70 | bool cd_load(const char* filename, size_t start, size_t len, size_t sector_size, uint8_t page, size_t offset, MemoryMap* map) { 71 | bool ret = false; 72 | FILE *in = fopen(filename, "rb"); 73 | if(in == NULL) { 74 | ERROR_MSG("Unable to open %s : %s", filename, strerror(errno)); 75 | } else { 76 | size_t remaining = len; 77 | size_t physical = (offset & 0x1FFFU) | (page << 0x0D); 78 | for(ret=true; ret && remaining; ) { 79 | size_t count = 2048 - (start % 2048); 80 | if(count > remaining) { 81 | count = remaining; 82 | } 83 | 84 | size_t sector_id = start / 2048; 85 | size_t sector_offset = start % 2048; 86 | 87 | size_t file_offset = (sector_id * sector_size) + sector_offset; 88 | 89 | size_t current_page = physical >> 0x0D; 90 | size_t current_addr = physical & 0x1FFF; 91 | 92 | size_t bank_offset = current_addr + (map->page[current_page].bank * PCE_BANK_SIZE); 93 | 94 | // [todo] test that map->page[current_page].id != PCE_MEMORY_NONE 95 | 96 | ret = false; 97 | if(fseek(in, (long int)file_offset, SEEK_SET) < 0) { 98 | ERROR_MSG("Offset out of bound : %s", strerror(errno)); 99 | } else if(fread(map->memory[map->page[current_page].id].data+bank_offset, 1, count, in) != count) { 100 | ERROR_MSG("Failed to read %d bytes : %s", count, strerror(errno)); 101 | } else { 102 | ret = true; 103 | } 104 | start += count; 105 | physical += count; 106 | remaining -= count; 107 | } 108 | 109 | } 110 | if(in) { 111 | fclose(in); 112 | } 113 | return ret; 114 | } 115 | -------------------------------------------------------------------------------- /cd.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_CD_H 37 | #define ETRIPATOR_CD_H 38 | 39 | #include "config.h" 40 | #include "memory_map.h" 41 | 42 | #define PCE_CD_RAM_BANK_COUNT 8U 43 | #define PCE_SYSCARD_RAM_BANK_COUNT 24U 44 | 45 | #define PCE_CD_RAM_FIRST_PAGE 0x80U 46 | #define PCE_SYSCARD_RAM_FIRST_PAGE 0x68U 47 | 48 | /// Adds CD RAM to memory map. 49 | /// \param map Memory map. 50 | /// \return true if the CD RAM and SYSCARD RAM memory areas were successfully created. 51 | /// \return false if an error occured. 52 | bool cd_memory_map(MemoryMap *map); 53 | 54 | /// Load CDROM data from file. 55 | /// \param [in] filename CDROM data filename. 56 | /// \param [in] start CDROM data offset. 57 | /// \param [in] len CDROM data length (in bytes). 58 | /// \param [in] sector_size CD sector size. 59 | /// \param [in] page Memory page. 60 | /// \param [in] offset Memory page offset. 61 | /// \param [out] map Memory map. 62 | /// \return true 63 | /// \return false 64 | bool cd_load(const char* filename, size_t start, size_t len, size_t sector_size, uint8_t page, size_t offset, MemoryMap* map); 65 | 66 | #endif // ETRIPATOR_CD_H 67 | -------------------------------------------------------------------------------- /cli/options.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "options.h" 37 | 38 | #include 39 | 40 | #include 41 | 42 | struct payload_t { 43 | size_t capacity; 44 | size_t size; 45 | const char ***array; 46 | }; 47 | 48 | static int opt_callback(struct argparse *self, const struct argparse_option *options) { 49 | struct payload_t *payload = (struct payload_t*)options->data; 50 | size_t last = payload->size++; 51 | if(payload->capacity <= payload->size) { 52 | payload->capacity += 4; 53 | const char **tmp = (const char**)realloc(*payload->array, payload->capacity*sizeof(const char*)); 54 | if(tmp == NULL) { 55 | return 0; 56 | } 57 | memset(tmp+last, 0, 4*sizeof(const char*)); 58 | *payload->array = tmp; 59 | } 60 | (*payload->array)[last] = *(char**)options->value; 61 | return 1; 62 | } 63 | 64 | // Extract command line options 65 | bool cli_opt_get(CommandLineOptions *options, int argc, const char** argv) { 66 | static const char *const usages[] = { 67 | "etripator [options] [--] ", 68 | NULL 69 | }; 70 | 71 | bool ret = false; 72 | 73 | char *dummy; 74 | struct payload_t labels_payload = { 0, 0, &options->labels_in }; 75 | struct payload_t comments_payload = {0, 0, &options->comments_in}; 76 | 77 | struct argparse_option arg_opt[] = { 78 | OPT_HELP(), 79 | OPT_BOOLEAN('i', "irq-detect", &options->extract_irq, "automatically detect and extract irq vectors when disassembling a ROM, or extract opening code and gfx from CDROM IPL data", NULL, 0, 0), 80 | OPT_BOOLEAN('c', "cd", &options->cdrom, "cdrom image disassembly. Irq detection and rom. Header jump is not performed", NULL, 0, 0), 81 | OPT_STRING('o', "out", &options->main_filename, "main asm file containing includes for all sections as long the irq vector table if the irq-detect option is enabled", NULL, 0, 0), 82 | OPT_STRING('l', "labels", &dummy, "labels definition filename", opt_callback, (intptr_t)&labels_payload, 0), 83 | OPT_STRING(0, "labels-out", &options->labels_out, "extracted labels output filename. Otherwise the labels will be written to .YYMMDDhhmmss.lbl", NULL, 0, 0), 84 | OPT_STRING(0, "comments", &dummy, "comments description filename", opt_callback, (intptr_t)&comments_payload, 0), 85 | OPT_BOOLEAN(0, "address", &options->address, "print statement address as comment", NULL, 0, 0), 86 | OPT_INTEGER(0, "sector_size", &options->sector_size, "2352 bytes sectors (cd only)", NULL, 0, 0), 87 | OPT_END(), 88 | }; 89 | 90 | struct argparse argparse; 91 | 92 | options->extract_irq = 0; 93 | options->cdrom = 0; 94 | options->cfg_filename = NULL; 95 | options->rom_filename = NULL; 96 | options->main_filename = "main.asm"; 97 | options->labels_in = NULL; 98 | options->labels_out = NULL; 99 | options->comments_in = NULL; 100 | options->address = 0; 101 | options->sector_size = 2048; 102 | 103 | argparse_init(&argparse, arg_opt, usages, 0); 104 | argparse_describe(&argparse, "\nEtripator : a PC Engine disassembler", " "); 105 | argc = argparse_parse(&argparse, argc, argv); 106 | if(!argc) { 107 | // ... 108 | } else if((options->sector_size != 2048) && (options->sector_size != 2352)) { 109 | ERROR_MSG("invalid sector size (must be 2048 or 2352)."); 110 | } else if(argc != 2) { 111 | if((options->extract_irq) && (argc == 1)) { 112 | /* Config file is optional with automatic irq vector extraction. */ 113 | options->cfg_filename = NULL; 114 | options->rom_filename = argv[0]; 115 | ret = true; 116 | } 117 | else { 118 | // ... 119 | } 120 | } 121 | else { 122 | options->cfg_filename = argv[0]; 123 | options->rom_filename = argv[1]; 124 | ret = true; 125 | } 126 | 127 | if(!ret) { 128 | argparse_usage(&argparse); 129 | } 130 | 131 | return ret; 132 | } 133 | 134 | // Release allocated resources during command line parsing 135 | void cli_opt_release(CommandLineOptions *options) { 136 | if(options->comments_in) { 137 | free(options->comments_in); 138 | } 139 | if(options->labels_in) { 140 | free(options->labels_in); 141 | } 142 | memset(options, 0, sizeof(CommandLineOptions)); 143 | } 144 | -------------------------------------------------------------------------------- /cli/options.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_OPTIONS_H 37 | #define ETRIPATOR_OPTIONS_H 38 | 39 | #include 40 | 41 | /* Command line options */ 42 | typedef struct { 43 | int extract_irq; 44 | int cdrom; 45 | int sector_size; 46 | int address; 47 | const char *cfg_filename; 48 | const char *rom_filename; 49 | const char *main_filename; 50 | const char *labels_out; 51 | const char **labels_in; 52 | const char **comments_in; 53 | } CommandLineOptions; 54 | 55 | /// Extract command line options 56 | bool cli_opt_get(CommandLineOptions *options, int argc, const char** argv); 57 | 58 | /// Release allocated resources during command line parsing 59 | void cli_opt_release(CommandLineOptions *options); 60 | 61 | #endif // ETRIPATOR_OPTIONS_H 62 | -------------------------------------------------------------------------------- /cmake/FindJansson.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find Jansson 2 | # Once done this will define 3 | # 4 | # JANSSON_FOUND - system has Jansson 5 | # JANSSON_INCLUDE_DIRS - the Jansson include directory 6 | # JANSSON_LIBRARIES - Link these to use Jansson 7 | # 8 | # Copyright (c) 2011 Lee Hambley 9 | # 10 | # Redistribution and use is allowed according to the terms of the New 11 | # BSD license. 12 | # For details see the accompanying COPYING-CMAKE-SCRIPTS file. 13 | # 14 | 15 | if (JANSSON_LIBRARIES AND JANSSON_INCLUDE_DIRS) 16 | # in cache already 17 | set(JANSSON_FOUND TRUE) 18 | else (JANSSON_LIBRARIES AND JANSSON_INCLUDE_DIRS) 19 | find_path(JANSSON_INCLUDE_DIR 20 | NAMES 21 | jansson.h 22 | PATHS 23 | /usr/include 24 | /usr/local/include 25 | /opt/local/include 26 | /sw/include 27 | ) 28 | 29 | find_library(JANSSON_LIBRARY 30 | NAMES 31 | jansson 32 | PATHS 33 | /usr/lib 34 | /usr/local/lib 35 | /opt/local/lib 36 | /sw/lib 37 | ) 38 | 39 | set(JANSSON_INCLUDE_DIRS 40 | ${JANSSON_INCLUDE_DIR} 41 | ) 42 | 43 | if (JANSSON_LIBRARY) 44 | set(JANSSON_LIBRARIES 45 | ${JANSSON_LIBRARIES} 46 | ${JANSSON_LIBRARY} 47 | ) 48 | endif (JANSSON_LIBRARY) 49 | endif (JANSSON_LIBRARIES AND JANSSON_INCLUDE_DIRS) 50 | 51 | include(FindPackageHandleStandardArgs) 52 | find_package_handle_standard_args(Jansson DEFAULT_MSG 53 | JANSSON_LIBRARIES JANSSON_INCLUDE_DIRS) 54 | 55 | if(JANSSON_FOUND) 56 | add_library(jansson UNKNOWN IMPORTED) 57 | set_target_properties(jansson 58 | PROPERTIES 59 | IMPORTED_LOCATION "${JANSSON_LIBRARIES}" 60 | INTERFACE_INCLUDE_DIRECTORIES "${JANSSON_INCLUDE_DIRS}" 61 | ) 62 | endif() 63 | 64 | # show the JANSSON_INCLUDE_DIRS and JANSSON_LIBRARIES variables only in the advanced view 65 | mark_as_advanced(JANSSON_INCLUDE_DIRS JANSSON_LIBRARIES) 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /comment.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "comment.h" 37 | #include "message.h" 38 | 39 | #include 40 | #include "jsonhelpers.h" 41 | 42 | #define COMMENT_ARRAY_INC 16 43 | 44 | /// Get comment index by its address. 45 | /// \param [in] repository Coment repository. 46 | /// \param [in] logical Logical address. 47 | /// \param [in] page Memory page. 48 | /// \return comment index. 49 | /// \return -1 if the label was not found. 50 | static int comment_repository_index(CommentRepository* repository, uint16_t logical, uint8_t page) { 51 | size_t i; 52 | for(i=0; ilast; i++) { 53 | if( (repository->comments[i].page == page) && 54 | (repository->comments[i].logical == logical) ) { 55 | return (int)i; 56 | } 57 | } 58 | return -1; 59 | } 60 | 61 | // Create comment repository. 62 | bool comment_repository_create(CommentRepository *repository) { 63 | assert(repository != NULL); 64 | bool ret = true; 65 | 66 | repository->last = 0; 67 | repository->comments = NULL; 68 | 69 | repository->size = COMMENT_ARRAY_INC; 70 | repository->comments = (Comment*)malloc(repository->size * sizeof(Comment)); 71 | if(repository->comments == NULL) { 72 | ERROR_MSG("Failed to create comments: %s", strerror(errno)); 73 | comment_repository_destroy(repository); 74 | ret = false; 75 | } 76 | return ret; 77 | } 78 | 79 | // Release comment repository resources. 80 | void comment_repository_destroy(CommentRepository* repository) { 81 | assert(repository != NULL); 82 | 83 | repository->size = 0; 84 | repository->last = 0; 85 | 86 | if(repository->comments != NULL) { 87 | for(size_t i=0; ilast; i++) { 88 | free(repository->comments[i].text); 89 | } 90 | free(repository->comments); 91 | repository->comments = NULL; 92 | } 93 | } 94 | 95 | // Add comment to repository. 96 | bool comment_repository_add(CommentRepository* repository, uint16_t logical, uint8_t page, const char *text) { 97 | assert(repository != NULL); 98 | assert(text != NULL); 99 | 100 | bool ret = true; 101 | int index = comment_repository_index(repository, logical, page); 102 | if(index >= 0) { 103 | WARNING_MSG("Duplicate comment for logical address $%04x in page $%02x", logical, page); 104 | } else { 105 | // Expand arrays if necessary. 106 | if(repository->last >= repository->size) { 107 | Comment *ptr; 108 | size_t new_size = repository->size + COMMENT_ARRAY_INC; 109 | ptr = (Comment*)realloc(repository->comments, new_size * sizeof(Comment)); 110 | if(ptr == NULL) { 111 | ERROR_MSG("Failed to expand comment buffer: %s", strerror(errno)); 112 | comment_repository_destroy(repository); 113 | ret = false; 114 | } else { 115 | repository->comments = ptr; 116 | repository->size = new_size; 117 | } 118 | } 119 | if(ret) { 120 | // Push addresses & text. 121 | repository->comments[repository->last].logical = logical; 122 | repository->comments[repository->last].page = page; 123 | repository->comments[repository->last].text = strdup(text); 124 | 125 | ++repository->last; 126 | } 127 | } 128 | return ret; 129 | } 130 | 131 | // Find a comment by its address. 132 | bool comment_repository_find(CommentRepository* repository, uint16_t logical, uint8_t page, Comment *out) { 133 | assert(repository != NULL); 134 | assert(out != NULL); 135 | 136 | int index = comment_repository_index(repository, logical, page); 137 | bool ret = (index >= 0); 138 | if(ret) { 139 | memcpy(out, &repository->comments[index], sizeof(Comment)); 140 | } else { 141 | memset(out, 0, sizeof(Comment)); 142 | } 143 | return ret; 144 | } 145 | 146 | // Get the number of comments stored in the repository. 147 | int comment_repository_size(CommentRepository* repository) { 148 | assert(repository != NULL); 149 | return (int)repository->last; 150 | } 151 | 152 | // Retrieve the comment at the specified index. 153 | bool comment_repository_get(CommentRepository* repository, int index, Comment *out) { 154 | assert(repository != NULL); 155 | assert(out != NULL); 156 | 157 | bool ret = false; 158 | if((index >= 0) && (index < (int)repository->last)) { 159 | memcpy(out, &repository->comments[index], sizeof(Comment)); 160 | ret = true; 161 | } else { 162 | memset(out, 0, sizeof(Comment)); 163 | } 164 | return ret; 165 | } 166 | 167 | // Delete comments. 168 | void comment_repository_delete(CommentRepository* repository, uint16_t first, uint16_t end, uint8_t page) { 169 | assert(repository != NULL); 170 | 171 | for(size_t i=0; ilast; i++) { 172 | if( (repository->comments[i].page == page) && 173 | (repository->comments[i].logical >= first) && 174 | (repository->comments[i].logical < end) ) { 175 | if(repository->last) { 176 | repository->last--; 177 | if(repository->comments[i].text) { 178 | free(repository->comments[i].text); 179 | } 180 | memcpy(&repository->comments[i], &repository->comments[repository->last], sizeof(Comment)); 181 | i--; 182 | } 183 | } 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /comment.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_COMMENT_H 37 | #define ETRIPATOR_COMMENT_H 38 | 39 | #include "config.h" 40 | 41 | /// Comment. 42 | typedef struct { 43 | uint16_t logical; //< Logical address. 44 | uint8_t page; //< Memory page. 45 | char* text; //< Comment text. 46 | } Comment; 47 | 48 | /// Comment repository. 49 | typedef struct { 50 | size_t size; //< Size of comment repository. 51 | size_t last; //< Last element in the repository. 52 | Comment *comments; //< Comments. 53 | } CommentRepository; 54 | 55 | /// Create comment repository. 56 | /// \param [in out] repository Comment repository. 57 | /// \return true if the repository was succesfully initialized 58 | /// \return false if an error occured 59 | bool comment_repository_create(CommentRepository* repository); 60 | 61 | /// Release comment repository resources. 62 | /// \param [in,out] repository Comment repository. 63 | void comment_repository_destroy(CommentRepository* repository); 64 | 65 | /// Add comment to repository. 66 | /// \param [in,out] repository Comment repository. 67 | /// \param [in] logical Logical address. 68 | /// \param [in] page Memory page. 69 | /// \param [in] text Comment text. 70 | /// \return true if the comment was successfully added to the repository. 71 | /// \return false if an error occured. 72 | bool comment_repository_add(CommentRepository* repository, uint16_t logical, uint8_t page, const char *text); 73 | 74 | /// Find a comment by its address. 75 | /// \param [in] repository Comment repository. 76 | /// \param [in] logical Logical address. 77 | /// \param [in] page Memory page. 78 | /// \param [out] out Associated comment (if any). 79 | /// \return true if a comment was found. 80 | /// \return 0 otherwise. 81 | bool comment_repository_find(CommentRepository* repository, uint16_t logical, uint8_t page, Comment *out); 82 | 83 | /// Get the number of comments stored in the repository. 84 | /// \param [in] repository Comment repository. 85 | /// \return Comment count. 86 | int comment_repository_size(CommentRepository* repository); 87 | 88 | /// Retrieve the comment at the specified index. 89 | /// \param [in] repository Comment repository. 90 | /// \param [in] index Comment index. 91 | /// \param [out] out Comment (if any). 92 | /// \return true if a comment exists for the specified index. 93 | /// \return false otherwise. 94 | bool comment_repository_get(CommentRepository* repository, int index, Comment *out); 95 | 96 | /// Delete comments. 97 | /// \param [in] repository Comment repository. 98 | /// \param [in] first Start of the logical address range. 99 | /// \param [in] end End of the logical address range. 100 | /// \param [in] page Memory page. 101 | void comment_repository_delete(CommentRepository* repository, uint16_t first, uint16_t end, uint8_t page); 102 | 103 | /// Load comments from file. 104 | /// \param [in, out] repository Comment repository. 105 | /// \param [in] filename Input filename. 106 | /// \return true if the comments contained in the file was succesfully added to the repository. 107 | /// \return false if an error occured. 108 | bool comment_repository_load(CommentRepository* repository, const char* filename); 109 | 110 | /// Save comments to file. 111 | /// \param [in] repository Comment repository. 112 | /// \param [in] filename Output filename. 113 | /// \return true if the comments were succesfully saved. 114 | /// \return false if an error occured. 115 | bool comment_repository_save(CommentRepository* repository, const char* filename); 116 | 117 | #endif // ETRIPATOR_COMMENT_H -------------------------------------------------------------------------------- /comment/load.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | #include "../message.h" 38 | #include "../jsonhelpers.h" 39 | #include "../comment.h" 40 | 41 | // Load comments from file. 42 | bool comment_repository_load(CommentRepository* repository, const char* filename) { 43 | assert(filename != NULL); 44 | assert(repository != NULL); 45 | 46 | bool ret = false; 47 | 48 | json_t* root; 49 | json_error_t err; 50 | json_t* value; 51 | int index = 0; 52 | root = json_load_file(filename, 0, &err); 53 | if(!root) { 54 | ERROR_MSG("Failed to parse %s:%d:%d: %s", filename, err.line, err.column, err.text); 55 | } else { 56 | if(!json_is_array(root)) { 57 | ERROR_MSG("Array expected."); 58 | } else for (index = 0, ret = true; ret && (index < json_array_size(root)) && (value = json_array_get(root, index)); index++) { 59 | ret = false; 60 | if(!json_is_object(value)) { 61 | ERROR_MSG("Expected object."); 62 | } else { 63 | int num; 64 | // logical 65 | json_t *tmp = json_object_get(value, "logical"); 66 | if(!json_validate_int(tmp, &num)) { 67 | ERROR_MSG("Invalid or missing logical address."); 68 | } else if((num < 0) || (num > 0xffff)) { 69 | ERROR_MSG("Logical address out of range."); 70 | } else { 71 | uint16_t logical = (uint16_t)num; 72 | // page 73 | tmp = json_object_get(value, "page"); 74 | if(!json_validate_int(tmp, &num)) { 75 | ERROR_MSG("Invalid or missing page."); 76 | } else { 77 | // text (same format as section/label description) 78 | char* text = NULL; 79 | if(json_load_description (value, "text", &text) != true) { 80 | ERROR_MSG("Faile to retrieve text."); 81 | } else if(text == NULL) { 82 | ERROR_MSG("Empty text string"); 83 | } else if((num < 0) || (num > 0xFF)) { 84 | ERROR_MSG("Page value out of range."); 85 | } else if(comment_repository_add(repository, logical, (uint8_t)num, text)) { 86 | ret = true; 87 | } 88 | free(text); 89 | } 90 | } 91 | } 92 | } 93 | json_decref(root); 94 | } 95 | return ret; 96 | } 97 | -------------------------------------------------------------------------------- /comment/save.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | #include 38 | 39 | #include "../message.h" 40 | #include "../jsonhelpers.h" 41 | #include "../comment.h" 42 | 43 | // Save comments to file. 44 | bool comment_repository_save(CommentRepository* repository, const char* filename) { 45 | assert(filename != NULL); 46 | assert(repository != NULL); 47 | 48 | bool ret = false; 49 | 50 | FILE *stream = fopen(filename, "wb"); 51 | if(stream == NULL) { 52 | ERROR_MSG("Failed to open %s: %s", filename, strerror(errno)); 53 | } else { 54 | int count = comment_repository_size(repository); 55 | fprintf(stream, "[\n"); 56 | for(int i=0; i ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_CONFIG_H 37 | #define ETRIPATOR_CONFIG_H 38 | 39 | #define _GNU_SOURCE 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include 48 | #include 49 | 50 | #include 51 | 52 | #include 53 | #include 54 | 55 | #include 56 | #include 57 | #include 58 | #include 59 | 60 | #if defined(__linux__) || defined(__APPLE__) 61 | # include 62 | # include 63 | #endif 64 | 65 | #if defined(_MSC_VER) 66 | # define strncasecmp _strnicmp 67 | # define strcasecmp _stricmp 68 | # define snprintf _snprintf 69 | # define access _access 70 | #endif 71 | 72 | #endif // ETRIPATOR_CONFIG_H 73 | -------------------------------------------------------------------------------- /decode.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_DECODE_H 37 | #define ETRIPATOR_DECODE_H 38 | 39 | #include "config.h" 40 | #include "label.h" 41 | #include "section.h" 42 | #include "memory_map.h" 43 | #include "comment.h" 44 | 45 | /// Finds any jump address from the current section. 46 | /// \param [in] section Current section. 47 | /// \param [in] map Memory map. 48 | /// \param [in out] repository Label repository. 49 | /// \return true upon success. 50 | /// \return false if an error occured. 51 | bool label_extract(Section *section, MemoryMap *map, LabelRepository *repository); 52 | 53 | /// Process data section. The result will be output has a binary file or an asm file containing hex values or strings. 54 | /// \param [out] out File output. 55 | /// \param [in] section Current section. 56 | /// \param [in] map Memory map. 57 | /// \param [in] repository Label repository. 58 | /// \param [in] comments Comments repository. 59 | /// \param [in] extra_infos Display extra informations as comments (if none set). 60 | /// \return true upon success. 61 | /// \return false if an error occured. 62 | bool data_extract(FILE *out, Section *section, MemoryMap *map, LabelRepository *repository, CommentRepository *comments, int extra_infos); 63 | 64 | /// Process code section. 65 | /// \param [out] out File output. 66 | /// \param [in out] logical Current logical address. 67 | /// \param [in] section Current section. 68 | /// \param [in] map Memory map. 69 | /// \param [in] repository Label repository. 70 | /// \param [in] comments Comments repository. 71 | /// \param [in] extra_infos Display extra informations as comments (if none set). 72 | /// \return true if rts, rti or brk instruction was decoded. 73 | /// \return false otherwise. 74 | int decode(FILE *out, uint16_t *logical, Section *section, MemoryMap *map, LabelRepository *repository, CommentRepository *comments, int extra_infos); 75 | 76 | /// Computes section size. 77 | /// \param [in] sections Section array. 78 | /// \param [in] index Index of the current section. 79 | /// \param [in] count Number of sections. 80 | /// \param [in] map Memory map. 81 | /// \return Section size. 82 | int32_t compute_size(SectionArray *sections, int index, int count, MemoryMap *map); 83 | 84 | /// Output hardware IO port and RAM labels. 85 | /// \param [out] out File output. 86 | /// \param [in] map Memory map. 87 | /// \param [in] repository Label repository. 88 | void label_dump(FILE *out, MemoryMap *map, LabelRepository *repository); 89 | 90 | #endif // ETRIPATOR_DECODE_H 91 | -------------------------------------------------------------------------------- /doxyfile.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = "@CMAKE_PROJECT_NAME@" 2 | PROJECT_NUMBER = @ETRIPATOR_VERSION@ 3 | STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@ \ 4 | @PROJECT_BINARY_DIR@ \ 5 | @CMAKE_SOURCE_DIR@ 6 | INPUT = @PROJECT_SOURCE_DIR@ 7 | INPUT += @PROJECT_SOURCE_DIR@/README.md 8 | FILE_PATTERNS = *.h \ 9 | *.c 10 | GENERATE_LATEX = NO 11 | RECURSIVE = YES 12 | USE_MDFILE_AS_MAINPAGE = README.md 13 | OPTIMIZE_OUTPUT_FOR_C = YES 14 | OPTIMIZE_OUTPUT_JAVA = NO 15 | SUBGROUPING = YES 16 | EXTRACT_ALL = YES 17 | OUTPUT_DIRECTORY = doc 18 | EXCLUDE_PATTERNS = */.git/* 19 | EXCLUDE_PATTERNS += */build/* 20 | EXCLUDE_PATTERNS += */cmake/* 21 | EXCLUDE_PATTERNS += */doc/* 22 | EXCLUDE_PATTERNS += */data/* 23 | EXCLUDE_PATTERNS += */test/* 24 | EXCLUDE_PATTERNS += */examples/* 25 | EXCLUDE = *.in 26 | JAVADOC_AUTOBRIEF = YES 27 | MARKDOWN_SUPPORT = YES 28 | SUBGROUPING = YES 29 | EXTRACT_STATIC = YES 30 | SHOW_INCLUDE_FILES = YES 31 | 32 | -------------------------------------------------------------------------------- /examples/maerchen_maze/gfx_unpack.json: -------------------------------------------------------------------------------- 1 | { 2 | "gfx_unpack": { 3 | "filename": "gfx.asm", 4 | "type": "code", 5 | "page": "0", 6 | "logical": "f71c", 7 | "size": "1ac", 8 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 9 | } 10 | } -------------------------------------------------------------------------------- /examples/maerchen_maze/labels.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name": "gfx_unpack.loop", "logical": "f796", "page": "00" }, 3 | { "name": "gfx_unpack.next", "logical": "f7f6", "page": "00" }, 4 | { "name": ".rle", "logical": "f7ac", "page": "00" }, 5 | { "name": ".rle_xor", "logical": "f7bc", "page": "00" }, 6 | { "name": ".copy", "logical": "f7cf", "page": "00" }, 7 | { "name": ".loop", "logical": "f7d2", "page": "00" }, 8 | { "name": "gfx_unpack.map_data", "logical": "f8a6", "page": "00" }, 9 | { "name": "gfx_unpack.remap_data", "logical": "f7e1", "page": "00" }, 10 | { "name": "gfx_unpack.rle", "logical": "f817", "page": "00" }, 11 | { "name": ".rle.loop", "logical": "f828", "page": "00" }, 12 | { "name": ".rle.unroll", "logical": "f83a", "page": "00" }, 13 | { "name": ".rle.copy", "logical": "f849", "page": "00" }, 14 | { "name": "gfx_unpack.xor", "logical": "f857", "page": "00" }, 15 | { "name": ".xor.loop", "logical": "f85c", "page": "00" }, 16 | { "name": "gfx_unpack.get_type", "logical": "f888", "page": "00" }, 17 | { "name": "gfx_unpack.copy", "logical": "f803", "page": "00" }, 18 | { "name": ".copy.loop", "logical": "f804", "page": "00" }, 19 | { "name": ".incw", "logical": "f894", "page": "00" }, 20 | { "name": ".l0", "logical": "f897", "page": "00" }, 21 | { "name": ".shift", "logical": "f899", "page": "00" }, 22 | { "name": ".end", "logical": "f8a1", "page": "00"} 23 | ] -------------------------------------------------------------------------------- /examples/monster_puroresu/labels.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name": "soft_reset", "logical": "e001", "page": "00" }, 3 | { "name": "clear_zp_sp", "logical": "e029", "page": "00" }, 4 | { "name": ".mute_channels", "logical": "e033", "page": "00" }, 5 | { "name": ".loop", "logical": "e055", "page": "00" }, 6 | { "name": ".vblank", "logical": "e068", "page": "00" }, 7 | { "name": ".hblank", "logical": "e07d", "page": "00" }, 8 | { "name": ".next_joypad", "logical": "e4d5", "page": "00" }, 9 | { "name": ".read_joy_end", "logical": "e51d", "page": "00" } 10 | ] -------------------------------------------------------------------------------- /examples/monster_puroresu/monster.json: -------------------------------------------------------------------------------- 1 | { 2 | "irq_reset": { 3 | "filename": "startup.asm", 4 | "type": "code", 5 | "page": "0", 6 | "logical": "e000", 7 | "size": "58", 8 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 9 | }, 10 | 11 | "irq_1": { 12 | "filename": "startup.asm", 13 | "type": "code", 14 | "page": "0", 15 | "logical": "e058", 16 | "size": "55", 17 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 18 | }, 19 | 20 | "unknown0": { 21 | "filename": "startup.asm", 22 | "type": "code", 23 | "page": "0", 24 | "logical": "e138", 25 | "size": "1d", 26 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 27 | }, 28 | 29 | "update_satb": { 30 | "filename": "startup.asm", 31 | "type": "code", 32 | "page": "0", 33 | "logical": "e0cc", 34 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 35 | }, 36 | 37 | "set_vdc_ctrl": { 38 | "filename": "startup.asm", 39 | "type": "code", 40 | "page": "0", 41 | "logical": "e4b5", 42 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 43 | }, 44 | 45 | "update_scroll": { 46 | "filename": "startup.asm", 47 | "type": "code", 48 | "page": "0", 49 | "logical": "e0ad", 50 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 51 | }, 52 | 53 | "read_joy": { 54 | "filename": "startup.asm", 55 | "type": "code", 56 | "page": "0", 57 | "logical": "e4ca", 58 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 59 | }, 60 | 61 | "update_sound": { 62 | "filename": "startup.asm", 63 | "type": "code", 64 | "page": "0", 65 | "logical": "fbc2", 66 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 67 | }, 68 | 69 | "update_channel": { 70 | "filename": "startup.asm", 71 | "type": "code", 72 | "page": "0", 73 | "logical": "fcac", 74 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 75 | }, 76 | 77 | "unknown7": { 78 | "filename": "startup.asm", 79 | "type": "code", 80 | "page": "0", 81 | "logical": "fd36", 82 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 83 | }, 84 | 85 | "unknown8": { 86 | "filename": "page2.asm", 87 | "type": "code", 88 | "page": "2", 89 | "logical": "a0b6", 90 | "size": "27", 91 | "mpr": ["ff", "f8", 0, 0, 0, 2, 0, 0 ] 92 | }, 93 | 94 | "irq_dummy": { 95 | "filename": "startup.asm", 96 | "type": "code", 97 | "page": "0", 98 | "logical": "fff0", 99 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 100 | }, 101 | 102 | "irq_vectors": { 103 | "filename": "startup.asm", 104 | "type": "data", 105 | "page": "0", 106 | "logical": "fff6", 107 | "size": "a", 108 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 109 | "data": { "type":"hex", "element_size": 2, "elements_per_line": 1 } 110 | } 111 | } -------------------------------------------------------------------------------- /examples/sf2/joypad.json: -------------------------------------------------------------------------------- 1 | { 2 | "joydetect": { 3 | "filename": "joypad.asm", 4 | "type": "code", 5 | "logical": "6c80", 6 | "page": "15", 7 | "size": "f4", 8 | "mpr": ["ff","f8","38","15","3c","3a","04","00"] 9 | }, 10 | "joyread": { 11 | "filename": "joypad.asm", 12 | "type": "code", 13 | "logical": "7d98", 14 | "page": "0d", 15 | "size": "f1", 16 | "mpr": ["ff","f8","38","0d","40","3a","04","00"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/sf2/labels.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name":"joyread", "logical":"7d98", "page":"0d" }, 3 | { "name":"first_scan", "logical":"7da3", "page":"0d" }, 4 | { "name":"second_scan", "logical":"7dde", "page":"0d" }, 5 | { "name":"detect_6btn", "logical":"7e0f", "page":"0d" }, 6 | { "name":"is_6btn", "logical":"7e3b", "page":"0d" }, 7 | { "name":"not_6btn", "logical":"7e40", "page":"0d" }, 8 | { "name":"trg_6btn", "logical":"7e2b", "page":"0d" }, 9 | { "name":"trg_2btn", "logical":"7e44", "page":"0d" }, 10 | { "name":"check_soft_reset", "logical":"7e59", "page":"0d" }, 11 | { "name":"check_sel_run", "logical":"7e72", "page":"0d" }, 12 | { "name":"next_pad", "logical":"7e80", "page":"0d" }, 13 | { "name":"soft_reset", "logical":"7e86", "page":"0d" }, 14 | { "name":"joypad", "logical":"2c74", "page":"f8" }, 15 | { "name":"joyold", "logical":"2c7a", "page":"f8" }, 16 | { "name":"joytrg", "logical":"2c80", "page":"f8" }, 17 | { "name":"joypad_6", "logical":"2c77", "page":"f8" }, 18 | { "name":"joyold_6", "logical":"2c7d", "page":"f8" }, 19 | { "name":"joytrg_6", "logical":"2c83", "page":"f8" }, 20 | { "name":"joyport", "logical":"1000", "page":"ff" } 21 | ] 22 | -------------------------------------------------------------------------------- /examples/syscard/bank0.json: -------------------------------------------------------------------------------- 1 | { 2 | "cdbios_functions": { 3 | "filename": "syscard.asm", 4 | "type": "code", 5 | "page": "0", 6 | "logical" : "e000", 7 | "size": "505", 8 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 9 | }, 10 | 11 | "unknown.0": { 12 | "filename": "syscard.asm", 13 | "type": "data", 14 | "page": "0", 15 | "logical" : "e504", 16 | "size": "5", 17 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 18 | "data": { "type": "hex", "element_size": 1, "elements_per_line": 32 } 19 | }, 20 | 21 | "ex_colorcmd.impl": { 22 | "filename": "syscard.asm", 23 | "type": "code", 24 | "page": "0", 25 | "logical" : "e509", 26 | "size": "ce", 27 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 28 | }, 29 | 30 | "unknown.1": { 31 | "filename": "syscard.asm", 32 | "type": "data", 33 | "page": "0", 34 | "logical" : "e5d7", 35 | "size": "3", 36 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 37 | "data": { "type": "hex", "element_size": 1, "elements_per_line": 32 } 38 | }, 39 | 40 | "ex_satclr.impl": { 41 | "filename": "syscard.asm", 42 | "type": "code", 43 | "page": "0", 44 | "logical" : "e5da", 45 | "size": "26", 46 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 47 | }, 48 | 49 | "unknown.2": { 50 | "filename": "syscard.asm", 51 | "type": "data", 52 | "page": "0", 53 | "logical" : "f8a9", 54 | "size": "f", 55 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 56 | "data": { "type": "hex", "element_size": 1, "elements_per_line": 32 } 57 | }, 58 | 59 | "bm_free.impl": { 60 | "filename": "syscard.asm", 61 | "type": "code", 62 | "page": "0", 63 | "logical" : "f8b8", 64 | "size": "575", 65 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 66 | }, 67 | 68 | "grp_bios.impl": { 69 | "filename": "syscard.asm", 70 | "type": "code", 71 | "page": "0", 72 | "logical" : "fe57", 73 | "size": "18", 74 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 75 | }, 76 | 77 | "jump_table.0": { 78 | "filename": "syscard.asm", 79 | "type": "data", 80 | "page": "0", 81 | "logical" : "fe2d", 82 | "size": "2a", 83 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 84 | "data": { "type": "hex", "element_size": 2, "elements_per_line": 1 } 85 | }, 86 | 87 | "jump_table.1": { 88 | "filename": "syscard.asm", 89 | "type": "data", 90 | "page": "0", 91 | "logical" : "fe70", 92 | "size": "22", 93 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 94 | "data": { "type": "hex", "element_size": 2, "elements_per_line": 1 } 95 | }, 96 | 97 | "ex_memopen.impl": { 98 | "filename": "syscard.asm", 99 | "type": "code", 100 | "page": "0", 101 | "logical" : "fe92", 102 | "size": "30", 103 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 104 | }, 105 | 106 | "unknown.3": { 107 | "filename": "syscard.asm", 108 | "type": "data", 109 | "page": "0", 110 | "logical" : "fec2", 111 | "size": "134", 112 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 113 | "data": { "type": "hex", "element_size": 1, "elements_per_line": 32 } 114 | }, 115 | 116 | "irq_vectors": { 117 | "filename": "syscard.asm", 118 | "type": "data", 119 | "page": "0", 120 | "logical": "fff6", 121 | "size": "a", 122 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 123 | "data": { "type": "hex", "element_size": 2, "elements_per_line": 1 } 124 | } 125 | } -------------------------------------------------------------------------------- /examples/syscard/syscard.inc: -------------------------------------------------------------------------------- 1 | video_reg_l = $0000 2 | video_reg_h = $0001 3 | video_data_l = $0002 4 | video_data_h = $0003 5 | color_ctrl = $0400 6 | color_reg_l = $0402 7 | color_reg_h = $0403 8 | color_data_l = $0404 9 | color_data_h = $0405 10 | psg_ch = $0800 11 | psg_mainvol = $0801 12 | psg_freq.lo = $0802 13 | psg_freq.hi = $0803 14 | psg_ctrl = $0804 15 | psg_pan = $0805 16 | psg_wavebuf = $0806 17 | psg_noise = $0807 18 | psg_lfoctrl = $0809 19 | psg_lfofreq = $0808 20 | timer_cnt = $0C00 21 | timer_ctrl = $0C01 22 | joyport = $1000 23 | irqport = $1400 24 | irq_disable = $1402 25 | irq_status = $1403 26 | cd_port = $1800 27 | bram_lock = $1803 28 | bram_unlock = $1807 29 | vi_bitpat = $20dc 30 | vi_rvbitpat = $20dd 31 | vi_padrs = $20de 32 | 33 | vi_porg = $20e0 34 | vi_ft_back = $20e1 35 | 36 | vi_stack = $20e4 37 | 38 | time_sw = $20e6 39 | main_sw = $20e7 40 | si = $20e8 41 | 42 | r0 = $20ea 43 | 44 | zl0 = $20ec 45 | zh0 = $20ed 46 | zl1 = $20ee 47 | zh1 = $20ef 48 | zl2 = $20f0 49 | zh2 = $20f1 50 | cdi_b = $20f2 51 | crl_m = $20f3 52 | crh_m = $20f4 53 | irq_m = $20f5 54 | str_b = $20f6 55 | reg_box = $20f7 56 | _al = $20f8 57 | _ah = $20f9 58 | _bl = $20fa 59 | _bh = $20fb 60 | _cl = $20fc 61 | _ch = $20fd 62 | _dl = $20fe 63 | _dh = $20ff 64 | irq2_jmp = $2200 65 | 66 | irq_jmp = $2202 67 | 68 | tim_jmp = $2204 69 | 70 | nmi_jmp = $2206 71 | 72 | sync_jmp = $2208 73 | 74 | rcr_jmp = $220a 75 | 76 | bgx1 = $220c 77 | 78 | bgx2 = $220e 79 | 80 | bgy1 = $2210 81 | 82 | bgy2 = $2212 83 | 84 | sat_addr = $2214 85 | 86 | spr_ptr = $2216 87 | spr_yl = $2217 88 | spr_yh = $2218 89 | spr_xl = $2219 90 | spr_xh = $221a 91 | spr_nl = $221b 92 | spr_nh = $221c 93 | spr_al = $221d 94 | spr_ah = $221e 95 | color_cmd = $221f 96 | bgc_ptr = $2220 97 | 98 | bgc_len = $2222 99 | sprc_ptr = $2223 100 | 101 | sprc_len = $2225 102 | joykeyflg = $2226 103 | joyena = $2227 104 | joy = $2228 105 | joytrg = $222d 106 | joyold = $2232 107 | irq_cnt = $2241 108 | notrdyflg = $2247 109 | rndl = $2249 110 | rndh = $224a 111 | rndm = $224b 112 | tnomin = $226a 113 | outmin = $226c 114 | outsec = $226d 115 | outfrm = $226e 116 | vdtin_flg = $2272 117 | recbase0_h = $2274 118 | recbase0_m = $2275 119 | recbase0_l = $2276 120 | recbase1_h = $2277 121 | recbase1_m = $2278 122 | recbase1_l = $2279 123 | scsists = $227b 124 | suberrc = $227c 125 | sibcode = $227e 126 | psg_work_top = $22d0 127 | graph_work_top = $2616 128 | key_work_top = $2649 129 | user_work_top = $267f 130 | -------------------------------------------------------------------------------- /examples/tadaima/README.md: -------------------------------------------------------------------------------- 1 | # Memory base 128 detection routine 2 | 3 | ## Command 4 | ```bash 5 | ./etripator --cd -l labels.json mb128.json Track02.iso 6 | ``` 7 | 8 | ## Console 9 | ``` 10 | mb128_detect 11 | 782a long jump to 7770 (82) 12 | 782e long jump to 7754 (82) 13 | 783c long jump to 7754 (82) 14 | 7848 short jump to 784f (82) 15 | 784d short jump to 785c (82) 16 | 7852 short jump to 7858 (82) 17 | 7854 short jump to 7828 (82) 18 | 7856 short jump to 785c (82) 19 | 785e long jump to 7754 (82) 20 | ``` 21 | 22 | ## Output 23 | ``` 24 | .code 25 | .bank 82 26 | .org $7826 27 | mb128_detect: 28 | phx 29 | clx 30 | mb128_detect.loop: 31 | lda #$a8 32 | jsr mb128_write_byte 33 | cla 34 | jsr mb128_write_bit 35 | lda $1000 36 | asl A 37 | asl A 38 | asl A 39 | asl A 40 | sta <$fe 41 | lda #$01 42 | jsr mb128_write_bit 43 | lda $1000 44 | and #$0f 45 | ora <$fe 46 | cmp #$04 47 | bne mb128_detect.retry 48 | cla 49 | plx 50 | rts 51 | bra mb128_detect.bit0 52 | mb128_detect.retry: 53 | inx 54 | cpx #$03 55 | bcs mb128_detect.failed 56 | bra mb128_detect.loop 57 | bra mb128_detect.bit0 58 | mb128_detect.failed: 59 | lda #$ff 60 | plx 61 | rts 62 | mb128_detect.bit0: 63 | pha 64 | cla 65 | jsr mb128_write_bit 66 | pla 67 | rts 68 | ``` 69 | -------------------------------------------------------------------------------- /examples/tadaima/labels.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name": "mb128_write_bit", "logical": "7754", "page": "82" }, 3 | { "name": "mb128_write_byte", "logical": "7770", "page": "82" }, 4 | { "name": "mb128_detect.loop", "logical": "7828", "page": "82" }, 5 | { "name": "mb128_detect.retry", "logical": "784f", "page": "82" }, 6 | { "name": "mb128_detect.failed", "logical": "7858", "page": "82" }, 7 | { "name": "mb128_detect.bit0", "logical": "785c", "page": "82" } 8 | ] 9 | -------------------------------------------------------------------------------- /examples/tadaima/mb128.json: -------------------------------------------------------------------------------- 1 | { 2 | "mb128_detect": { 3 | "filename": "mb128.asm", 4 | "type": "code", 5 | "page": "82", 6 | "logical" : "76e4", 7 | "offset": "4ee4", 8 | "size": "330", 9 | "mpr": ["ff", "f8", 0, "82", 0, 0, 0, 0 ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/youkai_douchuuki/comments.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"logical":"d6a1" , "page":"01f", "text":"compute vram address"}, 3 | {"logical":"d6b4" , "page":"01f", "text":"set VRAM write address"}, 4 | {"logical":"d6bc" , "page":"01f", "text":"set VRAM read address"}, 5 | {"logical":"d736" , "page":"01f", "text":"set source pointer"}, 6 | {"logical":"d73c" , "page":"01f", "text":"check if we reached of password list"}, 7 | {"logical":"d73f" , "page":"01f", "text":"compare with input"}, 8 | {"logical":"d757" , "page":"01f", "text":"move pointer to the next password"}, 9 | 10 | {"logical":"d76c" , "page":"01f", "text":"backup source pointer"}, 11 | 12 | {"logical" : "d750", "page": "1f", "text": "find end of string"} 13 | ] -------------------------------------------------------------------------------- /examples/youkai_douchuuki/labels.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name": "password.str", "logical": "31dc", "page": "f8" }, 3 | { "name": "password.len", "logical": "31f6", "page": "f8" }, 4 | 5 | { "name": "@loop", "logical" : "d738", "page": "1f"}, 6 | { "name": "@search", "logical" : "d73f", "page": "1f"}, 7 | { "name": "@next", "logical" : "d74e", "page": "1f"}, 8 | { "name": "@eos", "logical" : "d750", "page": "1f"}, 9 | { "name": "@end", "logical" : "d765", "page": "1f"}, 10 | 11 | { "name": "password.store", "logical" : "d6f7", "page": "1f", 12 | "description": [ 13 | "-----------------------------------------------------------------", 14 | "store password", 15 | "-----------------------------------------------------------------" 16 | ] 17 | } 18 | ] 19 | -------------------------------------------------------------------------------- /examples/youkai_douchuuki/password.json: -------------------------------------------------------------------------------- 1 | { 2 | "password.vram.addr": { 3 | "filename": "password.asm", 4 | "type": "code", 5 | "page": "1f", 6 | "logical" : "d6a1", 7 | "mpr": ["ff", "f8", "1b", "1c", "1d", "1e", "1f", 0 ], 8 | "description": [ 9 | "-----------------------------------------------------------------", 10 | "set VRAM write and read addresses", 11 | "-----------------------------------------------------------------" 12 | ] 13 | }, 14 | "ld6c8": { 15 | "filename": "password.asm", 16 | "type": "code", 17 | "page": "1f", 18 | "logical" : "d6c8", 19 | "mpr": ["ff", "f8", "1b", "1c", "1d", "1e", "1f", 0 ] 20 | }, 21 | "password.store.end": { 22 | "filename": "password.asm", 23 | "type": "code", 24 | "page": "1f", 25 | "logical" : "d6f6", 26 | "size": "3a", 27 | "mpr": ["ff", "f8", "1b", "1c", "1d", "1e", "1f", 0 ] 28 | }, 29 | "ld766": { 30 | "filename": "password.asm", 31 | "type": "code", 32 | "page": "1f", 33 | "logical" : "d766", 34 | "size": "0f", 35 | "mpr": ["ff", "f8", "1b", "1c", "1d", "1e", "1f", 0 ] 36 | }, 37 | "password.encode": { 38 | "filename": "password.asm", 39 | "type": "code", 40 | "page": "1f", 41 | "logical" : "d853", 42 | "size": "93", 43 | "mpr": ["ff", "f8", "1b", "1c", "1d", "1e", "1f", 0 ], 44 | "description": [ 45 | "-----------------------------------------------------------------", 46 | "encode password", 47 | "Have fun decoding them...", 48 | "-----------------------------------------------------------------" 49 | ] 50 | }, 51 | "password.check": { 52 | "filename": "password.asm", 53 | "type": "code", 54 | "page": "1f", 55 | "logical" : "d730", 56 | "size": "36", 57 | "mpr": ["ff", "f8", "1b", "1c", "1d", "1e", "1f", 0 ], 58 | "description": [ 59 | "-----------------------------------------------------------------", 60 | "check password", 61 | "-----------------------------------------------------------------" 62 | ] 63 | }, 64 | "passwords": { 65 | "filename": "password.asm", 66 | "type": "data", 67 | "page": "1f", 68 | "logical": "d198", 69 | "size": "3de", 70 | "mpr": ["ff", "f8", "1b", "1c", "1d", "1e", "1f", 0 ], 71 | "data": { "type":"hex", "element_size": 1, "elements_per_line": 8 }, 72 | "description": [ 73 | "-----------------------------------------------------------------", 74 | "passwords", 75 | "", 76 | "Only the first 8 bytes of the password string are checked.", 77 | "Note that the strings can be longer. They are separated by $2a.", 78 | "The password list ends with $00.", 79 | "-----------------------------------------------------------------" 80 | ] 81 | } 82 | } -------------------------------------------------------------------------------- /externals/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(argparse STATIC argparse/argparse.c argparse/argparse.h) 2 | 3 | add_subdirectory(cwalk) 4 | 5 | add_library(munit STATIC ${CMAKE_CURRENT_LIST_DIR}/munit/munit.c) 6 | target_include_directories(munit PUBLIC $) 7 | set_property(TARGET munit PROPERTY INTERFACE_INCLUDE_DIRECTORIES $) 8 | 9 | add_subdirectory(fff) 10 | -------------------------------------------------------------------------------- /ipl.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef IPL_H 37 | #define IPL_H 38 | 39 | #include "config.h" 40 | #include "section.h" 41 | 42 | /// IPL Information block data format 43 | typedef struct { 44 | /// IPLBLK - load start record no. of CD (3 bytes high/medium/low) 45 | /// this is where the program is stored. 46 | uint8_t load_start_record[3]; 47 | /// IPLBLN - load block length of CD (1 byte) 48 | /// number of sectors to read. 49 | uint8_t load_sector_count; 50 | /// IPLSTA - program load address (2 bytes low/high) 51 | /// main memory address for program read. 52 | uint8_t load_store_address[2]; 53 | /// IPLJMP - program execute address (2 bytes low/high) 54 | /// starting address of execution after program read. 55 | uint8_t load_exec_address[2]; 56 | /// IPLMPR - ipl set mpr2-6 (5 bytes) 57 | uint8_t mpr[5]; 58 | /// OPENMODE - opening mode 59 | /// bit 0: data read to vram (0: not read, 1: read) 60 | /// bit 1: data read to adpcm buffer (0: not read, 1: read) 61 | /// bit 5: bg display (0: display on, 1: display off) 62 | /// bit 6: adpcm play (0: play, 1: not play) 63 | /// bit 7: adpcm play mode (0: single, 1: repeat) 64 | uint8_t opening_mode; 65 | /// GRPBLK - opening graphic data record no. (3 bytes high/medium/low) 66 | uint8_t opening_gfx_record[3]; 67 | /// GRPBLN - opening graphic data length (1 byte) 68 | uint8_t opening_gfx_sector_count; 69 | /// GRPADR - opening graphic data read address (2 bytes low/high) 70 | uint8_t opening_gfx_read_address[2]; 71 | /// ADPBLK - opening ADPCM data record no. (3 bytes high/medium/low) 72 | uint8_t opening_adpcm_record[3]; 73 | /// ADPBLN - opening ADPCM data length (1 byte) 74 | uint8_t opening_adpcm_sector_count; 75 | /// ADPRATE - opening ADPCM sampling rate (1 byte) 76 | uint8_t opening_adpcm_sampling_rate; 77 | /// RESERVED (7 bytes) 78 | uint8_t reserved[7]; 79 | /// ID STR - "PC Engine CD-ROM SYSTEM", 0 80 | uint8_t id[24]; 81 | /// LEGAL - "Copyright HUDSON SOFT / NEC Home Electronics, Ltd.", 0 82 | uint8_t legal[50]; 83 | /// PROGRAM NAME - program name (16 bytes) 84 | uint8_t program_name[16]; 85 | /// EXTRA - (6 bytes) 86 | uint8_t extra[6]; 87 | } IPL; 88 | /* [todo] 89 | IPL graphic block 90 | color palette - 1 record 91 | BAT data - 1 record 92 | BG font data - GRPBLN - 2 records 93 | */ 94 | 95 | /// Display IPL infos. 96 | /// \param [in] in IPL infos. 97 | void ipl_print(IPL *in); 98 | 99 | /// Read IPL data from file. 100 | /// \param [out] out IPL infos. 101 | /// \param [in] filename Input filename. 102 | /// \return 0 on error, 1 otherwise. 103 | bool ipl_read(IPL *out, const char *filename); 104 | 105 | /// Get irq code offsets from IPL. 106 | /// \param [in] in IPL infos. 107 | /// \param [out] out Sections. 108 | /// \return 0 on error, 1 otherwise. 109 | bool ipl_sections(IPL *in, SectionArray *out); 110 | 111 | #endif // IPL_H 112 | -------------------------------------------------------------------------------- /irq.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "irq.h" 37 | #include "message.h" 38 | 39 | #define PCE_IRQ_TABLE 0xFFF6U 40 | #define PCE_IRQ_COUNT 5 41 | 42 | static char* g_irq_names[PCE_IRQ_COUNT] = { 43 | "irq_2", 44 | "irq_1", 45 | "irq_timer", 46 | "irq_nmi", 47 | "irq_reset" 48 | }; 49 | 50 | // Get irq code offsets from rom. 51 | bool irq_read(MemoryMap* map, SectionArray *out) { 52 | assert(map != NULL); 53 | assert(out != NULL); 54 | 55 | bool ret = false; 56 | if(map->memory[PCE_MEMORY_ROM].data == NULL) { 57 | ERROR_MSG("No ROM in memory map."); 58 | } else if(map->memory[PCE_MEMORY_ROM].length < (PCE_IRQ_TABLE + PCE_IRQ_COUNT)) { 59 | ERROR_MSG("ROM is abnormally small."); 60 | } else { 61 | uint16_t offset = PCE_IRQ_TABLE; 62 | map->mpr[7] = 0; 63 | 64 | ret = true; 65 | 66 | for(size_t i=0; ret && (i ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_IRQ_H 37 | #define ETRIPATOR_IRQ_H 38 | 39 | #include "config.h" 40 | #include "memory_map.h" 41 | #include "section.h" 42 | 43 | /// Get irq code offsets from rom. 44 | /// \param [in] map Memory map. 45 | /// \param [out] out Section list. 46 | /// \return true if the IRQ vectors where successfully extradcted. 47 | /// \return false otherwise (missing ROM, or offsets out of range). 48 | bool irq_read(MemoryMap* map, SectionArray *out); 49 | 50 | #endif // ETRIPATOR_IRQ_H 51 | -------------------------------------------------------------------------------- /jsonhelpers.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "jsonhelpers.h" 37 | 38 | #include 39 | #include 40 | 41 | bool json_validate_int(const json_t* obj, int* out) { 42 | assert(obj != NULL); 43 | assert(out != NULL); 44 | bool ret = false; 45 | if(json_is_string(obj)) { 46 | const char *str = json_string_value(obj); 47 | for(; (*str!='\0') && isspace(*str); str++) { 48 | } 49 | if(*str=='$') { 50 | str++; 51 | } 52 | errno = 0; 53 | *out = strtoul(str, NULL, 16); 54 | if(errno == 0) { 55 | ret = true; 56 | } 57 | } else if(json_is_integer(obj)) { 58 | *out = (int)json_integer_value(obj); 59 | ret = true; 60 | } 61 | return ret; 62 | } 63 | 64 | bool json_load_description(const json_t* obj, const char *key, char **out) { 65 | assert(out != NULL); 66 | assert(out && (*out == NULL)); 67 | 68 | bool ret = false; 69 | char *buffer = NULL; 70 | json_t *tmp = json_object_get(obj, key); 71 | 72 | if(tmp == NULL) { 73 | ret = true; 74 | } else { 75 | if(json_is_string(tmp)) { 76 | buffer = strdup(json_string_value(tmp)); 77 | } else if (json_is_array(tmp)) { 78 | int index; 79 | json_t* value; 80 | size_t len = 0; 81 | json_array_foreach(tmp, index, value) { 82 | if(json_is_string(value)) { 83 | const char *str = json_string_value(value); 84 | if(buffer != NULL) { 85 | buffer[len-1] = '\n'; 86 | } 87 | size_t n = len + strlen(str) + 1; 88 | char *ptr = realloc(buffer, n); 89 | if(ptr == NULL) { 90 | free(buffer); 91 | buffer = NULL; 92 | break; 93 | } 94 | memcpy(ptr+len, str, strlen(str)); 95 | ptr[n-1] = '\0'; 96 | buffer = ptr; 97 | len = n; 98 | } 99 | } 100 | } 101 | ret = (buffer != NULL); 102 | } 103 | *out = buffer; 104 | return ret; 105 | } 106 | 107 | void json_print_description(FILE *out, const char *key, const char *str) { 108 | assert(out != NULL); 109 | assert(key != NULL); 110 | assert(str != NULL); 111 | fprintf(out, "\"%s\":[", key); 112 | while(*str) { 113 | fprintf(out, "\n\t\t\t\""); 114 | for(;*str && (*str != '\n'); str++) { 115 | fputc(*str, out); 116 | } 117 | fprintf(out, "\"%c", *str ? ',' : ' '); 118 | if(*str) str++; 119 | } 120 | fprintf(out, "\n\t]"); 121 | } 122 | -------------------------------------------------------------------------------- /jsonhelpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_JSON_HELPERS_H 37 | #define ETRIPATOR_JSON_HELPERS_H 38 | 39 | #include "config.h" 40 | 41 | #include 42 | 43 | bool json_validate_int(const json_t* obj, int* out); 44 | bool json_load_description(const json_t* obj, const char *key, char **out); 45 | void json_print_description(FILE *out, const char *key, const char *str); 46 | 47 | #endif // ETRIPATOR_JSON_HELPERS_H -------------------------------------------------------------------------------- /label.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "label.h" 37 | #include "message.h" 38 | 39 | #include 40 | 41 | #define LABEL_ARRAY_INC 16 42 | 43 | /// Get label index by its address. 44 | /// \param [in] repository Label repository. 45 | /// \param [in] logical Logical address. 46 | /// \param [in] page Memory page. 47 | /// \return label index. 48 | /// \return -1 if the label was not found. 49 | static int label_repository_index(LabelRepository *repository, uint16_t logical, uint8_t page) { 50 | size_t i; 51 | for(i=0; ilast; i++) { 52 | if( (repository->labels[i].page == page) && 53 | (repository->labels[i].logical == logical) ) { 54 | return (int)i; 55 | } 56 | } 57 | return -1; 58 | } 59 | 60 | // Create label repository. 61 | bool label_repository_create(LabelRepository* repository) { 62 | assert(repository != NULL); 63 | bool ret = true; 64 | repository->last = 0; 65 | repository->labels = NULL; 66 | repository->size = LABEL_ARRAY_INC; 67 | repository->labels = (Label*)malloc(repository->size * sizeof(Label)); 68 | if(repository->labels == NULL) { 69 | ERROR_MSG("Failed to create label: %s", strerror(errno)); 70 | label_repository_destroy(repository); 71 | ret = false; 72 | } 73 | return ret; 74 | } 75 | 76 | // Delete label repository. 77 | void label_repository_destroy(LabelRepository* repository) { 78 | repository->size = 0; 79 | repository->last = 0; 80 | 81 | if(repository->labels != NULL) { 82 | for(size_t i=0; ilast; i++) { 83 | free(repository->labels[i].name); 84 | free(repository->labels[i].description); 85 | } 86 | free(repository->labels); 87 | repository->labels = NULL; 88 | } 89 | } 90 | 91 | // Add label to repository. 92 | bool label_repository_add(LabelRepository* repository, const char* name, uint16_t logical, uint8_t page, const char *description) { 93 | assert(repository != NULL); 94 | bool ret = true; 95 | int index = label_repository_index(repository, logical, page); 96 | if(index >= 0) { 97 | #if 0 98 | if(strcmp(name, repository->labels[index].name)) { 99 | // return 0; 100 | } 101 | #endif 102 | if(description && !repository->labels[index].description) { 103 | repository->labels[index].description = strdup(description); 104 | } 105 | } else { 106 | /* Expand arrays if necessary */ 107 | if(repository->last >= repository->size) { 108 | Label *ptr; 109 | repository->size += LABEL_ARRAY_INC; 110 | ptr = (Label*)realloc(repository->labels, repository->size * sizeof(Label)); 111 | if(ptr == NULL) { 112 | label_repository_destroy(repository); 113 | ret = false; 114 | } else { 115 | repository->labels = ptr; 116 | } 117 | } 118 | if(ret != 0) { 119 | /* Push addresses */ 120 | repository->labels[repository->last].logical = logical; 121 | repository->labels[repository->last].page = page; 122 | 123 | /* Push name and description */ 124 | repository->labels[repository->last].name = strdup(name); 125 | repository->labels[repository->last].description = (description != NULL) ? strdup(description) : NULL; 126 | 127 | ++repository->last; 128 | } 129 | } 130 | return ret; 131 | } 132 | 133 | // Find a label by its address. 134 | bool label_repository_find(LabelRepository* repository, uint16_t logical, uint8_t page, Label *out) { 135 | int index = label_repository_index(repository, logical, page); 136 | bool ret = (index >= 0); 137 | if(ret) { 138 | memcpy(out, &repository->labels[index], sizeof(Label)); 139 | } else { 140 | memset(out, 0, sizeof(Label)); 141 | } 142 | return ret; 143 | } 144 | 145 | // Get the number of labels stored in the repository. 146 | int label_repository_size(LabelRepository* repository) { 147 | assert(repository != NULL); 148 | return (int)repository->last; 149 | } 150 | 151 | // Retrieve the label at the specified index. 152 | bool label_repository_get(LabelRepository* repository, int index, Label *out) { 153 | bool ret = false; 154 | if((repository != NULL) && ((index >= 0) && (index < (int)repository->last))) { 155 | ret = true; 156 | memcpy(out, &repository->labels[index], sizeof(Label)); 157 | } else { 158 | memset(out, 0, sizeof(Label)); 159 | } 160 | return ret; 161 | } 162 | 163 | // Delete labels. 164 | void label_repository_delete(LabelRepository* repository, uint16_t first, uint16_t end, uint8_t page) { 165 | size_t i; 166 | for(i=0; ilast; i++) { 167 | if( (repository->labels[i].page == page) && 168 | (repository->labels[i].logical >= first) && 169 | (repository->labels[i].logical < end) ) { 170 | if(repository->last) { 171 | repository->last--; 172 | if(repository->labels[i].name) { 173 | free(repository->labels[i].name); 174 | } 175 | if(repository->labels[i].description) { 176 | free(repository->labels[i].description); 177 | } 178 | memcpy(&repository->labels[i], &repository->labels[repository->last], sizeof(Label)); 179 | i--; 180 | } 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /label.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_LABEL_H 37 | #define ETRIPATOR_LABEL_H 38 | 39 | #include "config.h" 40 | 41 | /// Label. 42 | typedef struct { 43 | char* name; //< Offset in the repository name buffer 44 | uint16_t logical; //< Logical address 45 | uint8_t page; //< Memory page 46 | char* description; //< Description (optional) 47 | } Label; 48 | 49 | /// Label repository. 50 | typedef struct { 51 | size_t size; //< Size of label repository. 52 | size_t last; //< Last element in the repository. 53 | Label *labels; //< Labels. 54 | } LabelRepository; 55 | 56 | /// Create label repository. 57 | /// \param [in out] repository Label repository. 58 | /// \return true if the repository was succesfully initialized 59 | /// \return false if an error occured 60 | bool label_repository_create(LabelRepository* repository); 61 | 62 | /// Release label repository resources. 63 | /// \param [in,out] repository Label repository. 64 | void label_repository_destroy(LabelRepository* repository); 65 | 66 | /// Add label (or inline description) to repository. 67 | /// \param [in,out] repository Label repository. 68 | /// \param [in] name Name. If the name is NULL, then this label is an inline description. 69 | /// \param [in] logical Logical address. 70 | /// \param [in] page Memory page. 71 | /// \param [in] description Description (optional if name is set, mandatory otherwise). 72 | /// \return true if the entry was successfully added to the repository. 73 | /// \return false if an error occured. 74 | bool label_repository_add(LabelRepository* repository, const char* name, uint16_t logical, uint8_t page, const char *description); 75 | 76 | /// Find a label by its address. 77 | /// \param [in] repository Label repository. 78 | /// \param [in] logical Logical address. 79 | /// \param [in] page Memory page. 80 | /// \param [out] out Associated label (if any). 81 | /// \return true if a label was found. 82 | /// \return 0 otherwise. 83 | bool label_repository_find(LabelRepository* repository, uint16_t logical, uint8_t page, Label *out); 84 | 85 | /// Get the number of labels stored in the repository. 86 | /// \param [in] repository Label repository. 87 | /// \return Label count. 88 | int label_repository_size(LabelRepository* repository); 89 | 90 | /// Retrieve the label at the specified index. 91 | /// \param [in] repository Label repository. 92 | /// \param [in] index Label index. 93 | /// \param [out] out Label (if any).& 94 | /// \return true if a label exists for the specified index. 95 | /// \return false otherwise. 96 | bool label_repository_get(LabelRepository* repository, int index, Label *out); 97 | 98 | /// Delete labels 99 | /// \param [in] repository Label repository. 100 | /// \param [in] first Start of the logical address range. 101 | /// \param [in] end End of the logical address range. 102 | /// \param [in] page Memory page. 103 | void label_repository_delete(LabelRepository* repository, uint16_t first, uint16_t end, uint8_t page); 104 | 105 | /// Load labels from file. 106 | /// \param [out] repository Label repository. 107 | /// \param [in] filename Input filename. 108 | /// \return true if the labels contained in the file was succesfully added to the repository. 109 | /// \return false if an error occured. 110 | bool label_repository_load(LabelRepository* repository, const char* filename); 111 | 112 | /// Save labels to file. 113 | /// \param [in] reposity Label repository. 114 | /// \param [in] filename Configuration file. 115 | /// \return true if the labels in the repository were succesfully written to the file. 116 | /// \return false if an error occured. 117 | bool label_repository_save(LabelRepository* repository, const char* filename); 118 | 119 | #endif // ETRIPATOR_LABEL_H 120 | -------------------------------------------------------------------------------- /label/load.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | #include "../message.h" 38 | #include "../jsonhelpers.h" 39 | #include "../label.h" 40 | 41 | #define MAX_LABEL_NAME 128 42 | 43 | // Load labels from file. 44 | bool label_repository_load(LabelRepository* repository, const char* filename) { 45 | assert(repository != NULL); 46 | assert(filename != NULL); 47 | 48 | bool ret = false; 49 | 50 | json_error_t err; 51 | json_t* root = json_load_file(filename, 0, &err); 52 | if(!root) { 53 | ERROR_MSG("Failed to parse %s:%d:%d: %s", filename, err.line, err.column, err.text); 54 | } else { 55 | json_t* value = NULL; 56 | int index = 0; 57 | if(!json_is_array(root)) { 58 | ERROR_MSG("Array expected."); 59 | } else for (index = 0, ret = true; ret && (index < json_array_size(root)) && (value = json_array_get(root, index)); index++) { 60 | ret = 0; 61 | if(!json_is_object(value)) { 62 | ERROR_MSG("Expected object."); 63 | } else { 64 | // name 65 | json_t* tmp = json_object_get(value, "name"); 66 | if (!json_is_string(tmp)) { 67 | ERROR_MSG("Missing or invalid label name."); 68 | } else { 69 | int num; 70 | const char* key = json_string_value(tmp); 71 | // logical 72 | tmp = json_object_get(value, "logical"); 73 | if(!json_validate_int(tmp, &num)) { 74 | ERROR_MSG("Invalid or missing logical address."); 75 | } else if((num < 0) || (num > 0xFFFF)) { 76 | ERROR_MSG("Logical address out of range."); 77 | } else { 78 | uint16_t logical = (uint16_t)num; 79 | // page 80 | tmp = json_object_get(value, "page"); 81 | if(!json_validate_int(tmp, &num)) { 82 | ERROR_MSG("Invalid or missing page."); 83 | } else { 84 | // description 85 | char* description = NULL; 86 | if(json_load_description(value, "description", &description) != true) { 87 | ERROR_MSG("Failed to load label description"); 88 | } else if((num < 0) || (num > 0xff)) { 89 | ERROR_MSG("Page value out of range."); 90 | } else if(label_repository_add(repository, key, logical, (uint8_t)num, description)) { 91 | ret = true; 92 | } 93 | free(description); 94 | } 95 | } 96 | } 97 | } 98 | } 99 | json_decref(root); 100 | } 101 | return ret; 102 | } 103 | -------------------------------------------------------------------------------- /label/save.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | #include 38 | 39 | #include "../message.h" 40 | #include "../jsonhelpers.h" 41 | #include "../label.h" 42 | 43 | // Save labels to file 44 | bool label_repository_save(LabelRepository* repository, const char* filename) { 45 | bool ret = false; 46 | FILE *stream = fopen(filename, "wb"); 47 | if(stream == NULL) { 48 | ERROR_MSG("Failed to open %s: %s", filename, strerror(errno)); 49 | } else { 50 | int count = label_repository_size(repository); 51 | 52 | fprintf(stream, "[\n"); 53 | for(int i=0; i ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "memory.h" 37 | #include "message.h" 38 | 39 | // Creates a new memory block. 40 | bool memory_create(Memory *memory, size_t length) { 41 | assert(memory != NULL); 42 | 43 | bool ret = false; 44 | if(length == 0) { 45 | ERROR_MSG("Invalid length"); 46 | } else { 47 | uint8_t *buffer = (uint8_t*)malloc(length); 48 | if(buffer == NULL) { 49 | ERROR_MSG("Unable to allocate %zu bytes: %s.", length, strerror(errno)); 50 | } else { 51 | memory->data = buffer; 52 | memory->length = length; 53 | ret = true; 54 | } 55 | } 56 | return ret; 57 | } 58 | 59 | // Releases memory block resources. 60 | void memory_destroy(Memory *memory) { 61 | assert(memory != NULL); 62 | free(memory->data); 63 | memory->data = NULL; 64 | memory->length = 0; 65 | } 66 | 67 | // Fills a memory block with a given byte value. 68 | bool memory_fill(Memory *memory, uint8_t c) { 69 | assert(memory != NULL); 70 | bool ret = false; 71 | if(memory->data != NULL) { 72 | const size_t n = memory->length; 73 | for(size_t i=0; idata[i] = c; 75 | } 76 | ret = true; 77 | } 78 | return ret; 79 | } 80 | -------------------------------------------------------------------------------- /memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_MEMORY_H 37 | #define ETRIPATOR_MEMORY_H 38 | 39 | #include "config.h" 40 | 41 | /// @defgroup Memory Memory block 42 | ///@{ 43 | 44 | /// Memory block. 45 | typedef struct { 46 | size_t length; ///< Byte array length. 47 | uint8_t *data; ///< Byte array. 48 | } Memory; 49 | 50 | /// Creates a new memory block. 51 | /// \param [out] memory Memory block. 52 | /// \param [in] length Memory block size (in bytes). 53 | /// \return true if the memory block was successfully created. 54 | /// \return false if an error occured. 55 | /// @note memory is left untouched if an error occured. 56 | bool memory_create(Memory *memory, size_t length); 57 | 58 | /// Releases memory block resources. 59 | /// \param [in out] mem Memory block. 60 | void memory_destroy(Memory *memory); 61 | 62 | /// Fills a memory block with a given byte value. 63 | /// \param [in out] mem Memory block. 64 | /// \param [in] c Byte value. 65 | /// \return true if the memory block was successfully filled. 66 | /// \return false if the memory block is invalid (0 size or unallocated). 67 | bool memory_fill(Memory *memory, uint8_t c); 68 | 69 | /// @} 70 | 71 | #endif // ETRIPATOR_MEMORY_H 72 | -------------------------------------------------------------------------------- /memory_map.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "memory_map.h" 37 | #include "message.h" 38 | 39 | // Resets memory map. 40 | static void memory_map_clear(MemoryMap *map) { 41 | for(unsigned int i=0; imemory[i].length = 0; 43 | map->memory[i].data = NULL; 44 | } 45 | for(unsigned int i=0; impr[i] = 0xFFU; 47 | } 48 | for(unsigned int i=0; ipage[i].id = PCE_MEMORY_NONE; 50 | map->page[i].bank = 0; 51 | } 52 | } 53 | 54 | // Initializes memory map. 55 | bool memory_map_init(MemoryMap *map) { 56 | bool ret = false; 57 | 58 | memory_map_clear(map); 59 | 60 | // Allocate main (or work) RAM. 61 | if(!memory_create(&map->memory[PCE_MEMORY_BASE_RAM], PCE_BANK_SIZE)) { 62 | ERROR_MSG("Failed to allocate main memory!"); 63 | } else { 64 | // Main RAM is mapped to pages 0xF8 to 0xFB (included). 65 | // Pages 0xF9 to 0xFB mirror page 0xF8. */ 66 | for(unsigned int i=0xf8; i<=0xfb; i++) { 67 | map->page[i].id = PCE_MEMORY_BASE_RAM; 68 | map->page[i].bank = 0; 69 | } 70 | 71 | // ROM and syscard RAM will be initialized later. 72 | ret = true; 73 | } 74 | return ret; 75 | } 76 | 77 | // Releases resources used by the memory map. 78 | void memory_map_destroy(MemoryMap *map) { 79 | assert(map != NULL); 80 | for(unsigned i=0; imemory[i]); 82 | } 83 | memory_map_clear(map); 84 | } 85 | 86 | // Get the memory page associated to a logical address. 87 | uint8_t memory_map_page(MemoryMap* map, uint16_t logical) { 88 | assert(map != NULL); 89 | uint8_t id = (logical >> 13) & 0x07U; 90 | return map->mpr[id]; 91 | } 92 | 93 | // Reads a single byte from memory. 94 | uint8_t memory_map_read(MemoryMap *map, size_t logical) { 95 | assert(map != NULL); 96 | const uint8_t id = memory_map_page(map, (uint16_t)logical); 97 | const Page *page = &map->page[id]; 98 | 99 | uint8_t ret = 0xFFU; 100 | if(page->id != PCE_MEMORY_NONE) { 101 | const size_t offset = (logical & 0x1FFFU) + (page->bank * PCE_BANK_SIZE); 102 | const Memory *mem = &map->memory[page->id]; 103 | if(offset < mem->length) { 104 | ret = mem->data[offset]; 105 | } 106 | } 107 | return ret; 108 | } 109 | 110 | // Update mprs. 111 | void memory_map_mpr(MemoryMap *map, const uint8_t mpr[PCE_MPR_COUNT]) { 112 | assert(map != NULL); 113 | for(unsigned int i=0; impr[i] = mpr[i]; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /memory_map.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_MEMORY_MAP_H 37 | #define ETRIPATOR_MEMORY_MAP_H 38 | 39 | #include "memory.h" 40 | 41 | /// PC Engine memory blocks. 42 | enum { 43 | PCE_MEMORY_NONE = -1, 44 | PCE_MEMORY_ROM = 0, 45 | PCE_MEMORY_BASE_RAM, 46 | PCE_MEMORY_CD_RAM, 47 | PCE_MEMORY_SYSCARD_RAM, 48 | PCE_MEMORY_COUNT 49 | }; 50 | 51 | #define PCE_PAGE_COUNT 0x100U 52 | 53 | #define PCE_MPR_COUNT 8U 54 | 55 | #define PCE_BANK_SIZE 8192U 56 | 57 | /// PC Engine memory page description. 58 | typedef struct { 59 | int id; // name the PCE_MEMORY_* enum ? 60 | size_t bank; 61 | } Page; 62 | 63 | /// PC Engine memory map. 64 | typedef struct { 65 | Memory memory[PCE_MEMORY_COUNT]; 66 | Page page[PCE_PAGE_COUNT]; 67 | uint8_t mpr[PCE_MPR_COUNT]; 68 | } MemoryMap; 69 | 70 | /// Initializes memory map. 71 | /// \param [in out] map Memory map. 72 | /// \return true if the memory map was succesfully initialized 73 | /// \return false if an error occured 74 | bool memory_map_init(MemoryMap *map); 75 | 76 | /// Releases resources used by the memory map. 77 | /// \param [in out] map Memory map. 78 | void memory_map_destroy(MemoryMap *map); 79 | 80 | /// Get the memory page associated to a logical address. 81 | /// \param [in] map Memory map. 82 | /// \param [in] logical Logical address. 83 | /// \return Memory page. 84 | uint8_t memory_map_page(MemoryMap* map, uint16_t logical); 85 | 86 | /// Reads a single byte from memory. 87 | /// \param [in] map Memory map. 88 | /// \param [in] logical Logical address. 89 | /// \return The value stored at the specified logical address. 90 | uint8_t memory_map_read(MemoryMap *map, size_t logical); 91 | 92 | /// Update the whole mprs list 93 | /// \param [in out] map Memory map. 94 | /// \param [in] mpr Memory page registers. 95 | void memory_map_mpr(MemoryMap *map, const uint8_t mpr[PCE_MPR_COUNT]); 96 | 97 | #endif // ETRIPATOR_MEMORY_MAP_H 98 | -------------------------------------------------------------------------------- /message.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "message.h" 37 | 38 | #include 39 | 40 | static MessagePrinter* g_message_printer_head = NULL; 41 | 42 | /* Setup global message printer list. */ 43 | void message_printer_init() { 44 | g_message_printer_head = NULL; 45 | // nothing much atm... 46 | } 47 | 48 | /* Releases the resources used by message printers. */ 49 | void message_printer_destroy() { 50 | for(MessagePrinter *it = g_message_printer_head; it != NULL; it = it->next) { 51 | if(it->close) { 52 | it->close(); 53 | } 54 | } 55 | g_message_printer_head = NULL; 56 | } 57 | 58 | /* Adds a new message printer to the global list. */ 59 | bool message_printer_add(MessagePrinter *printer) { 60 | bool ret = false; 61 | if((printer != NULL) && (printer->open != NULL)) { 62 | ret = printer->open(); 63 | if(ret) { 64 | printer->next = g_message_printer_head; 65 | g_message_printer_head = printer; 66 | } 67 | } 68 | return ret; 69 | } 70 | 71 | /* Dispatch messages to printers. */ 72 | void message_print(MessageType type, const char* file, size_t line, const char* function, const char* format, ...) { 73 | assert(file != NULL); 74 | assert(function != NULL); 75 | const char* filename; 76 | size_t length; 77 | cwk_path_get_basename(file, &filename, &length); 78 | if(filename == NULL) { 79 | filename = file; 80 | } 81 | for(MessagePrinter *it=g_message_printer_head; it != NULL; it = it->next) { 82 | if(it->output != NULL) { 83 | va_list args; 84 | va_start(args, format); 85 | (void)it->output(type, filename, line, function, format, args); 86 | va_end(args); 87 | } 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /message.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_MESSAGE_H 37 | #define ETRIPATOR_MESSAGE_H 38 | 39 | #include "config.h" 40 | 41 | /// @defgroup Message Message printing 42 | ///@{ 43 | 44 | // Message types. 45 | typedef enum { 46 | MESSAGE_TYPE_ERROR = 0, 47 | MESSAGE_TYPE_WARNING, 48 | MESSAGE_TYPE_INFO, 49 | MESSAGE_TYPE_DEBUG, 50 | MESSAGE_TYPE_COUNT, 51 | } MessageType; 52 | 53 | struct MessagePrinter; 54 | 55 | /// Initializes and allocates any resources necessary for the message printer. 56 | /// \return true if the message printer was successfully opened. 57 | /// \return false if an error occured. 58 | typedef bool (*MessagePrinterOpen)(); 59 | 60 | /// Releases resources used by the message printer. 61 | /// \return true if the resources used by the message printer were successfully released. 62 | /// \return false if an error occured. 63 | typedef bool (*MessagePrinterClose)(); 64 | 65 | /// \brief Prints message. 66 | /// \param [in] type Message type. 67 | /// \param [in] file Name of the file where the print message command was issued. 68 | /// \param [in] line Line number in the file where the print message command was issued. 69 | /// \param [in] function Function where the print message command was issued. 70 | /// \param [in] format Format string. 71 | /// \param [in] args Argument lists. 72 | /// \return true if the message was successfully formatted and printed. 73 | /// \return false if an error occured. 74 | typedef bool (*MessagePrinterOutput)(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args); 75 | 76 | /// Message printer implementation. 77 | typedef struct MessagePrinter { 78 | MessagePrinterOpen open; 79 | MessagePrinterClose close; 80 | MessagePrinterOutput output; 81 | struct MessagePrinter* next; 82 | } MessagePrinter; 83 | 84 | #define ERROR_MSG(format, ...) message_print(MESSAGE_TYPE_ERROR, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 85 | 86 | #define WARNING_MSG(format, ...) message_print(MESSAGE_TYPE_WARNING, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 87 | 88 | #define INFO_MSG(format, ...) message_print(MESSAGE_TYPE_INFO, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 89 | 90 | #if NDEBUG 91 | # define DEBUG_MSG(format, ...) 92 | #else 93 | # define DEBUG_MSG(format, ...) message_print(MESSAGE_TYPE_DEBUG, __FILE__, __LINE__, __FUNCTION__, format, ##__VA_ARGS__) 94 | #endif 95 | 96 | /// Setup global message printer list. 97 | void message_printer_init(); 98 | /// Releases resources used by message printers. 99 | void message_printer_destroy(); 100 | 101 | /// Opens and adds a new message printer to the global list. 102 | /// \param [in] printer Message printer to be added to the list. 103 | /// \return true if the message printer was successfully added to the list. 104 | /// \return false if the message printer failed to open and could not be added to the message printer list. 105 | bool message_printer_add(MessagePrinter *printer); 106 | 107 | /// Dispatch message to printers. 108 | /// \param type Message type. 109 | /// \param file Name of the file where the print message command was issued. 110 | /// \param line Line number in the file where the print message command was issued. 111 | /// \param function Function where the print message command was issued. 112 | /// \param format Format string. 113 | void message_print(MessageType type, const char* file, size_t line, const char* function, const char* format, ...); 114 | 115 | /// @} 116 | 117 | #endif // ETRIPATOR_MESSAGE_H 118 | -------------------------------------------------------------------------------- /message/console.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "../config.h" 37 | #include "console.h" 38 | 39 | static bool g_use_escape_code = false; 40 | 41 | /// Tests if the console has support for colors and other things. 42 | /// \return true always. 43 | static bool console_message_printer_open() { 44 | g_use_escape_code = isatty(fileno(stdout)) ? true : false; 45 | return true; 46 | } 47 | 48 | /// Do nothing. 49 | /// \return true always. 50 | static bool console_message_printer_close() { 51 | return true; 52 | } 53 | 54 | /// Prints message to console. 55 | /// \param [in] type Message type. 56 | /// \param [in] file Name of the file where the print message command was issued. 57 | /// \param [in] line Line number in the file where the print message command was issued. 58 | /// \param [in] function Function where the print message command was issued. 59 | /// \param [in] format Format string. 60 | /// \param [in] args Argument lists. 61 | /// \return true upon success. 62 | static bool console_message_printer_output(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { 63 | static const char *message_type_name[] = { 64 | "[Error]", 65 | "[Warning]", 66 | "[Info]" 67 | }; 68 | static const char *message_type_prefix[] = { 69 | "\x1b[1;31m", 70 | "\x1b[1;33m", 71 | "\x1b[1;32m" 72 | }; 73 | 74 | bool ret = true; 75 | if(g_use_escape_code) { 76 | fprintf(stderr, "%s%s\x1b[0m %s:%zd \x1b[0;33m %s \x1b[1;37m : " 77 | , message_type_prefix[type] 78 | , message_type_name[type] 79 | , file 80 | , line 81 | , function 82 | ); 83 | } else { 84 | fprintf(stderr, "%s %s:%zd %s : " 85 | , message_type_name[type] 86 | , file 87 | , line 88 | , function 89 | ); 90 | } 91 | 92 | vfprintf(stderr, format, args); 93 | 94 | if(g_use_escape_code) { 95 | fprintf(stderr, "\x1b[0m\n"); 96 | } else { 97 | fputc('\n', stderr); 98 | } 99 | fflush(stderr); 100 | return ret; 101 | } 102 | 103 | static MessagePrinter g_console_message_printer = { 104 | .open = console_message_printer_open, 105 | .close = console_message_printer_close, 106 | .output = console_message_printer_output, 107 | .next = NULL, 108 | }; 109 | 110 | /* Setups console message writer. */ 111 | bool console_message_printer_init() { 112 | g_use_escape_code = false; 113 | return message_printer_add(&g_console_message_printer); 114 | } 115 | 116 | -------------------------------------------------------------------------------- /message/console.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_MESSAGE_CONSOLE_H 37 | #define ETRIPATOR_MESSAGE_CONSOLE_H 38 | 39 | #include "../message.h" 40 | 41 | /// Setups file message writer. 42 | /// \return true always. 43 | bool console_message_printer_init(); 44 | 45 | #endif // ETRIPATOR_MESSAGE_FILE_H 46 | 47 | -------------------------------------------------------------------------------- /message/file.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "../config.h" 37 | #include "file.h" 38 | 39 | static const char* g_log_filename = "etripator.log"; 40 | 41 | /// Check if the log file can be opened and written to. 42 | /// \return true if the log file was successfully opened. 43 | /// \return false if an error occured. 44 | static bool file_message_printer_open() { 45 | bool ret = false; 46 | int fd = open(g_log_filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 47 | if(fd < 0) { 48 | fprintf(stderr, "Failed to open log file %s: %s\n", g_log_filename, strerror(errno)); 49 | } else if(close(fd) < 0) { 50 | fprintf(stderr, "Failed to close log file %s: %s\n", g_log_filename, strerror(errno)); 51 | } else { 52 | ret = true; 53 | } 54 | return ret; 55 | } 56 | 57 | /// Do nothing. 58 | /// \return true always. 59 | static bool file_message_printer_close() { 60 | return true; 61 | } 62 | 63 | /// Prints message to file. 64 | /// \param [in] type Message type. 65 | /// \param [in] file Name of the file where the print message command was issued. 66 | /// \param [in] line Line number in the file where the print message command was issued. 67 | /// \param [in] function Function where the print message command was issued. 68 | /// \param [in] format Format string. 69 | /// \param [in] args Argument lists. 70 | /// \return true if the message was successfully written to the log file. 71 | /// \return false if an error occured. 72 | static bool file_message_printer_output(MessageType type, const char* file, size_t line, const char* function, const char* format, va_list args) { 73 | static const char *message_type_name[MESSAGE_TYPE_COUNT] = { 74 | "[Error]", 75 | "[Warning]", 76 | "[Info]", 77 | "[Debug]" 78 | }; 79 | bool ret = false; 80 | FILE *out = fopen(g_log_filename, "a+"); 81 | if(out == NULL) { 82 | fprintf(stderr, "Failed to open log file %s: %s\n", g_log_filename, strerror(errno)); 83 | } else { 84 | fprintf(out, "%s %s:%zd %s : ", message_type_name[type], file, line, function); 85 | vfprintf(out, format, args); 86 | fputc('\n', out); 87 | fflush(out); 88 | if(ferror(out)) { 89 | fprintf(stderr, "Failed to output log to %s: %s\n", g_log_filename, strerror(errno)); 90 | } else { 91 | ret = true; 92 | } 93 | fclose(out); 94 | } 95 | return ret; 96 | } 97 | 98 | static MessagePrinter g_file_message_printer = { 99 | .open = file_message_printer_open, 100 | .close = file_message_printer_close, 101 | .output = file_message_printer_output, 102 | .next = NULL, 103 | }; 104 | 105 | /* Setups file message writer. */ 106 | bool file_message_printer_init() { 107 | return message_printer_add(&g_file_message_printer); 108 | } 109 | 110 | -------------------------------------------------------------------------------- /message/file.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_MESSAGE_FILE_H 37 | #define ETRIPATOR_MESSAGE_FILE_H 38 | 39 | #include "../message.h" 40 | 41 | /// @addtogroup Message 42 | /// @{ 43 | 44 | /// Setups file message writer. 45 | /// Messages will be appeneded to a file names "etripator.log". 46 | /// This file will be placed in the current working directory. 47 | /// \return true if the log file can be written to. 48 | /// \return false if an error occured. 49 | bool file_message_printer_init(); 50 | 51 | /// @} 52 | 53 | #endif // ETRIPATOR_MESSAGE_FILE_H 54 | 55 | -------------------------------------------------------------------------------- /opcodes.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_OPCODES_H 37 | #define ETRIPATOR_OPCODES_H 38 | 39 | #include "config.h" 40 | 41 | /// @defgroup Opcode Opcode 42 | ///@{ 43 | 44 | /// Opcode types: 45 | /// -# `OPC` 46 | /// -# `OPC A` 47 | /// -# `OPC #nn` 48 | /// -# `OPC #nn, ZZ` 49 | /// -# `OPC #nn, ZZ, X` 50 | /// -# `OPC #nn, hhll` 51 | /// -# `OPC #nn, hhll, X` 52 | /// -# `OPC ZZ` 53 | /// -# `OPC ZZ, X` 54 | /// -# `OPC ZZ, Y` 55 | /// -# `OPC (ZZ)` 56 | /// -# `OPC (ZZ, X)` 57 | /// -# `OPC (ZZ), Y` 58 | /// -# `OPC ZZ, hhll` 59 | /// -# `OPC hhll` 60 | /// -# `OPC (hhll)` 61 | /// -# `OPC hhll, X` 62 | /// -# `OPC hhll, Y` 63 | /// -# `OPC shsl,dhdl,hhll` 64 | /// -# `OPC l_hhll` (label) 65 | /// -# `OPC ZZ, l_hhll` (label) 66 | /// -# `OPC [hhll, X]` 67 | /// -# `.db OPC` (unsupported opcode output as raw binary data) 68 | enum PCE_ADDRESSING_MODE { 69 | PCE_OP = 0, 70 | PCE_OP_A, 71 | PCE_OP_nn, 72 | PCE_OP_nn_ZZ, 73 | PCE_OP_nn_ZZ_X, 74 | PCE_OP_nn_hhll, 75 | PCE_OP_nn_hhll_X, 76 | PCE_OP_ZZ, 77 | PCE_OP_ZZ_X, 78 | PCE_OP_ZZ_Y, 79 | PCE_OP__ZZ__, 80 | PCE_OP__ZZ_X__, 81 | PCE_OP__ZZ__Y_, 82 | PCE_OP_ZZ_hhll, 83 | PCE_OP_hhll, 84 | PCE_OP__hhll__, 85 | PCE_OP_hhll_X, 86 | PCE_OP_hhll_Y, 87 | PCE_OP_shsl_dhdl_hhll, 88 | PCE_OP__lbl__, 89 | PCE_OP_ZZ_lbl, 90 | PCE_OP__hhll_X__, 91 | PCE_unknown 92 | }; 93 | 94 | #define OPCODE_NAME_MAX_LEN 5U 95 | 96 | /// Opcode 97 | typedef struct { 98 | char name[OPCODE_NAME_MAX_LEN]; //< name 99 | uint8_t size; //< size in bytes 100 | uint8_t type; //< addressing type 101 | } Opcode; 102 | 103 | /// Get opcode description 104 | /// \param [in] op Opcode id 105 | /// \return Pointer to opcode description 106 | const Opcode* opcode_get(uint8_t op); 107 | 108 | /// Get opcode format string 109 | /// \param [in] op Pointer to opcode description 110 | /// \param [in] i Opcode argument id 111 | /// \return Argument format string 112 | /// \return NULL if the argument id is out of opcode argument count 113 | const char* opcode_format(const Opcode *op, int i); 114 | 115 | /// Is the instruction a local jump ? 116 | bool opcode_is_local_jump(uint8_t op); 117 | 118 | /// Is the instruction a "far" jump ? 119 | bool opcode_is_far_jump(uint8_t op); 120 | 121 | /// @} 122 | 123 | #endif // ETRIPATOR_OPCODES_H 124 | -------------------------------------------------------------------------------- /rom.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "rom.h" 37 | #include "message.h" 38 | 39 | static bool rom_load_data(const char *filename, MemoryMap *map) { 40 | bool ret = false; 41 | 42 | size_t size = 0; 43 | FILE *in = fopen(filename, "rb"); 44 | if (in == NULL) { 45 | ERROR_MSG("Unable to open %s : %s", filename, strerror(errno)); 46 | } else { 47 | // Compute file size. 48 | struct stat infos; 49 | int fd = fileno(in); 50 | if (fd < 0) { 51 | ERROR_MSG("Failed to retrieve file descriptior for %s : %s", filename, strerror(errno)); 52 | } else if (fstat(fd, &infos) < 0) { 53 | ERROR_MSG("Failed to retrieve file informations of %s : %s", filename, strerror(errno)); 54 | } else if (infos.st_size == 0) { 55 | ERROR_MSG("Empty file: %s", filename); 56 | } else { 57 | size = infos.st_size; 58 | // Check for possible header 59 | if (size & 0x200U) { 60 | // Jump header 61 | size &= ~0x200U; 62 | if (fseek(in, 0x200U, SEEK_SET) < 0) { 63 | ERROR_MSG("Failed to jump rom header in %s: %s", filename, strerror(errno)); 64 | } 65 | } 66 | } 67 | if(size) { 68 | // Allocate rom storage 69 | Memory *memory = &map->memory[PCE_MEMORY_ROM]; 70 | if (!memory_create(memory, (size + 0x1FFFU) & ~0x1FFFU)) { 71 | ERROR_MSG("Failed to allocate ROM storage : %s", strerror(errno)); 72 | } else { 73 | // Fill rom with 0xFF 74 | (void)memory_fill(memory, 0xFFU); 75 | // Read ROM data 76 | size_t count = (size < memory->length) ? size : memory->length; 77 | size_t nread = fread(memory->data, 1, count, in); 78 | if (nread != count) { 79 | ERROR_MSG("Failed to read ROM data from %s (expected %zu, read %zu): %s", filename, count, nread, strerror(errno)); 80 | memory_destroy(memory); 81 | } else { 82 | ret = true; 83 | } 84 | } 85 | } 86 | fclose(in); 87 | } 88 | return ret; 89 | } 90 | 91 | // Load ROM from file and update memory map. 92 | bool rom_load(const char* filename, MemoryMap* map) { 93 | assert(filename != NULL); 94 | assert(map != NULL); 95 | FILE *in; 96 | bool ret = false; 97 | if(rom_load_data(filename, map)) { 98 | unsigned int i; 99 | /* Initialize ROM pages. */ 100 | if (map->memory[PCE_MEMORY_ROM].length == 0x60000U) { 101 | for (i = 0; i < 64; i++) { 102 | map->page[i].id = PCE_MEMORY_ROM; 103 | map->page[i].bank = i & 0x1FU; 104 | } 105 | for (i = 64; i < 128; i++) { 106 | map->page[i].id = PCE_MEMORY_ROM; 107 | map->page[i].bank = (i & 0x0FU) + 32; 108 | } 109 | } else if (map->memory[PCE_MEMORY_ROM].length == 0x80000U) { 110 | for (i = 0; i < 64; i++) { 111 | map->page[i].id = PCE_MEMORY_ROM; 112 | map->page[i].bank = i & 0x3FU; 113 | } 114 | for (i = 64; i < 128; i++) { 115 | map->page[i].id = PCE_MEMORY_ROM; 116 | map->page[i].bank = (i & 0x1FU) + 32; 117 | } 118 | } else { 119 | for (i = 0; i < 128; i++) { 120 | map->page[i].id = PCE_MEMORY_ROM; 121 | map->page[i].bank = i % (map->memory[PCE_MEMORY_ROM].length / PCE_BANK_SIZE); 122 | } 123 | } 124 | ret = true; 125 | } 126 | return ret; 127 | } 128 | -------------------------------------------------------------------------------- /rom.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_ROM_H 37 | #define ETRIPATOR_ROM_H 38 | 39 | #include "memory_map.h" 40 | 41 | /// Load ROM from file and update memory map. 42 | /// \param [in] filename ROM filename. 43 | /// \param [out] map Memory map. 44 | /// \return true if the ROM was successfully loaded. 45 | /// \return false if an error occured. 46 | bool rom_load(const char* filename, MemoryMap* map); 47 | 48 | #endif // ETRIPATOR_ROM_H 49 | -------------------------------------------------------------------------------- /section.h: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #ifndef ETRIPATOR_SECTION_H 37 | #define ETRIPATOR_SECTION_H 38 | 39 | #include "config.h" 40 | 41 | /// Section type. 42 | typedef enum { 43 | SECTION_TYPE_UNKNOWN = -1, 44 | SECTION_TYPE_DATA = 0, 45 | SECTION_TYPE_CODE, 46 | SECTION_TYPE_COUNT 47 | } SectionType; 48 | 49 | /// Retrieves section type name 50 | /// \param [in] type Section type 51 | /// \return "data" if type is SECTION_TYPE_DATA 52 | /// \return "code" if type is SECTION_TYPE_CODE 53 | /// \return "unknown" otherwise 54 | const char* section_type_name(SectionType type); 55 | 56 | /// Data type 57 | typedef enum { 58 | DATA_TYPE_UNKNOWN = -1, 59 | DATA_TYPE_BINARY = 0, 60 | DATA_TYPE_HEX, 61 | DATA_TYPE_STRING, 62 | DATA_TYPE_JUMP_TABLE, 63 | DATA_TYPE_COUNT 64 | } DataType; 65 | 66 | /// Retrieves data type name 67 | /// \param [in] type Data type 68 | /// \return "binary" if type is DATA_TYPE_BINARY 69 | /// \return "hex" if type is DATA_TYPE_HEX 70 | /// \return "string" if type is DATA_TYPE_STRING 71 | /// \return "jumptable if type is DATA_TYPE_JUMP_TABLE 72 | /// \return "unknown" otherwise 73 | const char* data_type_name(DataType type); 74 | 75 | /// Data section configuration 76 | typedef struct { 77 | DataType type; //< type 78 | int32_t element_size; //< element size (string=0, byte=1, word=2) 79 | int32_t elements_per_line; //< number of elements per line 80 | 81 | uint8_t delimiter[8U]; //< string delimiter 82 | int32_t delimiter_size; //< string delimiter length 83 | } DataConfig; 84 | 85 | /// Section description 86 | typedef struct { 87 | char *name; //< Name 88 | SectionType type; //< Type 89 | uint8_t page; //< Memory page 90 | uint16_t logical; //< logical address 91 | uint32_t offset; //< input offset 92 | int32_t size; //< size (in bytes) 93 | uint8_t mpr[8]; //< mpr registers value 94 | char *output; //< output filename 95 | DataConfig data; //< data configuration (only valid for *data* sections) 96 | char *description; //< optional description 97 | } Section; 98 | 99 | /// Section array 100 | typedef struct { 101 | Section *data; ///< Pointer to section array. 102 | size_t count; ///< Number of sections currently in use. 103 | size_t capacity; ///< Number the section array can hold. 104 | } SectionArray; 105 | 106 | /// Reset a section array. 107 | /// \note The internal data pointer will not be freed. 108 | /// \param [in out] arr Section array to be reseted. 109 | void section_array_reset(SectionArray *arr); 110 | 111 | /// Release section array memory. 112 | /// \param [in out] arr Section array. 113 | void section_array_delete(SectionArray *arr); 114 | 115 | /// Add a new section. 116 | /// \param [in out] arr Section array the section will be added to. 117 | /// \param [in] in Section that will be added to the section array. 118 | /// \return 1 if the section was succesfully added. 119 | /// \return 0 if the section was merged with one from the section array. 120 | /// \return -1 if the section can not be merged or if there is not enough memory to add a new one. 121 | int section_array_add(SectionArray *arr, const Section* in); 122 | 123 | /// Merge and sort sections. 124 | /// \param [in out] arr Section array the section will be added to. 125 | void section_array_tidy(SectionArray *arr); 126 | 127 | /// Retrieve the ith section from the array. 128 | /// \param [in] arr Section array. 129 | /// \param [in] i Index of the section to be retrieved. 130 | /// \return A pointer to the section if the index is within the section array bounds. 131 | /// \return NULL if the index is out of the section array bounds. 132 | const Section* section_array_get(SectionArray *arr, size_t i); 133 | 134 | /// Reset a section to its default values. 135 | void section_reset(Section *s); 136 | 137 | /// Delete section. 138 | void section_delete(Section *ptr); 139 | 140 | // Load sections from a JSON file. 141 | // \param [out] arr Loaded sections. 142 | // \param [in] filename Input filename. 143 | // \return true if the sections contained in the file were succesfully loaded. 144 | // \return false if an error occured. 145 | bool section_load(SectionArray *arr, const char *filename); 146 | 147 | // Save sections to a JSON file. 148 | // \param [in] ptr Sections to be saved. 149 | // \param [in] count Number of sections. 150 | // \param [in] filename Output filename. 151 | // \return true if the sections were succesfully saved. 152 | // \return false if an error occured. 153 | bool section_save(const Section *ptr, int n, const char *filename); // [todo] use SectionArray 154 | 155 | #endif // ETRIPATOR_SECTION_H 156 | -------------------------------------------------------------------------------- /section/save.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include "../section.h" 37 | 38 | #include "../jsonhelpers.h" 39 | #include "../message.h" 40 | #include 41 | #include 42 | #include 43 | 44 | // Save sections to a JSON file 45 | bool section_save(const Section *ptr, int n, const char *filename) { 46 | bool ret = false; 47 | FILE *out = fopen(filename, "wb"); 48 | if(!out) { 49 | ERROR_MSG("Failed to open %s: %s", filename, strerror(errno)); 50 | } else { 51 | fprintf(out, "{\n"); 52 | for(int i=0; i 32 | WORKING_DIRECTORY $ 33 | ) 34 | add_custom_command( 35 | TARGET ${target_name} POST_BUILD 36 | COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/data $/data 37 | ) 38 | endfunction() 39 | 40 | add_unit_test( 41 | NAME message 42 | SOURCES 43 | message.c 44 | LIBRARIES cwalk 45 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 46 | ) 47 | 48 | add_unit_test( 49 | NAME memory 50 | SOURCES 51 | memory.c 52 | ${PROJECT_SOURCE_DIR}/memory.c 53 | ${PROJECT_SOURCE_DIR}/message.c 54 | ${PROJECT_SOURCE_DIR}/message/console.c 55 | LIBRARIES cwalk 56 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 57 | ) 58 | 59 | add_unit_test( 60 | NAME memory_map 61 | SOURCES 62 | memory_map.c 63 | ${PROJECT_SOURCE_DIR}/memory_map.c 64 | ${PROJECT_SOURCE_DIR}/memory.c 65 | ${PROJECT_SOURCE_DIR}/message.c 66 | ${PROJECT_SOURCE_DIR}/message/console.c 67 | LIBRARIES cwalk 68 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 69 | ) 70 | 71 | if(CMAKE_COMPILER_IS_GNUCC) 72 | add_unit_test( 73 | NAME rom 74 | SOURCES 75 | rom.c 76 | ${PROJECT_SOURCE_DIR}/rom.c 77 | ${PROJECT_SOURCE_DIR}/memory_map.c 78 | ${PROJECT_SOURCE_DIR}/memory.c 79 | ${PROJECT_SOURCE_DIR}/message.c 80 | ${PROJECT_SOURCE_DIR}/message/console.c 81 | LIBRARIES cwalk fff 82 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 83 | WRAP fopen fileno fstat fseek fread fclose 84 | ) 85 | endif() 86 | 87 | add_unit_test( 88 | NAME cd 89 | SOURCES 90 | cd.c 91 | ${PROJECT_SOURCE_DIR}/cd.c 92 | ${PROJECT_SOURCE_DIR}/memory_map.c 93 | ${PROJECT_SOURCE_DIR}/memory.c 94 | ${PROJECT_SOURCE_DIR}/message.c 95 | ${PROJECT_SOURCE_DIR}/message/console.c 96 | LIBRARIES cwalk 97 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 98 | ) 99 | 100 | add_unit_test( 101 | NAME label 102 | SOURCES 103 | label.c 104 | ${PROJECT_SOURCE_DIR}/label.c 105 | ${PROJECT_SOURCE_DIR}/label/load.c 106 | ${PROJECT_SOURCE_DIR}/message.c 107 | ${PROJECT_SOURCE_DIR}/jsonhelpers.c 108 | ${PROJECT_SOURCE_DIR}/message/console.c 109 | LIBRARIES cwalk jansson 110 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 111 | ) 112 | 113 | add_unit_test( 114 | NAME comment 115 | SOURCES 116 | comment.c 117 | ${PROJECT_SOURCE_DIR}/comment.c 118 | ${PROJECT_SOURCE_DIR}/comment/load.c 119 | ${PROJECT_SOURCE_DIR}/comment/save.c 120 | ${PROJECT_SOURCE_DIR}/message.c 121 | ${PROJECT_SOURCE_DIR}/jsonhelpers.c 122 | ${PROJECT_SOURCE_DIR}/message/console.c 123 | LIBRARIES cwalk jansson 124 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 125 | ) 126 | 127 | add_unit_test( 128 | NAME section 129 | SOURCES 130 | section.c 131 | ${PROJECT_SOURCE_DIR}/section/load.c 132 | ${PROJECT_SOURCE_DIR}/message.c 133 | ${PROJECT_SOURCE_DIR}/jsonhelpers.c 134 | ${PROJECT_SOURCE_DIR}/message/console.c 135 | LIBRARIES cwalk jansson 136 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 137 | ) 138 | 139 | add_unit_test( 140 | NAME opcodes 141 | SOURCES 142 | opcodes.c 143 | ${PROJECT_SOURCE_DIR}/opcodes.c 144 | ${PROJECT_SOURCE_DIR}/message.c 145 | ${PROJECT_SOURCE_DIR}/message/console.c 146 | LIBRARIES cwalk jansson 147 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 148 | ) 149 | 150 | add_unit_test( 151 | NAME ipl 152 | SOURCES 153 | ipl.c 154 | ${PROJECT_SOURCE_DIR}/section.c 155 | ${PROJECT_SOURCE_DIR}/message.c 156 | ${PROJECT_SOURCE_DIR}/message/console.c 157 | LIBRARIES cwalk jansson 158 | INCLUDE_DIRECTORIES ${PROJECT_SOURCE_DIR} 159 | ) 160 | -------------------------------------------------------------------------------- /test/cd.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | void* setup(const MunitParameter params[] __attribute__((unused)), void* user_data __attribute__((unused))) { 44 | return NULL; 45 | } 46 | 47 | void tear_down(void* fixture __attribute__((unused))) { 48 | } 49 | 50 | MunitResult cd_memory_map_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 51 | MemoryMap map = {}; 52 | 53 | munit_assert_true(memory_map_init(&map)); 54 | munit_assert_true(cd_memory_map(&map)); 55 | 56 | munit_assert_not_null(map.memory[PCE_MEMORY_CD_RAM].data); 57 | munit_assert_size(map.memory[PCE_MEMORY_CD_RAM].length, ==, PCE_CD_RAM_BANK_COUNT*PCE_BANK_SIZE); 58 | for(size_t i=0; i ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | #include "comment.h" 38 | #include "message.h" 39 | #include "message/console.h" 40 | 41 | void* setup(const MunitParameter params[] __attribute__((unused)), void* user_data __attribute__((unused))) { 42 | message_printer_init(); 43 | console_message_printer_init(); 44 | return NULL; 45 | } 46 | 47 | void tear_down(void* fixture __attribute__((unused))) { 48 | message_printer_destroy(); 49 | } 50 | 51 | MunitResult comment_add_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 52 | Comment comment = {0}; 53 | CommentRepository repository = {0}; 54 | munit_assert_true(comment_repository_create(&repository)); 55 | 56 | munit_assert_true(comment_repository_add(&repository, 0x0002, 0x00, "comment #0")); 57 | munit_assert_true(comment_repository_add(&repository, 0x0001, 0x00, "comment #1")); 58 | munit_assert_true(comment_repository_add(&repository, 0x0003, 0x00, "comment #3")); 59 | munit_assert_true(comment_repository_add(&repository, 0x0001, 0x01, "comment #2")); 60 | 61 | munit_assert_true(comment_repository_find(&repository, 0x0001, 0x01, &comment)); 62 | munit_assert_uint16(comment.logical, ==, 0x0001); 63 | munit_assert_uint8(comment.page, ==, 0x01); 64 | munit_assert_string_equal(comment.text, "comment #2"); 65 | 66 | munit_assert_true(comment_repository_find(&repository, 0x0001, 0x00, &comment)); 67 | munit_assert_uint16(comment.logical, ==, 0x0001); 68 | munit_assert_uint8(comment.page, ==, 0x00); 69 | munit_assert_string_equal(comment.text, "comment #1"); 70 | 71 | munit_assert_true(comment_repository_find(&repository, 0x0003, 0x00, &comment)); 72 | munit_assert_uint16(comment.logical, ==, 0x0003); 73 | munit_assert_uint8(comment.page, ==, 0x00); 74 | munit_assert_string_equal(comment.text, "comment #3"); 75 | 76 | munit_assert_int(comment_repository_size(&repository), ==, 4); 77 | 78 | comment_repository_destroy(&repository); 79 | 80 | return MUNIT_OK; 81 | } 82 | 83 | MunitResult comment_delete_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 84 | Comment comment = {0}; 85 | CommentRepository repository = {0}; 86 | munit_assert_true(comment_repository_create(&repository)); 87 | 88 | munit_assert_true(comment_repository_add(&repository, 0x0002, 0x03, "comment #7")); 89 | munit_assert_true(comment_repository_add(&repository, 0x0002, 0x01, "comment #6")); 90 | munit_assert_true(comment_repository_add(&repository, 0x0002, 0x02, "comment #5")); 91 | munit_assert_true(comment_repository_add(&repository, 0x000a, 0x00, "comment #4")); 92 | munit_assert_true(comment_repository_add(&repository, 0x0008, 0x00, "comment #3")); 93 | munit_assert_true(comment_repository_add(&repository, 0x0004, 0x00, "comment #2")); 94 | munit_assert_true(comment_repository_add(&repository, 0x0002, 0x00, "comment #1")); 95 | munit_assert_true(comment_repository_add(&repository, 0x0000, 0x00, "comment #0")); 96 | munit_assert_int(comment_repository_size(&repository), ==, 8); 97 | 98 | comment_repository_delete(&repository, 0x0001, 0x0009, 0x00); 99 | 100 | munit_assert_int(comment_repository_size(&repository), ==, 5); 101 | 102 | comment_repository_destroy(&repository); 103 | 104 | return MUNIT_OK; 105 | } 106 | 107 | MunitResult comment_load_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 108 | Comment comment = {0}; 109 | CommentRepository repository = {0}; 110 | 111 | munit_assert_true(comment_repository_create(&repository)); 112 | 113 | munit_assert_false(comment_repository_load(&repository, "/not_here/comment.json")); 114 | munit_assert_int(comment_repository_size(&repository), ==, 0); 115 | 116 | munit_assert_false(comment_repository_load(&repository, "data/comment_1.json")); 117 | munit_assert_int(comment_repository_size(&repository), ==, 1); 118 | 119 | munit_assert_true(comment_repository_get(&repository, 0, &comment)); 120 | munit_assert_uint16(comment.logical, ==, 0xCAFEU); 121 | munit_assert_uint8(comment.page, ==, 0x0AU); 122 | munit_assert_string_equal(comment.text, "hello!"); 123 | 124 | comment_repository_destroy(&repository); 125 | 126 | munit_assert_true(comment_repository_load(&repository, "data/comment_0.json")); 127 | munit_assert_int(comment_repository_size(&repository), ==, 2); 128 | 129 | munit_assert_true(comment_repository_find(&repository, 0xC105U, 3, &comment)); 130 | munit_assert_uint16(comment.logical, ==, 0xC105U); 131 | munit_assert_uint8(comment.page, ==, 3); 132 | munit_assert_string_equal(comment.text, "line 0\nline 1\nline 2"); 133 | 134 | munit_assert_true(comment_repository_find(&repository, 0xEABCU, 0, &comment)); 135 | munit_assert_uint16(comment.logical, ==, 0xEABCU); 136 | munit_assert_uint8(comment.page, ==, 0); 137 | munit_assert_string_equal(comment.text, "single line comment"); 138 | 139 | comment_repository_destroy(&repository); 140 | 141 | return MUNIT_OK; 142 | } 143 | 144 | static MunitTest comment_tests[] = { 145 | { "/add", comment_add_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 146 | { "/delete", comment_delete_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 147 | { "/load", comment_load_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 148 | { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } 149 | }; 150 | 151 | static const MunitSuite comment_suite = { 152 | "Comment test suite", comment_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE 153 | }; 154 | 155 | int main (int argc, char* const* argv) { 156 | return munit_suite_main(&comment_suite, NULL, argc, argv); 157 | } -------------------------------------------------------------------------------- /test/data/bank0_0.json: -------------------------------------------------------------------------------- 1 | { 2 | "cdbios_functions": { 3 | "filename": "syscard.asm", 4 | "type": "code", 5 | "page": "0", 6 | "logical" : "e000", 7 | "size": "504", 8 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 9 | }, 10 | 11 | "unknown.0": { 12 | "filename": "syscard.asm", 13 | "type": "data", 14 | "page": "0", 15 | "logical" : "e504", 16 | "size": "5", 17 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 18 | }, 19 | 20 | "ex_colorcmd.impl": { 21 | "filename": "syscard.asm", 22 | "type": "code", 23 | "page": "0", 24 | "logical" : "e509", 25 | "size": "ce", 26 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 27 | }, 28 | 29 | "unknown.1": { 30 | "filename": "syscard.asm", 31 | "type": "data", 32 | "page": "0", 33 | "logical" : "e5d7", 34 | "size": "3", 35 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 36 | } 37 | } -------------------------------------------------------------------------------- /test/data/bank0_1.json: -------------------------------------------------------------------------------- 1 | { 2 | "ex_satclr.impl": { 3 | "filename": "syscard.asm", 4 | "type": "code", 5 | "page": "0", 6 | "logical" : "e5da", 7 | "size": "26", 8 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 9 | }, 10 | 11 | "unknown.2": { 12 | "filename": "syscard.asm", 13 | "type": "data", 14 | "page": "0", 15 | "logical" : "f8a9", 16 | "size": "f", 17 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 18 | }, 19 | 20 | "bm_free.impl": { 21 | "filename": "syscard.asm", 22 | "type": "code", 23 | "page": "0", 24 | "logical" : "f8b8", 25 | "size": "575", 26 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 27 | }, 28 | 29 | "grp_bios.impl": { 30 | "filename": "syscard.asm", 31 | "type": "code", 32 | "page": "0", 33 | "logical" : "fe57", 34 | "size": "18", 35 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 36 | }, 37 | 38 | "jump_table.0": { 39 | "filename": "syscard.asm", 40 | "type": "data", 41 | "page": "0", 42 | "logical" : "fe2d", 43 | "size": "2a", 44 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 45 | }, 46 | 47 | "jump_table.1": { 48 | "filename": "syscard.asm", 49 | "type": "data", 50 | "page": "0", 51 | "logical" : "fe70", 52 | "size": "22", 53 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 54 | }, 55 | 56 | "ex_memopen.impl": { 57 | "filename": "syscard.asm", 58 | "type": "code", 59 | "page": "0", 60 | "logical" : "fe92", 61 | "size": "30", 62 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 63 | }, 64 | 65 | "unknown.3": { 66 | "filename": "syscard.asm", 67 | "type": "data", 68 | "page": "0", 69 | "logical" : "fec2", 70 | "size": "134", 71 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ] 72 | }, 73 | 74 | "irq_vectors": { 75 | "filename": "syscard.asm", 76 | "type": "data", 77 | "page": "0", 78 | "logical": "fff6", 79 | "size": "a", 80 | "mpr": ["ff", "f8", 0, 0, 0, 0, 0, 0 ], 81 | "data": { "type": "hex", "element_size": 2, "elements_per_line": 1 } 82 | } 83 | } -------------------------------------------------------------------------------- /test/data/comment_0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "logical": "EABC", "page": "0", "text": "single line comment" }, 3 | { "logical": "C105", "page": "3", "text": [ 4 | "line 0", 5 | "line 1", 6 | "line 2" 7 | ] 8 | } 9 | ] -------------------------------------------------------------------------------- /test/data/comment_1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "logical": "CAFE", "page": "0a", "text": "hello!" }, 3 | { "logical": "F00D", "page": "40", "text": { "foo": "bar" } } 4 | ] -------------------------------------------------------------------------------- /test/data/label_0.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name": "var", "logical": "31dc", "page": "f8" }, 3 | { "name": "do_something", "logical": "eabc", "page": "00", "description": "do something" }, 4 | { "name": "run", "logical" : "d6f7", "page": "1f", "description": [ 5 | "line0", 6 | "line1", 7 | "line2", 8 | "line3" 9 | ] 10 | } 11 | ] -------------------------------------------------------------------------------- /test/data/label_1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "name": "ok", "logical": "5030", "page": "04" }, 3 | { "name": "broken", "logical": "cafe", "page": ["5a"], "description": "!" } 4 | ] -------------------------------------------------------------------------------- /test/ipl.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | 38 | #include "../ipl.c" 39 | 40 | #include "message.h" 41 | #include "message/console.h" 42 | 43 | static uint8_t g_hcd8004_ipl[] = { 44 | 0x00, 0x00, 0x02, 0x04, 0x00, 0x40, 0x00, 0x40, 0x00, 0x01, 0x02, 0x03, 0x04, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 | 0x50, 0x43, 0x20, 0x45, 0x6E, 0x67, 0x69, 0x6E, 0x65, 0x20, 0x43, 0x44, 0x2D, 0x52, 0x4F, 0x4D, 47 | 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4D, 0x00, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 48 | 0x74, 0x20, 0x48, 0x55, 0x44, 0x53, 0x4F, 0x4E, 0x20, 0x53, 0x4F, 0x46, 0x54, 0x20, 0x2F, 0x20, 49 | 0x4E, 0x45, 0x43, 0x20, 0x48, 0x6F, 0x6D, 0x65, 0x20, 0x45, 0x6C, 0x65, 0x63, 0x74, 0x72, 0x6F, 50 | 0x6E, 0x69, 0x63, 0x73, 0x2C, 0x4C, 0x74, 0x64, 0x2E, 0x00, 0x53, 0x70, 0x61, 0x63, 0x65, 0x20, 51 | 0x41, 0x64, 0x76, 0x65, 0x6E, 0x74, 0x75, 0x72, 0x65, 0x20, 0x43, 0x4F, 0x42, 0x52, 0x41, 0x20, 52 | }; 53 | 54 | void* setup(const MunitParameter params[] __attribute__((unused)), void* user_data __attribute__((unused))) { 55 | message_printer_init(); 56 | console_message_printer_init(); 57 | return NULL; 58 | } 59 | 60 | void tear_down(void* fixture __attribute__((unused))) { 61 | message_printer_destroy(); 62 | } 63 | 64 | MunitResult ipl_read_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 65 | IPL ipl = {0}; 66 | const char *filename = "data/HCD8004.ipl"; 67 | 68 | FILE *in = fmemopen(g_hcd8004_ipl, sizeof(g_hcd8004_ipl), "r"); 69 | 70 | munit_assert_not_null(in); 71 | munit_assert_true(ipl_read_header(&ipl, in, filename)); 72 | munit_assert_int(fclose(in), ==, 0); 73 | 74 | munit_assert_uint8(ipl.load_start_record[0], ==, 0x00U); 75 | munit_assert_uint8(ipl.load_start_record[1], ==, 0x00U); 76 | munit_assert_uint8(ipl.load_start_record[2], ==, 0x02U); 77 | 78 | munit_assert_uint8(ipl.load_sector_count, ==, 0x04U); 79 | 80 | munit_assert_uint8(ipl.load_store_address[0], ==, 0x00U); 81 | munit_assert_uint8(ipl.load_store_address[1], ==, 0x40U); 82 | 83 | munit_assert_uint8(ipl.load_exec_address[0], ==, 0x00U); 84 | munit_assert_uint8(ipl.load_exec_address[1], ==, 0x40U); 85 | 86 | munit_assert_uint8(ipl.mpr[0], ==, 0x00U); 87 | munit_assert_uint8(ipl.mpr[1], ==, 0x01U); 88 | munit_assert_uint8(ipl.mpr[2], ==, 0x02U); 89 | munit_assert_uint8(ipl.mpr[3], ==, 0x03U); 90 | munit_assert_uint8(ipl.mpr[4], ==, 0x04U); 91 | 92 | munit_assert_uint8(ipl.opening_mode, ==, 0x00U); 93 | 94 | munit_assert_uint8(ipl.opening_gfx_record[0], ==, 0x00U); 95 | munit_assert_uint8(ipl.opening_gfx_record[1], ==, 0x00U); 96 | munit_assert_uint8(ipl.opening_gfx_record[2], ==, 0x00U); 97 | 98 | munit_assert_uint8(ipl.opening_gfx_sector_count, ==, 0x00U); 99 | 100 | munit_assert_uint8(ipl.opening_gfx_read_address[0], ==, 0x00U); 101 | munit_assert_uint8(ipl.opening_gfx_read_address[1], ==, 0x00U); 102 | 103 | munit_assert_uint8(ipl.opening_adpcm_record[0], ==, 0x00U); 104 | munit_assert_uint8(ipl.opening_adpcm_record[1], ==, 0x00U); 105 | munit_assert_uint8(ipl.opening_adpcm_record[2], ==, 0x00U); 106 | 107 | munit_assert_uint8(ipl.opening_adpcm_sector_count, ==, 0x00U); 108 | 109 | munit_assert_uint8(ipl.opening_adpcm_sampling_rate, ==, 0x00U); 110 | 111 | for(unsigned int i=0; i<7; i++) { 112 | munit_assert_uint8(ipl.reserved[i], ==, 0x00U); 113 | } 114 | 115 | munit_assert_memory_equal(24U, ipl.id, "PC Engine CD-ROM SYSTEM"); 116 | 117 | munit_assert_memory_equal(50U, ipl.legal, "Copyright HUDSON SOFT / NEC Home Electronics,Ltd."); 118 | 119 | munit_assert_memory_equal(16U, ipl.program_name, "Space Adventure "); 120 | 121 | munit_assert_memory_equal(6U, ipl.extra, "COBRA "); 122 | 123 | return MUNIT_OK; 124 | } 125 | 126 | static MunitTest g_ipl_tests[] = { 127 | { "/read", ipl_read_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 128 | { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } 129 | }; 130 | 131 | static const MunitSuite g_ipl_test_suite = { 132 | "Label test suite", g_ipl_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE 133 | }; 134 | 135 | int main (int argc, char* const* argv) { 136 | return munit_suite_main(&g_ipl_test_suite, NULL, argc, argv); 137 | } -------------------------------------------------------------------------------- /test/memory.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | void* setup(const MunitParameter params[] __attribute__((unused)), void* user_data __attribute__((unused))) { 44 | return NULL; 45 | } 46 | 47 | void tear_down(void* fixture __attribute__((unused))) { 48 | } 49 | 50 | MunitResult memory_create_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 51 | Memory mem = {0}; 52 | bool result = false; 53 | 54 | mem.data = NULL; 55 | mem.length = 0xCAFEU; 56 | munit_assert_false(memory_create(&mem, 0U)); 57 | munit_assert_size(mem.length, ==, 0xCAFEU); 58 | munit_assert_ptr_null(mem.data); 59 | 60 | munit_assert_true(memory_create(&mem, 32U)); 61 | munit_assert_size(mem.length, ==, 32U); 62 | munit_assert_ptr_not_null(mem.data); 63 | 64 | memory_destroy(&mem); 65 | munit_assert_size(mem.length, ==, 0U); 66 | munit_assert_ptr_null(mem.data); 67 | 68 | return MUNIT_OK; 69 | } 70 | 71 | MunitResult memory_create_fill(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 72 | Memory mem = {0}; 73 | 74 | munit_assert_false(memory_fill(&mem, 0x7C)); 75 | 76 | munit_assert_true(memory_create(&mem, 256U)); 77 | munit_assert_size(mem.length, ==, 256U); 78 | munit_assert_ptr_not_null(mem.data); 79 | 80 | munit_assert_true(memory_fill(&mem, 0x7C)); 81 | for(size_t i=0; i ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | #include 42 | 43 | void* setup(const MunitParameter params[] __attribute__((unused)), void* user_data __attribute__((unused))) { 44 | return NULL; 45 | } 46 | 47 | void tear_down(void* fixture __attribute__((unused))) { 48 | } 49 | 50 | MunitResult memory_map_read_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 51 | MemoryMap map = {0}; 52 | 53 | munit_assert_true(memory_map_init(&map)); 54 | 55 | map.mpr[1] = 0xF8U; 56 | 57 | map.memory[PCE_MEMORY_BASE_RAM].data[0x0000] = 0xC5; 58 | map.memory[PCE_MEMORY_BASE_RAM].data[0x0100] = 0x7E; 59 | map.memory[PCE_MEMORY_BASE_RAM].data[0x1000] = 0xA9; 60 | 61 | munit_assert_uint8(memory_map_read(&map, 0x2000U), ==, 0xC5); 62 | munit_assert_uint8(memory_map_read(&map, 0x2100U), ==, 0x7E); 63 | munit_assert_uint8(memory_map_read(&map, 0x3000U), ==, 0xA9); 64 | 65 | memory_map_destroy(&map); 66 | 67 | return MUNIT_OK; 68 | } 69 | 70 | static MunitTest memory_map_tests[] = { 71 | { "/read", memory_map_read_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 72 | { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } 73 | }; 74 | 75 | static const MunitSuite memory_map_suite = { 76 | "Memory map test suite", memory_map_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE 77 | }; 78 | 79 | int main (int argc, char* const* argv) { 80 | message_printer_init(); 81 | console_message_printer_init(); 82 | 83 | int ret = munit_suite_main(&memory_map_suite, NULL, argc, argv); 84 | 85 | message_printer_destroy(); 86 | 87 | return ret; 88 | } -------------------------------------------------------------------------------- /test/opcodes.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | #include "opcodes.h" 38 | #include "message.h" 39 | #include "message/console.h" 40 | 41 | void* setup(const MunitParameter params[] __attribute__((unused)), void* user_data __attribute__((unused))) { 42 | message_printer_init(); 43 | console_message_printer_init(); 44 | return NULL; 45 | } 46 | 47 | void tear_down(void* fixture __attribute__((unused))) { 48 | message_printer_destroy(); 49 | } 50 | 51 | MunitResult opcodes_get_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 52 | const Opcode* op; 53 | 54 | op = opcode_get(0x00); 55 | munit_assert_not_null(op); 56 | munit_assert_string_equal(op->name, "brk "); 57 | munit_assert_uint8(op->size, ==, 1U); 58 | munit_assert_uint8(op->type, ==, PCE_OP); 59 | 60 | op = opcode_get(0xFF); 61 | munit_assert_not_null(op); 62 | munit_assert_string_equal(op->name, "bbs7"); 63 | munit_assert_uint8(op->size, ==, 3U); 64 | munit_assert_uint8(op->type, ==, PCE_OP_ZZ_lbl); 65 | 66 | op = opcode_get(0x2B); 67 | munit_assert_not_null(op); 68 | munit_assert_string_equal(op->name, ".db "); 69 | munit_assert_uint8(op->size, ==, 1U); 70 | munit_assert_uint8(op->type, ==, PCE_unknown); 71 | 72 | return MUNIT_OK; 73 | } 74 | 75 | MunitResult opcodes_format_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 76 | const Opcode* op; 77 | unsigned int i; 78 | 79 | // tii 80 | op = opcode_get(0x73); 81 | munit_assert_uint8(op->type, ==, PCE_OP_shsl_dhdl_hhll); 82 | for(i=0; i<(op->size-1); i++) { // skip opcode 83 | munit_assert_not_null(opcode_format(op, i)); 84 | } 85 | for(; i<256; i++) { 86 | munit_assert_null(opcode_format(op, i)); 87 | } 88 | 89 | return MUNIT_OK; 90 | } 91 | 92 | MunitResult opcodes_jump_test(const MunitParameter params[] __attribute__((unused)), void* fixture __attribute__((unused))) { 93 | // local jump 94 | for(unsigned int i=0x0FU; i<0x100U; i+=0x10U) { 95 | munit_assert_true(opcode_is_local_jump(i)); // BBR* and BBS* 96 | } 97 | munit_assert_true(opcode_is_local_jump(0x90U)); // BCC 98 | munit_assert_true(opcode_is_local_jump(0xB0U)); // BCS 99 | munit_assert_true(opcode_is_local_jump(0x80U)); // BRA 100 | munit_assert_true(opcode_is_local_jump(0xF0U)); // BEQ 101 | munit_assert_true(opcode_is_local_jump(0x30U)); // BMI 102 | munit_assert_true(opcode_is_local_jump(0xD0U)); // BNE 103 | munit_assert_true(opcode_is_local_jump(0x10U)); // BPL 104 | munit_assert_true(opcode_is_local_jump(0x44U)); // BSR 105 | munit_assert_true(opcode_is_local_jump(0x50U)); // BVC 106 | munit_assert_true(opcode_is_local_jump(0x70U)); // BVS 107 | 108 | munit_assert_false(opcode_is_local_jump(0xEAU)); // NO 109 | munit_assert_false(opcode_is_local_jump(0x4CU)); // JMP 110 | munit_assert_false(opcode_is_local_jump(0x20U)); // JSP 111 | 112 | // far jump 113 | for(unsigned int i=0x0FU; i<0x100U; i+=0x10U) { 114 | munit_assert_false(opcode_is_far_jump(i)); // BBR* and BBS* 115 | } 116 | munit_assert_false(opcode_is_far_jump(0x90U)); // BCC 117 | munit_assert_false(opcode_is_far_jump(0xB0U)); // BCS 118 | munit_assert_false(opcode_is_far_jump(0x80U)); // BRA 119 | munit_assert_false(opcode_is_far_jump(0xF0U)); // BEQ 120 | munit_assert_false(opcode_is_far_jump(0x30U)); // BMI 121 | munit_assert_false(opcode_is_far_jump(0xD0U)); // BNE 122 | munit_assert_false(opcode_is_far_jump(0x10U)); // BPL 123 | munit_assert_false(opcode_is_far_jump(0x44U)); // BSR 124 | munit_assert_false(opcode_is_far_jump(0x50U)); // BVC 125 | munit_assert_false(opcode_is_far_jump(0x70U)); // BVS 126 | 127 | munit_assert_false(opcode_is_far_jump(0xEAU)); // NOP 128 | munit_assert_true(opcode_is_far_jump(0x4CU)); // JMP 129 | munit_assert_true(opcode_is_far_jump(0x20U)); // JSR 130 | 131 | return MUNIT_OK; 132 | } 133 | 134 | static MunitTest opcodes_tests[] = { 135 | { "/get", opcodes_get_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 136 | { "/format", opcodes_format_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 137 | { "/jump", opcodes_jump_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 138 | { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } 139 | }; 140 | 141 | static const MunitSuite opcodes_suite = { 142 | "Opcodes test suite", opcodes_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE 143 | }; 144 | 145 | int main (int argc, char* const* argv) { 146 | return munit_suite_main(&opcodes_suite, NULL, argc, argv); 147 | } -------------------------------------------------------------------------------- /test/rom.c: -------------------------------------------------------------------------------- 1 | /* 2 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 3 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 4 | 5 | __/¯\____ ___/\__ _/\__ _/\_ _/\__ _/\___ ___/\__ __/\_ _/\__ 6 | \_ ____/_> ____ \_/ _ \_ \ < /_ \_/ _>> ____ \_ > \_/ _ \_ 7 | _> ___/ ¯>__> <<__// __ _/ |> > <<__// /\ // __ _/ 8 | _> \7 <__/:. \__/:. \> \_/ L/ _____/. 7> .\_/:. \__/ <_/ \_ 9 | |:::::::::::::::::::::::/:::::::::::::>::::::::/::::::::::::::::::::::::/:::::| 10 | |¯¯\::::/\:/¯\::::/¯¯¯¯<::::/\::/¯¯\:/¯¯¯¯¯¯\::\::/¯¯\::::/¯¯\::::/¯¯¯¯<::::/¯| 11 | |__ |¯¯| T _ |¯¯¯| ___ |¯¯| |¯| _ T ______ |¯¯¯¯| _ |¯¯¯| _ |¯¯¯| ___ |¯¯| _| 12 | \|__|/\|/ \|___|/ \|__|/\|_|/ \|/ \| |/ \|___|/ \|___|/dNo\|__|/ 13 | 14 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 15 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 16 | 17 | This file is part of Etripator, 18 | copyright (c) 2009--2024 Vincent Cruz. 19 | 20 | Etripator is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | Etripator is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with Etripator. If not, see . 32 | 33 | ¬°¤*,¸¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸ 34 | ¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯¬°¤*,¸_¸,*¤°¬°¤*,¸,*¤°¬¯ 35 | */ 36 | #include 37 | 38 | #include 39 | 40 | #include 41 | #include 42 | 43 | #include 44 | 45 | DEFINE_FFF_GLOBALS; 46 | 47 | // [NOTE] munit is using fileno. If a test fails, munit will loop indefinitely :/ 48 | 49 | FAKE_VALUE_FUNC(FILE*, __wrap_fopen, const char*, const char*) 50 | FAKE_VALUE_FUNC(int, __wrap_fileno, FILE*) 51 | FAKE_VALUE_FUNC(int, __wrap_fstat, int, struct stat*) 52 | FAKE_VALUE_FUNC(int, __wrap_fseek, FILE*, long, int) 53 | FAKE_VALUE_FUNC(size_t, __wrap_fread, void*, size_t, size_t, FILE*) 54 | FAKE_VALUE_FUNC(int, __wrap_fclose, FILE*) 55 | 56 | static int fstat_empty_file(int fd __attribute__((unused)), struct stat* infos) { 57 | memset(infos, 0, sizeof(struct stat)); 58 | infos->st_size = 0; 59 | return 0; 60 | } 61 | 62 | static size_t g_dummy_file_size; 63 | 64 | static int fstat_dummy_file(int fd __attribute__((unused)), struct stat* infos) { 65 | infos->st_size = g_dummy_file_size; 66 | return 0; 67 | } 68 | 69 | static size_t fread_dummy(void* out, size_t size, size_t nmemb, FILE* in __attribute__((unused))) { 70 | uint8_t *ptr = (uint8_t*)out; 71 | uint8_t b = 0; 72 | for(size_t j=0; j 8kb 140 | 141 | static MunitTest rom_tests[] = { 142 | { "/load/small", rom_load_small_test, setup, tear_down, MUNIT_TEST_OPTION_NONE, NULL }, 143 | { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } 144 | }; 145 | 146 | static const MunitSuite rom_suite = { 147 | "ROM test suite", rom_tests, NULL, 1, MUNIT_SUITE_OPTION_NONE 148 | }; 149 | 150 | int main (int argc, char* const* argv) { 151 | message_printer_init(); 152 | console_message_printer_init(); 153 | 154 | int ret = munit_suite_main(&rom_suite, NULL, argc, argv); 155 | 156 | message_printer_destroy(); 157 | 158 | return ret; 159 | } --------------------------------------------------------------------------------