├── .github └── workflows │ ├── build-docker.yml │ └── build-win-native.yml ├── .gitignore ├── .vscode ├── launch.json ├── launch.json.gdb.bak ├── settings.json └── tasks.json ├── CMake ├── toolchain.libdragon.cmake ├── toolchain.libultra.cmake └── toolchain.mips64-elf.cmake ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── UpdateToolchain.ps1 ├── docs └── images │ ├── vscode-extensions.png │ └── vscode-set-variant.png ├── inc ├── flashcart.h └── version.h └── src └── main.c /.github/workflows/build-docker.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build the exmple ROM to keep it up-to-date. 2 | name: Build CMake ROM with docker 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | cmake-container-build: 9 | runs-on: ubuntu-latest 10 | container: 11 | image: ghcr.io/n64-tools/gcc-toolchain-mips64:latest 12 | credentials: 13 | username: ${{ github.actor }} 14 | password: ${{ secrets.github_token }} 15 | volumes: 16 | - my_docker_volume:/volume_mount 17 | 18 | steps: 19 | - name: Check for dockerenv file 20 | run: (ls /.dockerenv && echo Found dockerenv) || (echo No dockerenv) 21 | 22 | - name: Checkout Code 23 | uses: actions/checkout@v3 24 | with: 25 | fetch-depth: 1 # we only require the last check-in, unless we want to create a changelog. 26 | 27 | - name: Checkout latest libdragon lib Code 28 | uses: actions/checkout@v3 29 | with: 30 | repository: dragonminded/libdragon 31 | ref: trunk # NOTE: update this if you want to use a specific branch e.g. `opengl` 32 | path: libdragon-build 33 | fetch-depth: 1 # we only require the last check-in, unless we want to create a changelog. 34 | 35 | - name: Build libdragon and tools 36 | run: | 37 | cd libdragon-build 38 | make libdragon 39 | make tools 40 | continue-on-error: true 41 | 42 | # TODO: move to a seperate job?! 43 | - name: Generate toolchain 44 | run: | 45 | mkdir -p toolchain/libdragon/include/ 46 | cp ./libdragon-build/include/* toolchain/libdragon/include/ 47 | mkdir -p toolchain/libdragon/lib/ 48 | cp ./libdragon-build/*.a toolchain/libdragon/lib/ 49 | mkdir -p toolchain/libdragon/ldscripts/ 50 | cp ./libdragon-build/*.ld ./toolchain/libdragon/ldscripts/ 51 | mkdir -p toolchain/libdragon/headers/ 52 | cp ./libdragon-build/header ./toolchain/libdragon/headers/ 53 | mkdir -p toolchain/libdragon/tools/ 54 | cp -r ./libdragon-build/tools/ ./toolchain/libdragon/ 55 | 56 | # Clean up the tools. 57 | rm -rf ./toolchain/libdragon/tools/*.sh 58 | rm -rf ./toolchain/libdragon/tools/Makefile 59 | rm -rf ./toolchain/libdragon/tools/*.c 60 | rm -rf ./toolchain/libdragon/tools/*.h 61 | 62 | rm -rf ./toolchain/libdragon/tools/mkdfs/Makefile 63 | rm -rf ./toolchain/libdragon/tools/mkdfs/*.c 64 | rm -rf ./toolchain/libdragon/tools/mkdfs/*.h 65 | 66 | rm -rf ./toolchain/libdragon/tools/dumpdfs/Makefile 67 | rm -rf ./toolchain/libdragon/tools/dumpdfs/*.c 68 | rm -rf ./toolchain/libdragon/tools/dumpdfs/*.h 69 | 70 | rm -rf ./toolchain/libdragon/tools/audioconv64/Makefile 71 | rm -rf ./toolchain/libdragon/tools/audioconv64/*.c 72 | rm -rf ./toolchain/libdragon/tools/audioconv64/*.h 73 | 74 | rm -rf ./toolchain/libdragon/tools/mksprite/Makefile 75 | rm -rf ./toolchain/libdragon/tools/mksprite/*.c 76 | rm -rf ./toolchain/libdragon/tools/mksprite/*.h 77 | continue-on-error: true 78 | 79 | # - name: Check directory output 80 | # run: | 81 | # echo 'default directory listing:' 82 | # ls -R . 83 | # continue-on-error: true 84 | 85 | - name: Create ROM output DIR 86 | run: | 87 | mkdir ./build 88 | continue-on-error: true 89 | 90 | - name: Generate CMake files 91 | run: >- 92 | cd ./build && cmake -G Ninja 93 | -DCMAKE_TOOLCHAIN_FILE=$PWD/../CMake/toolchain.libdragon.cmake 94 | -DTOOLCHAIN_PREFIX=$PWD/../toolchain/gcc-toolchain-mips64 95 | -DLIBDRAGON_PREFIX=$PWD/../toolchain/libdragon 96 | -DHARDWARE_TYPE=ALL 97 | -DSDK_TYPE=LIBDRAGON 98 | -DCMAKE_MAKE_PROGRAM=ninja 99 | $PWD/../ 100 | continue-on-error: true 101 | 102 | - name: Build ROM using CMake 103 | run: | 104 | cmake --build ./build --target all --config Release 105 | continue-on-error: true 106 | 107 | - name: Publish Build Artifacts 108 | uses: actions/upload-artifact@v3 109 | with: 110 | name: DOCKER-GENERATED-ROM 111 | path: | 112 | ./build/*.elf 113 | ./build/*.bin 114 | ./build/*.v64 115 | continue-on-error: true -------------------------------------------------------------------------------- /.github/workflows/build-win-native.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build the exmple ROM to keep it up-to-date. 2 | name: Build CMake ROM with windows 3 | 4 | on: 5 | push: 6 | pull_request: 7 | 8 | jobs: 9 | build-rom: 10 | runs-on: windows-latest 11 | strategy: 12 | fail-fast: false 13 | 14 | steps: 15 | - name: Checkout Code 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 1 # we only require the last check-in, unless we want to create a changelog. 19 | 20 | # # Cache and restore dependencies instead of downloading them to increase build speed. 21 | # # Expires after 7 days. 22 | # - uses: actions/cache@v3 23 | # id: cache 24 | # with: 25 | # path: | 26 | # ./toolchain/**/*.tar.gz 27 | # ./toolchain/**/*.tar.bz2 28 | # key: ${{ runner.os }}-dependency-downloads # TODO: concurrency errors may currently occur due to matrix, but they are the same files. 29 | 30 | - name: Get toolchain dependencies 31 | run: | 32 | echo 'Downloading dependencies' 33 | ./UpdateToolchain.ps1 34 | continue-on-error: true 35 | 36 | # - name: Check toolchain directory output 37 | # run: | 38 | # echo 'toolchain directory listing:' 39 | # ls -R ./toolchain/libdragon/ 40 | # continue-on-error: true 41 | 42 | # - name: Add libdragon tools to PATH 43 | # run: setx PATH "%PATH%;${{ github.workspace }}\toolchain\libdragon\tools" 44 | 45 | - name: Create ROM output DIR 46 | run: | 47 | mkdir ${{ github.workspace }}/build 48 | 49 | - name: Generate CMake files 50 | run: >- 51 | cd ${{ github.workspace }}/build && cmake -G Ninja 52 | -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/CMake/toolchain.libdragon.cmake 53 | -DTOOLCHAIN_PREFIX=${{ github.workspace }}/toolchain/gcc-toolchain-mips64 54 | -DLIBDRAGON_PREFIX=${{ github.workspace }}/toolchain/libdragon 55 | -DHARDWARE_TYPE=ALL 56 | -DSDK_TYPE=LIBDRAGON 57 | -DCMAKE_MAKE_PROGRAM=${{ github.workspace }}/tools/ninja.exe 58 | ${{ github.workspace }} 59 | continue-on-error: true 60 | 61 | - name: Build ROM using CMake 62 | run: | 63 | cmake --build ${{ github.workspace }}/build --target all --config Release 64 | continue-on-error: true 65 | 66 | # - name: Check build output 67 | # run: | 68 | # echo 'build dir listing:' 69 | # cd ${{ github.workspace }}/build 70 | # ls -R . 71 | # continue-on-error: true 72 | 73 | - name: Publish Build Artifacts 74 | uses: actions/upload-artifact@v3 75 | with: 76 | name: WIN-NATIVE-GENERATED-ROM 77 | path: | 78 | **/build/*.elf 79 | **/build/*.bin 80 | **/build/*.v64 81 | continue-on-error: true 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeLists.txt.user 2 | CMakeCache.txt 3 | CMakeFiles 4 | CMakeScripts 5 | Testing 6 | Makefile 7 | cmake_install.cmake 8 | install_manifest.txt 9 | compile_commands.json 10 | CTestTestfile.cmake 11 | _deps 12 | 13 | /toolchain/ 14 | /build/ 15 | /tools/ 16 | /temp/ 17 | /out/ 18 | .vs/ 19 | 20 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch debug ROM on ares Emulator", 6 | "type": "node", 7 | "request": "attach", // uses attach rather than launch so that it closes autmatically. 8 | "preLaunchTask": "ares-emulator", // Called in tasks.json 9 | }, 10 | { 11 | "name": "Launch debug ROM on ED64 via USB", 12 | "type": "node", 13 | "request": "attach", 14 | "preLaunchTask": "ed64-usb", // Called in tasks.json 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /.vscode/launch.json.gdb.bak: -------------------------------------------------------------------------------- 1 | // { 2 | // "version": "0.2.0", 3 | // "configurations": [ 4 | // { 5 | // "name": "LibDragon", 6 | // "type": "cppdbg", 7 | // "request": "launch", 8 | // "miDebuggerPath": "${workspaceFolder}/toolchain/gcc-toolchain-mips64/bin/mips64-elf-gdb.exe", 9 | // "targetArchitecture": "vr4300", 10 | // "program": "${workspaceFolder}/build/BUILD-DEMO.elf", 11 | 12 | // "setupCommands": [ 13 | // {"text": "target extended-remote localhost:3333"}, 14 | // {"text": "monitor reset_config none separate"}, 15 | // {"text": "monitor reset halt"}, 16 | // {"text": "monitor flash write_image erase \"${workspaceFolder}/build/BUILD-DEMO.hex\" "}, //this one definitely needs changing! 17 | // {"text": "file ${workspaceFolder}/build/BUILD-DEMO.elf"}, 18 | // {"text": "monitor reset halt"} 19 | // ], 20 | 21 | // "customLaunchSetupCommands": [ 22 | // {"text": "monitor reset_config none separate"}, 23 | // {"text": "monitor reset halt"} 24 | // ], 25 | 26 | // "launchCompleteCommand": "exec-continue", 27 | // "debugServerPath": "C:/Program Files/GNU ARM Eclipse/OpenOCD/0.10.0-201704182147-dev/bin/openocd.exe", 28 | // "debugServerArgs": "-s \"C:/Program Files/GNU ARM Eclipse/OpenOCD/0.10.0-201704182147-dev/scripts/\" -f interface/stlink-v2.cfg -f board/stm32f7discovery.cfg", //this also needs changing! 29 | // "serverStarted": "Info\\ :\\ [\\w\\d\\.]*:\\ hardware", 30 | // "filterStderr": true, 31 | // "externalConsole": true, 32 | // "cwd": "${workspaceFolder}" 33 | // // Enable the following to debug GDB 34 | // //"logging": { 35 | // // "engineLogging": true, 36 | // // "traceResponse": true 37 | // //}, 38 | // } 39 | // ] 40 | // } 41 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cmake.preferredGenerators": [ 3 | "Ninja" 4 | ], 5 | "cmake.generator": "Ninja", 6 | "cmake.autoRestartBuild" : true, 7 | "cmake.configureSettings": { 8 | "CMAKE_MAKE_PROGRAM": "${workspaceFolder}/tools/ninja.exe" 9 | }, 10 | "cmake.cmakePath": "C:/Program Files/CMake/bin/cmake.exe", 11 | "cmake.configureOnOpen": false, 12 | "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools" 13 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "ares-emulator", 6 | "command": "${workspaceFolder}/tools/ares-windows-msvc-x64/ares-v131/ares", 7 | "args": ["${workspaceFolder}/build/${input:releaseType}/BUILD-DEMO.z64"], 8 | "type": "shell", 9 | "presentation": { 10 | "reveal": "silent", 11 | "close": true 12 | } 13 | }, 14 | { 15 | "label": "ed64-usb", 16 | "command": "${workspaceFolder}/tools/ed64-usb/usbtool", 17 | "args": ["${workspaceFolder}/build/${input:releaseType}/BUILD-DEMO.z64"], 18 | "type": "shell", 19 | "presentation": { 20 | "reveal": "silent", 21 | "close": true 22 | } 23 | } 24 | ], 25 | "inputs": [ 26 | { 27 | "type": "pickString", 28 | "id": "releaseType", 29 | "description": "What build type do you want to run?", 30 | "options": [ 31 | "debug-rom", 32 | "release-rom" 33 | ], 34 | "default": "debug-rom" 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /CMake/toolchain.libdragon.cmake: -------------------------------------------------------------------------------- 1 | option(TOOLCHAIN_LIBDRAGON "Use LIBDRAGON" ON) #only set if this file is called~? 2 | 3 | include_directories( 4 | ${LIBDRAGON_PREFIX}/include 5 | ) 6 | 7 | link_directories( 8 | ${LIBDRAGON_PREFIX}/lib/ 9 | ) 10 | 11 | link_libraries( 12 | dragon 13 | ) 14 | 15 | # set the necessary tools we need for building the rom 16 | set(N64_TOOL ${LIBDRAGON_PREFIX}/tools/n64tool) 17 | set(CHECKSUM_TOOL ${LIBDRAGON_PREFIX}/tools/chksum64) 18 | set(ED64ROMCONFIG_TOOL ${LIBDRAGON_PREFIX}/tools/ed64romconfig) 19 | set(MKDFS_TOOL ${LIBDRAGON_PREFIX}/tools/mkdfs/mkdfs) 20 | set(DUMPDFS_TOOL ${LIBDRAGON_PREFIX}/tools/dumpdfs/dumpdfs) 21 | set(AUDIOCONV_TOOL ${LIBDRAGON_PREFIX}/tools/audioconv64/audioconv64) 22 | set(MKSPRITE_TOOL ${LIBDRAGON_PREFIX}/tools/mksprite/mksprite) 23 | set(MKSPRITECONV_TOOL ${LIBDRAGON_PREFIX}/tools/mksprite/convtool) 24 | 25 | 26 | set(RSP_ASFLAGS "-march=mips1 -mabi=32 -Wa,--fatal-warnings") # TODO: add to compile 27 | 28 | set(LINKER_FLAGS_START "-ldragon") 29 | set(LINKER_FLAGS_END "-ldragonsys -Wl,--gc-sections -Wl,--wrap __do_global_ctors") 30 | 31 | 32 | include(${CMAKE_CURRENT_LIST_DIR}/toolchain.mips64-elf.cmake) -------------------------------------------------------------------------------- /CMake/toolchain.libultra.cmake: -------------------------------------------------------------------------------- 1 | # TODO: this file is incomplete!!!! 2 | option(TOOLCHAIN_LIBULTRA "Use LIBULTRA" ON) #only set if this file is called~? 3 | 4 | 5 | include_directories( 6 | ${LIBULTRA_PREFIX}/include 7 | ) 8 | 9 | link_directories( 10 | ${LIBULTRA_PREFIX}/lib/ 11 | ) 12 | 13 | # link_libraries( 14 | # dragon 15 | # ) 16 | 17 | # set the necessary tools we need for building the rom 18 | # set(N64_TOOL ${LIBULTRA_PREFIX}/tools/spicy) 19 | # set(CHECKSUM_TOOL ${LIBULTRA_PREFIX}/tools/checksum) 20 | 21 | # set(LINKER_FLAGS_START "-ldragon") 22 | # set(LINKER_FLAGS_END "-ldragonsys") 23 | 24 | 25 | include(${CMAKE_CURRENT_LIST_DIR}/toolchain.mips64-elf.cmake) -------------------------------------------------------------------------------- /CMake/toolchain.mips64-elf.cmake: -------------------------------------------------------------------------------- 1 | include(CMakeForceCompiler) 2 | 3 | # set toolchain directories 4 | set(TOOLCHAIN_BIN_DIR ${TOOLCHAIN_PREFIX}/bin) 5 | 6 | # the name of the operating system for which CMake is to build 7 | set(CMAKE_SYSTEM_NAME Generic) 8 | 9 | # name of the CPU CMake is building for 10 | set(CMAKE_SYSTEM_PROCESSOR mips64) 11 | 12 | # set the language standard (gnu-99) 13 | set(CMAKE_C_STANDARD 99) 14 | set(CMAKE_C_STANDARD_REQUIRED TRUE) 15 | set(CMAKE_CXX_STANDARD 99) 16 | set(CMAKE_CXX_STANDARD_REQUIRED TRUE) 17 | 18 | # macro to setup compilers 19 | macro(SET_COMPILER_VAR var name) 20 | find_program(CMAKE_${var} mips64-elf-${name} HINTS ${TOOLCHAIN_BIN_DIR} DOC "${name} tool") 21 | endmacro() 22 | 23 | # setup C compiler 24 | if(NOT CMAKE_C_COMPILER) 25 | SET_COMPILER_VAR(C_COMPILER gcc) 26 | endif() 27 | 28 | # setup C++ compiler 29 | if(NOT CMAKE_CXX_COMPILER) 30 | SET_COMPILER_VAR(CXX_COMPILER g++) 31 | endif() 32 | 33 | # setup Assembler compiler 34 | if(NOT CMAKE_ASM_COMPILER) 35 | SET_COMPILER_VAR(ASM_COMPILER gcc) 36 | SET_COMPILER_VAR(ASM-ATT_COMPILER as) 37 | endif() 38 | 39 | include_directories( 40 | ${TOOLCHAIN_PREFIX}/mips64-elf/include 41 | ${TOOLCHAIN_PREFIX}/include 42 | ) 43 | 44 | link_directories( 45 | ${TOOLCHAIN_PREFIX}/lib 46 | ${TOOLCHAIN_PREFIX}/mips64-elf/lib 47 | ) 48 | 49 | link_libraries( 50 | libc.a 51 | libm.a 52 | ) 53 | 54 | set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 55 | set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 56 | set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 57 | set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) 58 | 59 | # this makes the test compiles use static library option so that we don't need to pre-set linker flags and scripts 60 | set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) 61 | 62 | # set the flags for an N64's architecture 63 | set(MCPU_FLAGS "-march=vr4300 -mtune=vr4300 -MMD") 64 | 65 | set(EXTRA_FLAGS_OPTIMIZATION "-falign-functions=32 -ffunction-sections -fdata-sections") 66 | set(EXTRA_FLAGS_WARNINGS "-Wall -Werror -Wno-error=deprecated-declarations -fdiagnostics-color=always") 67 | 68 | set(CMAKE_C_CXX_FLAGS "${MCPU_FLAGS} ${EXTRA_FLAGS_OPTIMIZATION} ${EXTRA_FLAGS_WARNINGS}") 69 | set(CMAKE_C_CXX_FLAGS_DEBUG "-O0 -g3") # TODO: -ggdb3 70 | set(CMAKE_C_CXX_FLAGS_RELEASE "-O2") 71 | 72 | set(CMAKE_C_FLAGS "${CMAKE_C_CXX_FLAGS}" CACHE INTERNAL "c compiler flags") 73 | set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_CXX_FLAGS_DEBUG}" ) 74 | set(CMAKE_C_FLAGS_RELEASE " ${CMAKE_C_CXX_FLAGS_RELEASE}" ) 75 | 76 | set(CMAKE_CXX_FLAGS "${CMAKE_C_CXX_FLAGS}" CACHE INTERNAL "cxx compiler flags") 77 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_CXX_FLAGS_DEBUG}" ) 78 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_C_CXX_FLAGS_RELEASE}" ) 79 | 80 | set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} -Wa,--fatal-warnings" CACHE INTERNAL "asm compiler flags") 81 | set(CMAKE_ASM_FLAGS_DEBUG "-g" ) 82 | set(CMAKE_ASM_FLAGS_RELEASE "" ) 83 | 84 | set(CMAKE_EXE_LINKER_FLAGS "-g ${LINKER_FLAGS_START} -lc -lm ${LINKER_FLAGS_END}" CACHE INTERNAL "exe link flags") 85 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.23) 2 | 3 | include(CMakeToolsHelpers OPTIONAL) 4 | include(ExternalProject) 5 | 6 | set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "ON" FORCE) # debug helper 7 | 8 | message(STATUS "\n\nINFO: Running CMake ${CMAKE_VERSION}\n\n") 9 | 10 | # the following prevents launching a build in the source tree 11 | set(CMAKE_DISABLE_SOURCE_CHANGES ON) 12 | set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) 13 | 14 | # fatal error and message explaining this 15 | if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) 16 | message(STATUS "\n-- ###############################################\n") 17 | message(STATUS "Please run the build outside of the source tree.\n\n") 18 | message(STATUS "Hint: create a 'build' folder and run CMake from there..") 19 | message(STATUS "###############################################\n\n") 20 | message(FATAL_ERROR "Build launched in the source tree.") 21 | endif() 22 | 23 | # set time stamp of build 24 | string(TIMESTAMP BUILD_TIMESTAMP UTC) 25 | 26 | message(STATUS "Building for hardware type: ${HARDWARE_TYPE}") 27 | message(STATUS "Using SDK: ${SDK_TYPE}") 28 | 29 | # make sure the version is set 30 | if(NOT BUILD_VERSION) 31 | set(BUILD_VERSION 0.0.1) 32 | endif() 33 | 34 | message(STATUS "ROM version is: ${BUILD_VERSION}") 35 | message(STATUS "Tweek Timestamp is: ${BUILD_TIMESTAMP}") 36 | 37 | string(REPLACE "." ";" VERSION_LIST ${BUILD_VERSION}) 38 | list(GET VERSION_LIST 0 BUILD_VER_MAJOR) 39 | list(GET VERSION_LIST 1 BUILD_VER_MINOR) 40 | list(GET VERSION_LIST 2 BUILD_VER_REV) 41 | 42 | project(BUILD-DEMO # rename for your ROM name 43 | VERSION ${BUILD_VERSION} 44 | LANGUAGES C ASM) 45 | 46 | 47 | set( ELF_NAME ${PROJECT_NAME}.elf ) 48 | set( BIN_NAME ${PROJECT_NAME}.bin ) 49 | set( ROM_NAME ${PROJECT_NAME}.z64 ) 50 | 51 | set( LINKER_FILE_NAME "${LIBDRAGON_PREFIX}/ldscripts/n64.ld" ) 52 | set(ROM_HEADER ${LIBDRAGON_PREFIX}/headers/header) 53 | 54 | add_executable( ${ELF_NAME} 55 | # Add libs here: 56 | #${LIBDRAGON_SOURCES} 57 | #${FATFS_SOURCES} 58 | ) 59 | 60 | target_compile_definitions( ${ELF_NAME} PUBLIC 61 | ROM_VER_MAJOR=${BUILD_VER_MAJOR} 62 | ROM_VER_MINOR=${BUILD_VER_MINOR} 63 | ROM_VER_REV=${BUILD_VER_REV} 64 | ROM_VER_TWEEK=${BUILD_TIMESTAMP} 65 | FLASHCART_TARGET_TYPE=${HARDWARE_TYPE} 66 | FLASHCART_TARGET_REVISION=${HARDWARE_REVISION} 67 | ) 68 | 69 | target_sources( ${ELF_NAME} 70 | PUBLIC 71 | # Add your source files here: 72 | ${CMAKE_CURRENT_LIST_DIR}/src/main.c 73 | ) 74 | 75 | # probably a better way to do this, but if you need to build for something that uses different compiler flags... 76 | #SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_LIST_DIR}/src/gscore.c PROPERTIES COMPILE_FLAGS -O0) 77 | 78 | target_include_directories( ${ELF_NAME} 79 | PUBLIC 80 | ${CMAKE_CURRENT_LIST_DIR}/inc 81 | # Add extra includes from libs here: 82 | #${LIBDRAGON_INCLUDE_DIRS} 83 | #${FATFS_INCLUDE_DIRS} 84 | ) 85 | 86 | target_link_directories( ${ELF_NAME} 87 | PUBLIC 88 | ${CMAKE_CURRENT_LIST_DIR}/lib 89 | ) 90 | 91 | set_target_properties( ${ELF_NAME} 92 | PROPERTIES LINK_FLAGS "-T${LINKER_FILE_NAME}" 93 | ) 94 | 95 | add_custom_command(TARGET ${ELF_NAME} 96 | POST_BUILD 97 | COMMAND ${CMAKE_OBJCOPY} ARGS -O binary ${ELF_NAME} ${BIN_NAME} 98 | ) 99 | 100 | # if the toolchain is different, we need to handle it here, or push it to a module, or even the toolchain?! 101 | if(TOOLCHAIN_LIBDRAGON) 102 | 103 | # # FIXME: There is a regression with N64-Tool where it cannot overwrite an existing file. 104 | # # This command is a workaround: 105 | # add_custom_command(TARGET ${ELF_NAME} 106 | # POST_BUILD # Delete the ROM file so it can be overwritten by N64Tool 107 | # COMMAND DEL -F ${ROM_NAME} 108 | # ) 109 | 110 | add_custom_command(TARGET ${ELF_NAME} 111 | POST_BUILD # Make sure your ROM size is big enough... perhaps we could use "size" on the bin to check? 112 | COMMAND ${N64_TOOL} ARGS -l 1M -t "${PROJECT_NAME}" -h ${ROM_HEADER} -o ${ROM_NAME} ${BIN_NAME} 113 | ) 114 | 115 | add_custom_command(TARGET ${ELF_NAME} 116 | POST_BUILD 117 | COMMAND ${CHECKSUM_TOOL} ARGS ${ROM_NAME} 118 | ) 119 | else() # add some other compilation flags 120 | # show error? 121 | endif(TOOLCHAIN_LIBDRAGON) 122 | unset(TOOLCHAIN_LIBDRAGON CACHE) # <---- this is the important to make sure the next build succeeds!! 123 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 4, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 23, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "general-preset", 11 | "displayName": "Set Variables", 12 | "description": "Sets ROM and libdragon SDK variables", 13 | "hidden": true, 14 | "cacheVariables": { 15 | "SDK_TYPE": "LIBDRAGON", 16 | "HARDWARE_TYPE" : "ALL", 17 | "HARDWARE_REVISION" : "0", 18 | "BUILD_VERSION" : "0.0.1", 19 | "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/CMake/toolchain.libdragon.cmake", 20 | "TOOLCHAIN_PREFIX": "${sourceDir}/toolchain/gcc-toolchain-mips64", 21 | "LIBDRAGON_PREFIX": "${sourceDir}/toolchain/libdragon" 22 | } 23 | }, 24 | { 25 | "name": "release-rom", 26 | "displayName": "libdragon Release ROM", 27 | "description": "Builds ROM using libdragon SDK", 28 | "generator": "Ninja", 29 | "binaryDir": "${sourceDir}/build/${presetName}", 30 | "inherits": [ 31 | "general-preset" 32 | ], 33 | "cacheVariables": { 34 | "CMAKE_BUILD_TYPE": "Release" 35 | } 36 | }, 37 | { 38 | "name": "debug-rom", 39 | "displayName": "libdragon Debug ROM", 40 | "description": "Builds Debug ROM using libdragon SDK", 41 | "generator": "Ninja", 42 | "binaryDir": "${sourceDir}/build/${presetName}", 43 | "inherits": [ 44 | "general-preset" 45 | ], 46 | "cacheVariables": { 47 | "CMAKE_BUILD_TYPE": "Debug" 48 | } 49 | } 50 | ], 51 | "buildPresets": [ 52 | { 53 | "name": "Debug", 54 | "configurePreset": "debug-rom", 55 | "verbose": true, 56 | "cleanFirst": true 57 | }, 58 | { 59 | "name": "Release", 60 | "configurePreset": "release-rom", 61 | "verbose": true, 62 | "cleanFirst": true 63 | } 64 | ] 65 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cmake-demo-rom 2 | Generates a ROM built with CMake 3 | This uses the https://github.com/DragonMinded/libdragon/tree/trunk/examples/vtest (as of 2023-01-01) rom as a sample. 4 | 5 | ## Building 6 | Although there have been improvements, the latest libdragon does not (yet) support CMake out the box. 7 | All current steps below require at least one custom upstream component that may not always be inline with the latest available "official" improvements. 8 | 9 | ### Windows with VSCode 10 | Requirements: 11 | * Turning on Windows 10 or 11 developer mode Or Windows 7 with latest PowerShell version installed 12 | * Enabling Remote Powershell execution policy (`Set-ExecutionPolicy Unrestricted`) 13 | * a current version of [CMake](https://cmake.org/download/) (tested working with 3.18.4) to be installed (make sure the PATH variable is set). 14 | * VSCode with `CMake`, `CMake Tools` and `C/C++` extensions 15 | ![Required VSCode Extensions](docs/images/vscode-extensions.png) 16 | 17 | * Run `UpdateToolchain.ps1` to download the required toolchain and libdragon files 18 | * Adjust CMakePresets.json for your paths if necessary (although should work automatically out the box) 19 | * Adjust .vscode/settings.json for your paths (although should work automatically out the box) 20 | 21 | Building the ROM: 22 | In VS-Code 23 | * Click on the Bottom bar to set the "Configure Preset": ![CMake variant](docs/images/vscode-set-variant.png) 24 | * Hit `F7` to build the ROM 25 | 26 | ### Docker 27 | See the current [docker workflow file](.github/workflows/build-docker.yml) for how you can do it. 28 | By default, this build references the `trunk` branch. To change it, adjust the `ref: trunk` for the checkout. 29 | 30 | ## Launching ROM 31 | 32 | ### Windows with VSCode 33 | Uses `launch.json` via `tasks.json` contained in the `.vscode` folder. 34 | NOTE: By default the applications are not installed and the paths will require updating. 35 | Hit `F5` to load the ROM (once built). 36 | -------------------------------------------------------------------------------- /UpdateToolchain.ps1: -------------------------------------------------------------------------------- 1 | 2 | $filepath = "$PSScriptRoot/temp/" 3 | New-Item -ItemType Directory -Force -Path $filepath 4 | 5 | $url = "https://github.com/n64-tools/libdragon/releases/download/develop-dragonminded-windows-tools-latest/libdragon-library.zip" 6 | $output = "$PSScriptRoot/temp/libdragon.zip" 7 | $destination = "$PSScriptRoot/toolchain/libdragon/" 8 | 9 | if (Test-Path $output) 10 | { 11 | Remove-Item -LiteralPath $output -Force -Recurse 12 | } 13 | Write-Host "Downloading Libdragon..." 14 | (New-Object Net.WebClient).Downloadfile($url , $output) 15 | 16 | if (Test-Path $destination) 17 | { 18 | Remove-Item -LiteralPath $destination -Force -Recurse 19 | } 20 | Expand-Archive -Force -Path $output -DestinationPath $destination 21 | Write-Host "Downloaded Libdragon successfully." 22 | 23 | $url = "https://github.com/n64-tools/libdragon/releases/download/develop-dragonminded-windows-tools-latest/libdragon-tools-win_x86_64.zip" 24 | $output = "$PSScriptRoot/temp/libdragon-tools.zip" 25 | $destination = "$PSScriptRoot/toolchain/libdragon/" 26 | 27 | if (Test-Path $output) 28 | { 29 | Remove-Item -LiteralPath $output -Force -Recurse 30 | } 31 | Write-Host "Downloading Libdragon tools..." 32 | (New-Object Net.WebClient).Downloadfile($url , $output) 33 | 34 | # if (Test-Path $destination) 35 | # { 36 | # Remove-Item -LiteralPath $destination -Force -Recurse 37 | # } 38 | Expand-Archive -Force -Path $output -DestinationPath $destination 39 | Write-Host "Downloaded Libdragon tools successfully." 40 | 41 | $url = "https://github.com/n64-tools/gcc-toolchain-mips64/releases/download/latest/gcc-toolchain-mips64-win64.zip" 42 | $output = "$PSScriptRoot/temp/gcc-toolchain-mips64.zip" 43 | $destination = "$PSScriptRoot/toolchain/gcc-toolchain-mips64/" 44 | 45 | if (Test-Path $output) 46 | { 47 | Remove-Item -LiteralPath $output -Force -Recurse 48 | } 49 | Write-Host "Downloading GCC..." 50 | (New-Object Net.WebClient).Downloadfile($url , $output) 51 | if (Test-Path $destination) 52 | { 53 | Remove-Item -LiteralPath $destination -Force -Recurse 54 | } 55 | Expand-Archive -Force -Path $output -DestinationPath $destination 56 | Write-Host "Downloaded GCC Toolchain successfully." 57 | 58 | $url = "https://github.com/ninja-build/ninja/releases/latest/download/ninja-win.zip" 59 | $output = "$PSScriptRoot/temp/ninja.zip" 60 | $destination = "$PSScriptRoot/tools/" 61 | 62 | if (Test-Path $output) 63 | { 64 | Remove-Item -LiteralPath $output -Force -Recurse 65 | } 66 | Write-Host "Downloading Ninja-Build..." 67 | (New-Object Net.WebClient).Downloadfile($url , $output) 68 | if (Test-Path $destination) 69 | { 70 | Remove-Item -LiteralPath $destination -Force -Recurse 71 | } 72 | Expand-Archive -Force -Path $output -DestinationPath $destination 73 | Write-Host "Downloaded Ninja-Build successfully." 74 | 75 | $filepath = "$PSScriptRoot/temp/" 76 | if (Test-Path $filepath) 77 | { 78 | Remove-Item -LiteralPath $filepath -Force -Recurse 79 | } 80 | Write-Host "Finished cleanup of temp directories.." 81 | 82 | Write-Host "Toolchain install completed sucessfully." 83 | -------------------------------------------------------------------------------- /docs/images/vscode-extensions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n64-tools/cmake-demo-rom/96746daa1e1808e2a68f1540e37bacc0015fbfcf/docs/images/vscode-extensions.png -------------------------------------------------------------------------------- /docs/images/vscode-set-variant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/n64-tools/cmake-demo-rom/96746daa1e1808e2a68f1540e37bacc0015fbfcf/docs/images/vscode-set-variant.png -------------------------------------------------------------------------------- /inc/flashcart.h: -------------------------------------------------------------------------------- 1 | #ifndef FLASHCART_TARGET_TYPE 2 | #define FLASHCART_TARGET_TYPE "ALL" 3 | #endif 4 | #ifndef FLASHCART_TARGET_REVISION 5 | #define FLASHCART_TARGET_REVISION 0 6 | #endif -------------------------------------------------------------------------------- /inc/version.h: -------------------------------------------------------------------------------- 1 | #ifndef ROM_VER_MAJOR 2 | #define ROM_VER_MAJOR 0 3 | #endif 4 | #ifndef ROM_VER_MINOR 5 | #define ROM_VER_MINOR 0 6 | #endif 7 | #ifndef ROM_VER_REVISION 8 | #define ROM_VER_REVISION 1 9 | #endif 10 | #ifndef ROM_VER_TWEEK 11 | #define ROM_VER_TWEEK 0 12 | #endif -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "version.h" 9 | #include "flashcart.h" 10 | 11 | /* hardware definitions */ 12 | // Pad buttons 13 | #define A_BUTTON(a) ((a) & 0x8000) 14 | #define B_BUTTON(a) ((a) & 0x4000) 15 | #define Z_BUTTON(a) ((a) & 0x2000) 16 | #define START_BUTTON(a) ((a) & 0x1000) 17 | 18 | // D-Pad 19 | #define DU_BUTTON(a) ((a) & 0x0800) 20 | #define DD_BUTTON(a) ((a) & 0x0400) 21 | #define DL_BUTTON(a) ((a) & 0x0200) 22 | #define DR_BUTTON(a) ((a) & 0x0100) 23 | 24 | // Triggers 25 | #define TL_BUTTON(a) ((a) & 0x0020) 26 | #define TR_BUTTON(a) ((a) & 0x0010) 27 | 28 | // Yellow C buttons 29 | #define CU_BUTTON(a) ((a) & 0x0008) 30 | #define CD_BUTTON(a) ((a) & 0x0004) 31 | #define CL_BUTTON(a) ((a) & 0x0002) 32 | #define CR_BUTTON(a) ((a) & 0x0001) 33 | 34 | #define PAD_DEADZONE 5 35 | #define PAD_ACCELERATION 10 36 | #define PAD_CHECK_TIME 40 37 | 38 | 39 | unsigned short gButtons = 0; 40 | struct controller_data gKeys; 41 | 42 | volatile int gTicks; /* incremented every vblank */ 43 | 44 | /* input - do getButtons() first, then getAnalogX() and/or getAnalogY() */ 45 | unsigned short getButtons(int pad) 46 | { 47 | // Read current controller status 48 | controller_scan(); 49 | gKeys = get_keys_pressed(); 50 | return (unsigned short)(gKeys.c[0].data >> 16); 51 | } 52 | 53 | unsigned char getAnalogX(int pad) 54 | { 55 | return (unsigned char)gKeys.c[pad].x; 56 | } 57 | 58 | unsigned char getAnalogY(int pad) 59 | { 60 | return (unsigned char)gKeys.c[pad].y; 61 | } 62 | 63 | display_context_t lockVideo(int wait) 64 | { 65 | display_context_t dc; 66 | 67 | if (wait) 68 | while (!(dc = display_lock())); 69 | else 70 | dc = display_lock(); 71 | return dc; 72 | } 73 | 74 | void unlockVideo(display_context_t dc) 75 | { 76 | if (dc) 77 | display_show(dc); 78 | } 79 | 80 | /* text functions */ 81 | void drawText(display_context_t dc, char *msg, int x, int y) 82 | { 83 | if (dc) 84 | graphics_draw_text(dc, x, y, msg); 85 | } 86 | 87 | void printText(display_context_t dc, char *msg, int x, int y) 88 | { 89 | if (dc) 90 | graphics_draw_text(dc, x*8, y*8, msg); 91 | } 92 | 93 | /* vblank callback */ 94 | void vblCallback(void) 95 | { 96 | gTicks++; 97 | } 98 | 99 | void delay(int cnt) 100 | { 101 | int then = gTicks + cnt; 102 | while (then > gTicks) ; 103 | } 104 | 105 | /* initialize console hardware */ 106 | void init_n64(void) 107 | { 108 | /* Initialize peripherals */ 109 | display_init( RESOLUTION_320x240, DEPTH_32_BPP, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE ); 110 | 111 | register_VI_handler(vblCallback); 112 | 113 | controller_init(); 114 | } 115 | 116 | /* main code entry point */ 117 | int main(void) 118 | { 119 | display_context_t _dc; 120 | char temp[128]; 121 | int res = 0; 122 | unsigned short buttons, previous = 0; 123 | 124 | init_n64(); 125 | 126 | while (1) 127 | { 128 | int j; 129 | int width[6] = { 320, 640, 256, 512, 512, 640 }; 130 | int height[6] = { 240, 480, 240, 480, 240, 240 }; 131 | unsigned int color; 132 | 133 | _dc = lockVideo(1); 134 | color = graphics_make_color(0xCC, 0xCC, 0xCC, 0xFF); 135 | graphics_fill_screen(_dc, color); 136 | 137 | color = graphics_make_color(0xFF, 0xFF, 0xFF, 0xFF); 138 | graphics_draw_line(_dc, 0, 0, width[res]-1, 0, color); 139 | graphics_draw_line(_dc, width[res]-1, 0, width[res]-1, height[res]-1, color); 140 | graphics_draw_line(_dc, width[res]-1, height[res]-1, 0, height[res]-1, color); 141 | graphics_draw_line(_dc, 0, height[res]-1, 0, 0, color); 142 | 143 | graphics_draw_line(_dc, 0, 0, width[res]-1, height[res]-1, color); 144 | graphics_draw_line(_dc, 0, height[res]-1, width[res]-1, 0, color); 145 | 146 | color = graphics_make_color(0x00, 0x00, 0x00, 0xFF); 147 | graphics_set_color(color, 0); 148 | 149 | // TODO: print line showing build version. 150 | // TODO: print line showing whether ROM is debug. 151 | // TODO: print line showing H/W and H/W Rev vars. 152 | printText(_dc, "Video Resolution Test", width[res]/16 - 10, 3); 153 | switch (res) 154 | { 155 | case 0: 156 | printText(_dc, "320x240p", width[res]/16 - 3, 5); 157 | break; 158 | case 1: 159 | printText(_dc, "640x480i", width[res]/16 - 3, 5); 160 | break; 161 | case 2: 162 | printText(_dc, "256x240p", width[res]/16 - 3, 5); 163 | break; 164 | case 3: 165 | printText(_dc, "512x480i", width[res]/16 - 3, 5); 166 | break; 167 | case 4: 168 | printText(_dc, "512x240p", width[res]/16 - 3, 5); 169 | break; 170 | case 5: 171 | printText(_dc, "640x240p", width[res]/16 - 3, 5); 172 | break; 173 | } 174 | 175 | for (j=0; j<8; j++) 176 | { 177 | sprintf(temp, "Line %d", j); 178 | printText(_dc, temp, 3, j); 179 | sprintf(temp, "Line %d", height[res]/8 - j - 1); 180 | printText(_dc, temp, 3, height[res]/8 - j - 1); 181 | } 182 | printText(_dc, "0123456789", 0, 16); 183 | printText(_dc, "9876543210", width[res]/8 - 10, 16); 184 | 185 | unlockVideo(_dc); 186 | 187 | while (1) 188 | { 189 | // wait for change in buttons 190 | buttons = getButtons(0); 191 | if (buttons ^ previous) 192 | break; 193 | delay(1); 194 | } 195 | 196 | if (A_BUTTON(buttons ^ previous)) 197 | { 198 | // A changed 199 | if (!A_BUTTON(buttons)) 200 | { 201 | resolution_t mode[6] = { 202 | RESOLUTION_320x240, 203 | RESOLUTION_640x480, 204 | RESOLUTION_256x240, 205 | RESOLUTION_512x480, 206 | RESOLUTION_512x240, 207 | RESOLUTION_640x240, 208 | }; 209 | res++; 210 | res %= 6; 211 | display_close(); 212 | display_init(mode[res], DEPTH_16_BPP, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE); 213 | } 214 | } 215 | 216 | previous = buttons; 217 | } 218 | 219 | return 0; 220 | } 221 | --------------------------------------------------------------------------------