├── .gitignore ├── .vscode └── c_cpp_properties.json ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── deploy.bat ├── genbuild.bat ├── neg.ld ├── neg_ram.ld ├── pico_sdk_import.cmake └── src ├── bf.c ├── bf.h ├── bf_table.c ├── coreboot.c ├── frm.c ├── main.c ├── memeloc.h ├── neg.c ├── neg.h ├── nicart.pio ├── picart_setup.c ├── picart_setup.h ├── png.c └── png.h /.gitignore: -------------------------------------------------------------------------------- 1 | /__pycache__/ 2 | /build/ 3 | /.vscode/settings.json 4 | *.bin 5 | /bf.txt 6 | /carttest.py 7 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": 3 | [ 4 | { 5 | "name": "Pi Pico", 6 | "includePath": 7 | [ 8 | "${workspaceFolder}/src/", 9 | "${workspaceFolder}/src/*", 10 | "C:/Programs/PicoSDK/**" 11 | ], 12 | "defines": 13 | [ 14 | 15 | ], 16 | "compilerPath": "C:/Programs/ARM_GCC/bin/arm-none-eabi-gcc.exe", 17 | "intelliSenseMode": "gcc-arm", 18 | "configurationProvider" : "ms-vscode.cmake-tools" 19 | } 20 | ], 21 | "version": 4 22 | } 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | include(pico_sdk_import.cmake) 4 | 5 | project(asd C CXX ASM) 6 | 7 | pico_sdk_init() 8 | 9 | add_executable(negcart 10 | src/main.c 11 | src/coreboot.c 12 | src/frm.c 13 | src/neg.c 14 | src/picart_setup.c 15 | src/bf_table.c 16 | src/bf.c 17 | src/png.c 18 | ) 19 | 20 | pico_generate_pio_header(negcart ${CMAKE_CURRENT_LIST_DIR}/src/nicart.pio) 21 | 22 | pico_set_linker_script(negcart ${CMAKE_CURRENT_LIST_DIR}/neg.ld) 23 | #pico_set_linker_script(negcart ${CMAKE_CURRENT_LIST_DIR}/neg_ram.ld) 24 | 25 | pico_set_binary_type(negcart blocked_ram) 26 | #pico_set_binary_type(negcart no_flash) 27 | 28 | target_link_libraries(negcart 29 | pico_stdlib 30 | pico_multicore 31 | hardware_pio 32 | hardware_dma 33 | hardware_gpio 34 | hardware_irq 35 | hardware_exception 36 | ) 37 | 38 | #target_compile_options(negcart PUBLIC -Os -g) 39 | #target_link_options(negcart PUBLIC -Os -g) 40 | 41 | #target_compile_definitions(hardware_timer INTERFACE PICO_TIME_DEFAULT_ALARM_POOL_DISABLED=1) 42 | 43 | pico_set_double_implementation(negcart none) 44 | pico_set_float_implementation(negcart none) 45 | 46 | add_compile_definitions(PICO_STDIO_USB_CONNECT_WAIT_TIMEOUT_MS=5000) 47 | add_compile_definitions(PICO_STDIO_USB_ENABLE_RESET_VIA_VENDOR_INTERFACE=0) 48 | add_compile_definitions(PICO_DEFAULT_UART_TX_PIN=0) 49 | add_compile_definitions(PICO_DEFAULT_UART_RX_PIN=1) 50 | add_compile_definitions(PICO_DEFAULT_UART_BAUD_RATE=115200) 51 | add_compile_definitions(PICO_PRINTF_ALWAYS_INCLUDED=1) 52 | add_compile_definitions(PICO_PRINTF_SUPPORT_LONG_LONG=0) 53 | add_compile_definitions(PICO_PRINTF_SUPPORT_FLOAT=0) 54 | add_compile_definitions(PICO_PRINTF_SUPPORT_EXPONENTIAL=0) 55 | add_compile_definitions(PICO_FLOAT_PROPAGATE_NANS=0) 56 | add_compile_definitions(PICO_NO_FPGA_CHECK=1) 57 | add_compile_definitions(PICO_FLOAT_SUPPORT_ROM_V1=0) 58 | add_compile_definitions(PICO_DOUBLE_SUPPORT_ROM_V1=0) 59 | #add_compile_definitions(PICO_RP2040_B1_SUPPORTED=0) 60 | #add_compile_definitions(PICO_RP2040_B2_SUPPORTED=0) 61 | 62 | pico_enable_stdio_uart(negcart 1) 63 | pico_enable_stdio_usb(negcart 0) 64 | 65 | pico_add_extra_outputs(negcart) 66 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2022 Sono (https://github.com/SonoSooS) 2 | All Rights Reserved 3 | 4 | The source code is provided only for educational and security-monitoring purposes. 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [REDACTED] 2 | 3 | > Note: The source code presented here is the public version of this project, modified to comply with Github's Terms of Service. While the public and private versions are functionally equal, the source code between them is not. 4 | 5 | 6 | After lots of optimization effort to push the RP2040's unique features to their absolute limit, it's finally possible to perform an ntrboot boot using this tool. 7 | 8 | 9 | ## Credits 10 | 11 | - profi200 for giving helpful tips and optimization ideas 12 | - aspargas2 for [minfirm](https://github.com/aspargas2/minfirm) 13 | - gbatek for the enPng/KEY2 crypto 14 | 15 | ## Usage 16 | 17 | > TODO: currently only [minfirm](https://github.com/aspargas2/minfirm) works with the public version, but some issues still need to be solved in the private version before it can be published 18 | 19 | > TODO: the Pico has to be unplugged and re-plugged after a successful and/or an unsuccessful boot because reset detection is currently broken in the private version (need a new Pico before I can investigate why) 20 | 21 | Hook up the pins to the cartridge adapter like this: 22 | - GP2 - GP9: DAT0 - DAT7 23 | - GND: GND 24 | - GP10: /CLK 25 | - GP11: /CS (or /CS1, for ROM select) 26 | - GP12 (unused): /CS2 (SPI flash select) 27 | - GP13 (currently unused, but needed for a later patch): /RST 28 | 29 | > Warning: DO NOT HOOK UP CARTRIDGE 3v3 TO THE PICO WITH USB CONNECTED! 30 | 31 | You need an USB power source (no data needed after programming) before turning the 3DS on, because the boot time of the Pico is way too slow to be able to use it standalone, even though the 3DS has no problem powering the Pico from the cartridge port alone. 32 | 33 | 34 | ## Building 35 | 36 | Before building, set your binary flavor in `CMakeLists.txt`: 37 | - for in-flash binary (should be default), uncomment the lines with `neg.ld` and `blocked_ram`, and comment out the lines with `neg_ram.ld` and `no_flash` 38 | - for in-RAM binary, it's a bit more complicated... 39 | - uncomment the lines with `neg_ram.ld` and `no_flash`, and comment out the lines with `blocked_ram` and `neg.ld` 40 | - follow the instructions at [oof2](https://github.com/SonoSooS/oof2) to patch your SDK 41 | - after successfully building the project, patch the resulting .uf2 to somewhere else using `oof2.py`, then you can drag that binary to the Pico's USB bootloader (unpatched .uf2 will not work, and will just stay there in the OS disk cache) 42 | 43 | > Note: On Windows you need to patch an older version of CMake (3.20), so it doesn't try overriding the ARM gcc used for building the source code with MSVC. 44 | 45 | > Notice: It's recommended to use the Ninja generator, as every other generator fails (for me) in some ways at compile-time. 46 | 47 | You can just build this like every other Pico SDK project. See `genbuild.bat` for an example way to invoke CMake from a `build` folder. 48 | 49 | Assuming you used the Ninja generator, just run `ninja -j1` from the `build` folder. 50 | 51 | > Note: on Windows you need native MSVC in PATH to build elf2uf2.exe successfully 52 | -------------------------------------------------------------------------------- /deploy.bat: -------------------------------------------------------------------------------- 1 | @C:\Python36\python ..\..\oof2\oof2.py negcart.uf2 %* 2 | -------------------------------------------------------------------------------- /genbuild.bat: -------------------------------------------------------------------------------- 1 | @cmake .. -G "Ninja" -DPICO_TOOLCHAIN_PATH=C:\Programs\ARM_GCC -DPICO_SDK_PATH=C:\Programs\PicoSDK -DPICO_BUILD_DOCS=0 %* 2 | -------------------------------------------------------------------------------- /neg.ld: -------------------------------------------------------------------------------- 1 | /* Based on GCC ARM embedded samples. 2 | Defines the following symbols for use by code: 3 | __exidx_start 4 | __exidx_end 5 | __etext 6 | __data_start__ 7 | __preinit_array_start 8 | __preinit_array_end 9 | __init_array_start 10 | __init_array_end 11 | __fini_array_start 12 | __fini_array_end 13 | __data_end__ 14 | __bss_start__ 15 | __bss_end__ 16 | __end__ 17 | end 18 | __HeapLimit 19 | __StackLimit 20 | __StackTop 21 | __stack (== StackTop) 22 | */ 23 | 24 | MEMORY 25 | { 26 | FLASH(rx) : ORIGIN = 0x10000000, LENGTH = 2048k 27 | RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 128k 28 | BANK2(rwx) : ORIGIN = 0x21020000, LENGTH = 64k 29 | BANK3(rwx) : ORIGIN = 0x21030000, LENGTH = 64k 30 | SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k 31 | SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k 32 | } 33 | 34 | ENTRY(_entry_point) 35 | 36 | SECTIONS 37 | { 38 | /* Second stage bootloader is prepended to the image. It must be 256 bytes big 39 | and checksummed. It is usually built by the boot_stage2 target 40 | in the Raspberry Pi Pico SDK 41 | */ 42 | 43 | .flash_begin : { 44 | __flash_binary_start = .; 45 | } > FLASH 46 | 47 | .boot2 : { 48 | __boot2_start__ = .; 49 | KEEP (*(.boot2)) 50 | __boot2_end__ = .; 51 | } > FLASH 52 | 53 | ASSERT(__boot2_end__ - __boot2_start__ == 256, 54 | "ERROR: Pico second stage bootloader must be 256 bytes in size") 55 | 56 | /* The second stage will always enter the image at the start of .text. 57 | The debugger will use the ELF entry point, which is the _entry_point 58 | symbol if present, otherwise defaults to start of .text. 59 | This can be used to transfer control back to the bootrom on debugger 60 | launches only, to perform proper flash setup. 61 | */ 62 | 63 | .text : { 64 | __logical_binary_start = .; 65 | KEEP (*(.vectors)) 66 | KEEP (*(.binary_info_header)) 67 | __binary_info_header_end = .; 68 | KEEP (*(.reset)) 69 | /* TODO revisit this now memset/memcpy/float in ROM */ 70 | /* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from 71 | * FLASH ... we will include any thing excluded here in .data below by default */ 72 | *(.init) 73 | *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .text*) 74 | *(.fini) 75 | /* Pull all c'tors into .text */ 76 | *crtbegin.o(.ctors) 77 | *crtbegin?.o(.ctors) 78 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 79 | *(SORT(.ctors.*)) 80 | *(.ctors) 81 | /* Followed by destructors */ 82 | *crtbegin.o(.dtors) 83 | *crtbegin?.o(.dtors) 84 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 85 | *(SORT(.dtors.*)) 86 | *(.dtors) 87 | 88 | *(.eh_frame*) 89 | . = ALIGN(4); 90 | } > FLASH 91 | 92 | .rodata : { 93 | *(EXCLUDE_FILE(*libgcc.a: *libc.a:*lib_a-mem*.o *libm.a:) .rodata*) 94 | . = ALIGN(4); 95 | *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) 96 | . = ALIGN(4); 97 | } > FLASH 98 | 99 | .ARM.extab : 100 | { 101 | *(.ARM.extab* .gnu.linkonce.armextab.*) 102 | } > FLASH 103 | 104 | __exidx_start = .; 105 | .ARM.exidx : 106 | { 107 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 108 | } > FLASH 109 | __exidx_end = .; 110 | 111 | /* Machine inspectable binary information */ 112 | . = ALIGN(4); 113 | __binary_info_start = .; 114 | .binary_info : 115 | { 116 | KEEP(*(.binary_info.keep.*)) 117 | *(.binary_info.*) 118 | } > FLASH 119 | __binary_info_end = .; 120 | . = ALIGN(4); 121 | 122 | /* End of .text-like segments */ 123 | __etext = .; 124 | 125 | .ram_vector_table (COPY): { 126 | *(.ram_vector_table) 127 | } > RAM 128 | 129 | .data : { 130 | __data_start__ = .; 131 | *(vtable) 132 | 133 | *(.time_critical*) 134 | 135 | /* remaining .text and .rodata; i.e. stuff we exclude above because we want it in RAM */ 136 | *(.text*) 137 | . = ALIGN(4); 138 | *(.rodata*) 139 | . = ALIGN(4); 140 | 141 | *(.data*) 142 | 143 | . = ALIGN(4); 144 | *(.after_data.*) 145 | . = ALIGN(4); 146 | /* preinit data */ 147 | PROVIDE_HIDDEN (__mutex_array_start = .); 148 | KEEP(*(SORT(.mutex_array.*))) 149 | KEEP(*(.mutex_array)) 150 | PROVIDE_HIDDEN (__mutex_array_end = .); 151 | 152 | . = ALIGN(4); 153 | /* preinit data */ 154 | PROVIDE_HIDDEN (__preinit_array_start = .); 155 | KEEP(*(SORT(.preinit_array.*))) 156 | KEEP(*(.preinit_array)) 157 | PROVIDE_HIDDEN (__preinit_array_end = .); 158 | 159 | . = ALIGN(4); 160 | /* init data */ 161 | PROVIDE_HIDDEN (__init_array_start = .); 162 | KEEP(*(SORT(.init_array.*))) 163 | KEEP(*(.init_array)) 164 | PROVIDE_HIDDEN (__init_array_end = .); 165 | 166 | . = ALIGN(4); 167 | /* finit data */ 168 | PROVIDE_HIDDEN (__fini_array_start = .); 169 | *(SORT(.fini_array.*)) 170 | *(.fini_array) 171 | PROVIDE_HIDDEN (__fini_array_end = .); 172 | 173 | *(.jcr) 174 | . = ALIGN(4); 175 | /* All data end */ 176 | __data_end__ = .; 177 | } > RAM AT> FLASH 178 | 179 | 180 | .memedata : { 181 | __memedata_start__ = .; 182 | *(.memedata*) 183 | . = ALIGN(4); 184 | __memedata_end__ = .; 185 | } > RAM AT > FLASH 186 | __memedata_source__ = LOADADDR(.memedata); 187 | 188 | .uninitialized_data (COPY): { 189 | . = ALIGN(4); 190 | *(.uninitialized_data*) 191 | } > RAM 192 | 193 | .memenodata (NOLOAD): { 194 | . = ALIGN(4); 195 | *(.memenodata*) 196 | } > RAM 197 | 198 | .memebank2 : { 199 | __memebank2_start__ = .; 200 | *(.memebank2*) 201 | . = ALIGN(4); 202 | __memebank2_end__ = .; 203 | } > BANK2 AT > FLASH 204 | __memebank2_source__ = LOADADDR(.memebank2); 205 | 206 | .memenbank2 (NOLOAD): { 207 | . = ALIGN(4); 208 | *(.memenbank2*) 209 | } > BANK2 210 | 211 | .memebank3 : { 212 | __memebank3_start__ = .; 213 | *(.memebank3*) 214 | . = ALIGN(4); 215 | __memebank3_end__ = .; 216 | } > BANK3 AT > FLASH 217 | __memebank3_source__ = LOADADDR(.memebank3); 218 | 219 | .memenbank3 (NOLOAD): { 220 | . = ALIGN(4); 221 | *(.memenbank3*) 222 | } > BANK3 223 | 224 | /* Start and end symbols must be word-aligned */ 225 | .scratch_x : { 226 | __scratch_x_start__ = .; 227 | *(.scratch_x.*) 228 | . = ALIGN(4); 229 | __scratch_x_end__ = .; 230 | } > SCRATCH_X AT > FLASH 231 | __scratch_x_source__ = LOADADDR(.scratch_x); 232 | 233 | .scratch_y : { 234 | __scratch_y_start__ = .; 235 | *(.scratch_y.*) 236 | . = ALIGN(4); 237 | __scratch_y_end__ = .; 238 | } > SCRATCH_Y AT > FLASH 239 | __scratch_y_source__ = LOADADDR(.scratch_y); 240 | 241 | .bss (NOLOAD) : { 242 | . = ALIGN(4); 243 | __bss_start__ = .; 244 | *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) 245 | *(COMMON) 246 | . = ALIGN(4); 247 | __bss_end__ = .; 248 | } > RAM 249 | 250 | .heap (COPY): 251 | { 252 | __end__ = .; 253 | end = __end__; 254 | *(.heap*) 255 | __HeapLimit = .; 256 | } > RAM 257 | 258 | /* .stack*_dummy section doesn't contains any symbols. It is only 259 | * used for linker to calculate size of stack sections, and assign 260 | * values to stack symbols later 261 | * 262 | * stack1 section may be empty/missing if platform_launch_core1 is not used */ 263 | 264 | /* by default we put core 0 stack at the end of scratch Y, so that if core 1 265 | * stack is not used then all of SCRATCH_X is free. 266 | */ 267 | .stack1_dummy (COPY): 268 | { 269 | *(.stack1*) 270 | } > SCRATCH_X 271 | .stack_dummy (COPY): 272 | { 273 | *(.stack*) 274 | } > SCRATCH_Y 275 | 276 | .flash_end : { 277 | __flash_binary_end = .; 278 | } > FLASH 279 | 280 | /* stack limit is poorly named, but historically is maximum heap ptr */ 281 | __StackLimit = ORIGIN(RAM) + LENGTH(RAM); 282 | __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); 283 | __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); 284 | __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); 285 | __StackBottom = __StackTop - SIZEOF(.stack_dummy); 286 | PROVIDE(__stack = __StackTop); 287 | 288 | /* Check if data + heap + stack exceeds RAM limit */ 289 | ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") 290 | 291 | ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") 292 | /* todo assert on extra code */ 293 | } 294 | 295 | -------------------------------------------------------------------------------- /neg_ram.ld: -------------------------------------------------------------------------------- 1 | /* Based on GCC ARM embedded samples. 2 | Defines the following symbols for use by code: 3 | __exidx_start 4 | __exidx_end 5 | __etext 6 | __data_start__ 7 | __preinit_array_start 8 | __preinit_array_end 9 | __init_array_start 10 | __init_array_end 11 | __fini_array_start 12 | __fini_array_end 13 | __data_end__ 14 | __bss_start__ 15 | __bss_end__ 16 | __end__ 17 | end 18 | __HeapLimit 19 | __StackLimit 20 | __StackTop 21 | __stack (== StackTop) 22 | */ 23 | 24 | MEMORY 25 | { 26 | RAM(rwx) : ORIGIN = 0x21000000, LENGTH = 128k 27 | BANK2(rwx) : ORIGIN = 0x21020000, LENGTH = 64k 28 | BANK3(rwx) : ORIGIN = 0x21030000, LENGTH = 64k 29 | SCRATCH_X(rwx) : ORIGIN = 0x20040000, LENGTH = 4k 30 | SCRATCH_Y(rwx) : ORIGIN = 0x20041000, LENGTH = 4k 31 | } 32 | 33 | ENTRY(_entry_point) 34 | 35 | SECTIONS 36 | { 37 | /* Note in NO_FLASH builds the entry point for both the bootrom, and debugger 38 | entry (ELF entry point), are *first* in the image, and the vector table 39 | follows immediately afterward. This is because the bootrom enters RAM 40 | binaries directly at their lowest address (preferring main RAM over XIP 41 | cache-as-SRAM if both are used). 42 | */ 43 | 44 | .text : { 45 | __logical_binary_start = .; 46 | __reset_start = .; 47 | KEEP (*(.reset)) 48 | __reset_end = .; 49 | KEEP (*(.binary_info_header)) 50 | __binary_info_header_end = .; 51 | . = ALIGN(256); 52 | KEEP (*(.vectors)) 53 | *(.time_critical*) 54 | *(.text*) 55 | . = ALIGN(4); 56 | *(.init) 57 | *(.fini) 58 | /* Pull all c'tors into .text */ 59 | *crtbegin.o(.ctors) 60 | *crtbegin?.o(.ctors) 61 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 62 | *(SORT(.ctors.*)) 63 | *(.ctors) 64 | /* Followed by destructors */ 65 | *crtbegin.o(.dtors) 66 | *crtbegin?.o(.dtors) 67 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 68 | *(SORT(.dtors.*)) 69 | *(.dtors) 70 | 71 | *(.eh_frame*) 72 | } > RAM 73 | 74 | .rodata : { 75 | *(.rodata*) 76 | . = ALIGN(4); 77 | *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.flashdata*))) 78 | . = ALIGN(4); 79 | } > RAM 80 | 81 | .ARM.extab : 82 | { 83 | *(.ARM.extab* .gnu.linkonce.armextab.*) 84 | } > RAM 85 | 86 | __exidx_start = .; 87 | .ARM.exidx : 88 | { 89 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 90 | } > RAM 91 | __exidx_end = .; 92 | 93 | /* Machine inspectable binary information */ 94 | . = ALIGN(4); 95 | __binary_info_start = .; 96 | .binary_info : 97 | { 98 | KEEP(*(.binary_info.keep.*)) 99 | *(.binary_info.*) 100 | } > RAM 101 | __binary_info_end = .; 102 | . = ALIGN(4); 103 | 104 | .data : { 105 | /* End of .text-like segments */ 106 | __etext = .; 107 | __data_start__ = .; 108 | *(vtable) 109 | *(.data*) 110 | 111 | . = ALIGN(4); 112 | *(.after_data.*) 113 | 114 | . = ALIGN(4); 115 | /* preinit data */ 116 | PROVIDE_HIDDEN (__mutex_array_start = .); 117 | KEEP(*(SORT(.mutex_array.*))) 118 | KEEP(*(.mutex_array)) 119 | PROVIDE_HIDDEN (__mutex_array_end = .); 120 | 121 | . = ALIGN(4); 122 | /* preinit data */ 123 | PROVIDE_HIDDEN (__preinit_array_start = .); 124 | KEEP(*(SORT(.preinit_array.*))) 125 | KEEP(*(.preinit_array)) 126 | PROVIDE_HIDDEN (__preinit_array_end = .); 127 | 128 | . = ALIGN(4); 129 | /* init data */ 130 | PROVIDE_HIDDEN (__init_array_start = .); 131 | KEEP(*(SORT(.init_array.*))) 132 | KEEP(*(.init_array)) 133 | PROVIDE_HIDDEN (__init_array_end = .); 134 | 135 | . = ALIGN(4); 136 | /* finit data */ 137 | PROVIDE_HIDDEN (__fini_array_start = .); 138 | *(SORT(.fini_array.*)) 139 | *(.fini_array) 140 | PROVIDE_HIDDEN (__fini_array_end = .); 141 | 142 | *(.jcr) 143 | . = ALIGN(4); 144 | /* All data end */ 145 | __data_end__ = .; 146 | } > RAM 147 | 148 | .memedata : { 149 | __memedata_start__ = .; 150 | *(.memedata*) 151 | . = ALIGN(4); 152 | __memedata_end__ = .; 153 | } > RAM 154 | __memedata_source__ = LOADADDR(.memedata); 155 | 156 | .uninitialized_data (COPY): { 157 | . = ALIGN(4); 158 | *(.uninitialized_data*) 159 | } > RAM 160 | 161 | .memenodata (NOLOAD): { 162 | . = ALIGN(4); 163 | *(.memenodata*) 164 | } > RAM 165 | 166 | .memebank2 : { 167 | __memebank2_start__ = .; 168 | *(.memebank2*) 169 | . = ALIGN(4); 170 | __memebank2_end__ = .; 171 | } > BANK2 172 | __memebank2_source__ = LOADADDR(.memebank2); 173 | 174 | .memenbank2 (NOLOAD): { 175 | . = ALIGN(4); 176 | *(.memenbank2*) 177 | } > BANK2 178 | 179 | .memebank3 : { 180 | __memebank3_start__ = .; 181 | *(.memebank3*) 182 | . = ALIGN(4); 183 | __memebank3_end__ = .; 184 | } > BANK3 185 | __memebank3_source__ = LOADADDR(.memebank3); 186 | 187 | .memenbank3 (NOLOAD): { 188 | . = ALIGN(4); 189 | *(.memenbank3*) 190 | } > BANK3 191 | 192 | /* Start and end symbols must be word-aligned */ 193 | .scratch_x : { 194 | __scratch_x_start__ = .; 195 | *(.scratch_x.*) 196 | . = ALIGN(4); 197 | __scratch_x_end__ = .; 198 | } > SCRATCH_X 199 | __scratch_x_source__ = LOADADDR(.scratch_x); 200 | 201 | .scratch_y : { 202 | __scratch_y_start__ = .; 203 | *(.scratch_y.*) 204 | . = ALIGN(4); 205 | __scratch_y_end__ = .; 206 | } > SCRATCH_Y 207 | __scratch_y_source__ = LOADADDR(.scratch_y); 208 | 209 | .bss (NOLOAD) : { 210 | . = ALIGN(4); 211 | __bss_start__ = .; 212 | *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.bss*))) 213 | *(COMMON) 214 | . = ALIGN(4); 215 | __bss_end__ = .; 216 | } > RAM 217 | 218 | .heap (COPY): 219 | { 220 | __end__ = .; 221 | end = __end__; 222 | *(.heap*) 223 | __HeapLimit = .; 224 | } > RAM 225 | 226 | /* .stack*_dummy section doesn't contains any symbols. It is only 227 | * used for linker to calculate size of stack sections, and assign 228 | * values to stack symbols later 229 | * 230 | * stack1 section may be empty/missing if platform_launch_core1 is not used */ 231 | 232 | /* by default we put core 0 stack at the end of scratch Y, so that if core 1 233 | * stack is not used then all of SCRATCH_X is free. 234 | */ 235 | .stack1_dummy (COPY): 236 | { 237 | *(.stack1*) 238 | } > SCRATCH_X 239 | .stack_dummy (COPY): 240 | { 241 | *(.stack*) 242 | } > SCRATCH_Y 243 | 244 | /* stack limit is poorly named, but historically is maximum heap ptr */ 245 | __StackLimit = ORIGIN(RAM) + LENGTH(RAM); 246 | __StackOneTop = ORIGIN(SCRATCH_X) + LENGTH(SCRATCH_X); 247 | __StackTop = ORIGIN(SCRATCH_Y) + LENGTH(SCRATCH_Y); 248 | __StackOneBottom = __StackOneTop - SIZEOF(.stack1_dummy); 249 | __StackBottom = __StackTop - SIZEOF(.stack_dummy); 250 | PROVIDE(__stack = __StackTop); 251 | 252 | /* Check if data + heap + stack exceeds RAM limit */ 253 | ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed") 254 | 255 | ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary") 256 | /* todo assert on extra code */ 257 | } 258 | 259 | -------------------------------------------------------------------------------- /pico_sdk_import.cmake: -------------------------------------------------------------------------------- 1 | # This is a copy of /external/pico_sdk_import.cmake 2 | 3 | # This can be dropped into an external project to help locate this SDK 4 | # It should be include()ed prior to project() 5 | 6 | if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) 7 | set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) 8 | message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") 9 | endif () 10 | 11 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) 12 | set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) 13 | message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") 14 | endif () 15 | 16 | if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) 17 | set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) 18 | message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") 19 | endif () 20 | 21 | set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") 22 | set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") 23 | set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") 24 | 25 | if (NOT PICO_SDK_PATH) 26 | if (PICO_SDK_FETCH_FROM_GIT) 27 | include(FetchContent) 28 | set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) 29 | if (PICO_SDK_FETCH_FROM_GIT_PATH) 30 | get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") 31 | endif () 32 | # GIT_SUBMODULES_RECURSE was added in 3.17 33 | if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") 34 | FetchContent_Declare( 35 | pico_sdk 36 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 37 | GIT_TAG master 38 | GIT_SUBMODULES_RECURSE FALSE 39 | ) 40 | else () 41 | FetchContent_Declare( 42 | pico_sdk 43 | GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk 44 | GIT_TAG master 45 | ) 46 | endif () 47 | 48 | if (NOT pico_sdk) 49 | message("Downloading Raspberry Pi Pico SDK") 50 | FetchContent_Populate(pico_sdk) 51 | set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) 52 | endif () 53 | set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) 54 | else () 55 | message(FATAL_ERROR 56 | "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." 57 | ) 58 | endif () 59 | endif () 60 | 61 | get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") 62 | if (NOT EXISTS ${PICO_SDK_PATH}) 63 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") 64 | endif () 65 | 66 | set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) 67 | if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) 68 | message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") 69 | endif () 70 | 71 | set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) 72 | 73 | include(${PICO_SDK_INIT_CMAKE_FILE}) 74 | -------------------------------------------------------------------------------- /src/bf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pico/platform.h" 3 | 4 | #include "memeloc.h" 5 | 6 | //extern const uint32_t blowfish_S[0x100 * 4]; 7 | //extern const uint32_t blowfish_P[18]; 8 | extern const uint32_t blowfish_table[(0x100 * 4) + 18]; 9 | 10 | #pragma GCC optimize ("Os") 11 | 12 | 13 | #define F F_CPU 14 | //#define F F_INTERP 15 | 16 | static inline uint32_t MEMELOC_RAM_F(F_CPU)(uint32_t indata) 17 | { 18 | //register const uint32_t* dptr = blowfish_S; 19 | register const uint32_t* dptr = blowfish_table; 20 | 21 | register uint32_t data = indata; 22 | register uint32_t res; 23 | register uint8_t idx; 24 | 25 | { 26 | data = (data >> 24) | (data << 8); 27 | idx = (uint8_t)data; 28 | 29 | res = dptr[idx]; 30 | dptr += 0x100; 31 | } 32 | 33 | { 34 | data = (data >> 24) | (data << 8); 35 | idx = (uint8_t)data; 36 | 37 | res += dptr[idx]; 38 | dptr += 0x100; 39 | } 40 | 41 | { 42 | data = (data >> 24) | (data << 8); 43 | idx = (uint8_t)data; 44 | 45 | res ^= dptr[idx]; 46 | dptr += 0x100; 47 | } 48 | 49 | { 50 | data = (data >> 24) | (data << 8); 51 | idx = (uint8_t)data; 52 | 53 | res += dptr[idx]; 54 | //dptr += 0x100; 55 | } 56 | 57 | return res; 58 | } 59 | 60 | void MEMELOC_RAM_F(bfEncrypt)(uint32_t* __restrict ptr0, uint32_t* __restrict ptr1) 61 | { 62 | register uint32_t x1 = *ptr0; 63 | register uint32_t x2 = *ptr1; 64 | 65 | //register const uint32_t* dptr = blowfish_P; 66 | register const uint32_t* dptr = &blowfish_table[0x400]; 67 | 68 | for(uint32_t i = 0; i != 16; i++) 69 | { 70 | x1 ^= *(dptr++); 71 | x2 ^= F(x1); 72 | 73 | uint32_t tmp = x1; 74 | x1 = x2; 75 | x2 = tmp; 76 | } 77 | 78 | *ptr0 = x2 ^ dptr[1]; 79 | *ptr1 = x1 ^ dptr[0]; 80 | } 81 | 82 | void MEMELOC_RAM_F(bfDecrypt)(uint32_t* __restrict ptr0, uint32_t* __restrict ptr1) 83 | { 84 | register uint32_t x1 = *ptr0; 85 | register uint32_t x2 = *ptr1; 86 | 87 | //register const uint32_t* dptr = &blowfish_P[18]; 88 | register const uint32_t* dptr = &blowfish_table[0x400 + 18]; 89 | 90 | for(uint32_t i = 0; i != 16; i++) 91 | { 92 | x1 ^= *(--dptr); 93 | x2 ^= F(x1); 94 | 95 | uint32_t tmp = x1; 96 | x1 = x2; 97 | x2 = tmp; 98 | } 99 | 100 | *ptr0 = x2 ^ dptr[-2]; 101 | *ptr1 = x1 ^ dptr[-1]; 102 | } 103 | -------------------------------------------------------------------------------- /src/bf.h: -------------------------------------------------------------------------------- 1 | 2 | void bfInit(void); 3 | void bfEncrypt(uint32_t* __restrict ptr0, uint32_t* __restrict ptr1); 4 | void bfDecrypt(uint32_t* __restrict ptr0, uint32_t* __restrict ptr1); 5 | -------------------------------------------------------------------------------- /src/bf_table.c: -------------------------------------------------------------------------------- 1 | /* 2 | bf_table.c - Blowfish table for NTRCARD command decryption 3 | 4 | Raw Blowfish data is copied to 0x1FFFD000 by boot11, 5 | then boot9 processes it into 0x080006A0 6 | */ 7 | 8 | #include 9 | #include "pico/platform.h" 10 | 11 | #include "memeloc.h" 12 | 13 | #define BFLOC MEMELOC_RAM_D("bf") 14 | 15 | //const uint32_t BFLOC blowfish_S[0x100 * 4] __attribute__((aligned(0x1000))) = 16 | const uint32_t BFLOC blowfish_table[(0x100 * 4) + 18] __attribute__((aligned(0x1000))) = 17 | { 18 | 0xCE59E797, 19 | 0x5669DE16, 20 | 0x96FFEC63, 21 | 0x2C058069, 22 | 0x6688021C, 23 | 0xCCAA512A, 24 | 0xF3FFE410, 25 | 0xA7BFFA0A, 26 | 0xE6EB535B, 27 | 0xC95138AC, 28 | 0x2CD75FF9, 29 | 0x7BF6B8F3, 30 | 0xE30DC6F8, 31 | 0x5F6BE10A, 32 | 0xB851CDD1, 33 | 0xE9C59219, 34 | 0xA220B268, 35 | 0x6706B0AF, 36 | 0x960D1829, 37 | 0x7A88A677, 38 | 0x7C9E6FE6, 39 | 0xB910B74E, 40 | 0x4E0D171E, 41 | 0x0A3D8983, 42 | 0x49AF345E, 43 | 0x3E644AB0, 44 | 0x7ED66E8E, 45 | 0x4B18B7CA, 46 | 0x8D005F31, 47 | 0x82340F7C, 48 | 0x81F1B4A8, 49 | 0x52E0FA11, 50 | 0x51772698, 51 | 0x386EB463, 52 | 0x78172C06, 53 | 0x5BEB7D0A, 54 | 0xE3A8A2EB, 55 | 0x4EC70358, 56 | 0x56FEC38D, 57 | 0x465814E0, 58 | 0x8CE62A56, 59 | 0x9F4B318F, 60 | 0xA977CAA8, 61 | 0x792CC69E, 62 | 0xAF670902, 63 | 0x286C0242, 64 | 0xDEC4523E, 65 | 0x4BC2DAF7, 66 | 0x68BAEBCA, 67 | 0xEB86748C, 68 | 0x7BBEC0D2, 69 | 0x2720B12B, 70 | 0x820668C6, 71 | 0xE1BA88C7, 72 | 0x95FDA029, 73 | 0x4BA924FA, 74 | 0x5D809EF8, 75 | 0xB4D6EEF8, 76 | 0x691E76D4, 77 | 0x96AD4779, 78 | 0xD082FF08, 79 | 0x70FD023E, 80 | 0x5F164D5B, 81 | 0x4427C3AC, 82 | 0x7E1816E0, 83 | 0x55D28BC0, 84 | 0x73D03AEB, 85 | 0x06D11235, 86 | 0x2D855EDF, 87 | 0x842E0FCB, 88 | 0x33CBBDD2, 89 | 0xE448C816, 90 | 0x60DD06A2, 91 | 0x1BB66D13, 92 | 0xC1A23644, 93 | 0x0EEECF2D, 94 | 0x3A2855B6, 95 | 0x4322E69F, 96 | 0x1A9C5855, 97 | 0xA46EAD3C, 98 | 0x1679D155, 99 | 0xE2432BE1, 100 | 0x28BAAF73, 101 | 0xB04F5D0E, 102 | 0x89AA596B, 103 | 0xA8F0A4C9, 104 | 0xBC5318B3, 105 | 0x4180318B, 106 | 0xF819FDE0, 107 | 0xFCE5172C, 108 | 0xAEE75056, 109 | 0x075B30E1, 110 | 0x5202569A, 111 | 0x0DE3FA43, 112 | 0xADC6198F, 113 | 0x08FC5FA5, 114 | 0xE5FBD672, 115 | 0x0051DEBB, 116 | 0x00701C89, 117 | 0x19531772, 118 | 0x0B55A052, 119 | 0xF3CF5B5F, 120 | 0xC039055D, 121 | 0x21DE249D, 122 | 0x19A93BC2, 123 | 0x90AB38BD, 124 | 0x708B5997, 125 | 0x7731D457, 126 | 0x72B956E3, 127 | 0xCBF980A5, 128 | 0xE786604E, 129 | 0x24F5B87E, 130 | 0x15C62B96, 131 | 0xF73D6844, 132 | 0xF60BC63A, 133 | 0x0ACA38E4, 134 | 0x2AAA8805, 135 | 0xC3203637, 136 | 0x00FD3D84, 137 | 0x14AA3B86, 138 | 0xF63EB387, 139 | 0xA2996ADA, 140 | 0xDE1C6AB3, 141 | 0x88D49A7C, 142 | 0x02B29DE7, 143 | 0x6A312362, 144 | 0xDF0DDF8D, 145 | 0x2E0AF56F, 146 | 0xED492EAA, 147 | 0x8944FCC0, 148 | 0x65A87B17, 149 | 0x1EB75B59, 150 | 0xF36ECDF3, 151 | 0x8D38E75B, 152 | 0xD3B8DCC9, 153 | 0x64DCD54A, 154 | 0xEE8DD90F, 155 | 0x6264B1F6, 156 | 0x030582ED, 157 | 0x5576F634, 158 | 0x73AF8BA0, 159 | 0xC8F0E7BA, 160 | 0x8F08AAFC, 161 | 0x36458E54, 162 | 0x06100D61, 163 | 0xE3B6AA51, 164 | 0x4E3028AD, 165 | 0x242EAD6D, 166 | 0x4D4D5C0A, 167 | 0x0CBDA224, 168 | 0x19F98356, 169 | 0x0202917D, 170 | 0xE8B4F04C, 171 | 0xE9A482A2, 172 | 0x4712C4BC, 173 | 0xEEA0F303, 174 | 0xA8A432A1, 175 | 0xD51CEB44, 176 | 0x75C4BF58, 177 | 0xAD27DEFD, 178 | 0x75E131C1, 179 | 0x2265A06E, 180 | 0x324A3713, 181 | 0xBDF0AD99, 182 | 0x98A6A6CB, 183 | 0x10A85837, 184 | 0xBC185800, 185 | 0x5136F923, 186 | 0x562A995E, 187 | 0x230DE313, 188 | 0x2316F66C, 189 | 0x1B4276D6, 190 | 0x8C35A602, 191 | 0x8EA6C382, 192 | 0x0C20E0B7, 193 | 0xC4957B2B, 194 | 0x5952BD66, 195 | 0x8F44DC81, 196 | 0x8778A3B5, 197 | 0xA898A5CF, 198 | 0x39226690, 199 | 0xDFBB8B68, 200 | 0xECC70B3D, 201 | 0xB2F8425B, 202 | 0x9F87220B, 203 | 0x5F29689C, 204 | 0xB3E3984C, 205 | 0xEBB30B2E, 206 | 0xE663A91A, 207 | 0xDDC85B63, 208 | 0x5E409580, 209 | 0xB5E53C69, 210 | 0xD7BD7225, 211 | 0x0FD52275, 212 | 0xE16F9862, 213 | 0x96017835, 214 | 0x580E8903, 215 | 0xC24FE66C, 216 | 0x69886138, 217 | 0x12AFD553, 218 | 0x60291075, 219 | 0x822276BB, 220 | 0x2A5248F4, 221 | 0x71557F72, 222 | 0xE0DA853D, 223 | 0x2F9CF4E7, 224 | 0x03C3C8B6, 225 | 0x078224B5, 226 | 0x631358C7, 227 | 0x70071C2C, 228 | 0xDD081A40, 229 | 0xD3FDF4A6, 230 | 0xA4973721, 231 | 0xB2DC1C25, 232 | 0xA210630A, 233 | 0x1053E89D, 234 | 0x3687FEA4, 235 | 0x0DD0526D, 236 | 0xB74A848E, 237 | 0x1CA2F372, 238 | 0x83A9F304, 239 | 0x51AF9E2A, 240 | 0x1BD2A49F, 241 | 0x8D8139D7, 242 | 0x6D26CA4B, 243 | 0x7202CD94, 244 | 0x3735ED54, 245 | 0xF778798B, 246 | 0x8261050D, 247 | 0xC2B9671C, 248 | 0xE5119F23, 249 | 0x84EB1C5D, 250 | 0x6ADABCD5, 251 | 0x1A69E919, 252 | 0x98E6F517, 253 | 0x4866A231, 254 | 0x02757FA1, 255 | 0xCEE9BEC5, 256 | 0x881599FC, 257 | 0x77E76848, 258 | 0x0EF209E6, 259 | 0x1E646C85, 260 | 0x5421CEC5, 261 | 0x712627F2, 262 | 0x74D87526, 263 | 0x4B6EFEFE, 264 | 0xA28CE144, 265 | 0x656B9864, 266 | 0x340813E0, 267 | 0x78BFB89B, 268 | 0xEF91AC74, 269 | 0xC51B4B57, 270 | 0x233F54A9, 271 | 0xB5F26D78, 272 | 0x258B4732, 273 | 0x9C0A3102, 274 | 0x074A813A, 275 | 0xF8746975, 276 | 0xA32B35D5, 277 | 0xF5918A39, 278 | 0x28F3A119, 279 | 0x4CCD3499, 280 | 0xA13F0134, 281 | 0xE033EF96, 282 | 0x59BB0F52, 283 | 0xB61CBE99, 284 | 0x77C84C60, 285 | 0x08717647, 286 | 0x4F00771E, 287 | 0x7A0CCAE2, 288 | 0x1990DA29, 289 | 0xBB46423A, 290 | 0x2F1B0A88, 291 | 0xF9325AB3, 292 | 0xFADF2679, 293 | 0xF1C23620, 294 | 0xE92D9DD1, 295 | 0x8151F439, 296 | 0x8063DCF7, 297 | 0x71B70CAC, 298 | 0xA740E109, 299 | 0x206638D8, 300 | 0xBE90D70A, 301 | 0xADEFB392, 302 | 0x2C59015C, 303 | 0x271E23F3, 304 | 0xBBB201F3, 305 | 0xC2A852AB, 306 | 0x9DE89847, 307 | 0x2B9ABB77, 308 | 0x9630F416, 309 | 0x5585D6F9, 310 | 0x5C71C874, 311 | 0x6B737767, 312 | 0x1A4DB910, 313 | 0x1413A630, 314 | 0xD6723B56, 315 | 0x1A06C70F, 316 | 0xDFF43E6B, 317 | 0x03F7ADF1, 318 | 0x95181B3B, 319 | 0x30ED830A, 320 | 0xD743CBE7, 321 | 0x228BAA79, 322 | 0xC80C14DC, 323 | 0xFCA3B777, 324 | 0x8CE7D991, 325 | 0xC26EB027, 326 | 0x302C793B, 327 | 0xFDF3179D, 328 | 0x85AB0D1B, 329 | 0xF6C03752, 330 | 0x3C3B75AF, 331 | 0x1ACF3B6B, 332 | 0x65E87A3B, 333 | 0x9B4F2AA3, 334 | 0xB53945D5, 335 | 0x8EDA8297, 336 | 0xC3567FEA, 337 | 0x58C372EA, 338 | 0xA87994F8, 339 | 0x410D9906, 340 | 0xEB2D688D, 341 | 0x3525B33D, 342 | 0x43772B36, 343 | 0xAA4E7A50, 344 | 0xE66F2422, 345 | 0x08D4E06C, 346 | 0xA90E17B2, 347 | 0xCCF37330, 348 | 0x78C96C83, 349 | 0x01C5B80B, 350 | 0x007AE4F4, 351 | 0x1F77ABE0, 352 | 0x2519EA6F, 353 | 0xA1B3EFE2, 354 | 0x8F6A40AC, 355 | 0xBE9884C2, 356 | 0xF2E48AED, 357 | 0x2EBF3B61, 358 | 0x1E3B1C16, 359 | 0x5EE14C04, 360 | 0x56C3373B, 361 | 0x74EFAF83, 362 | 0x0989803F, 363 | 0x11D5CA03, 364 | 0x175BBD69, 365 | 0x7C43665C, 366 | 0x32DCEE8F, 367 | 0x0EF07048, 368 | 0x1DC4E888, 369 | 0xCFB01367, 370 | 0x230BFB83, 371 | 0x31D77164, 372 | 0x4459CA10, 373 | 0x042309C7, 374 | 0xC5DF00A1, 375 | 0x4EB57F5A, 376 | 0xD24924E8, 377 | 0x8D16703F, 378 | 0x1286ECF4, 379 | 0x400A9386, 380 | 0x61DD4781, 381 | 0x817320F6, 382 | 0xEE0CF8FA, 383 | 0x56313F71, 384 | 0x283741E3, 385 | 0xF3E6A2E1, 386 | 0x9F46B6A3, 387 | 0xEC8C7316, 388 | 0xC8B3AA98, 389 | 0x82B5EB9D, 390 | 0x1F14E21E, 391 | 0xB7B013EF, 392 | 0x06491851, 393 | 0x2ED11554, 394 | 0xE9BD845A, 395 | 0x69B1D965, 396 | 0xC9E8E3D5, 397 | 0x956F3ADF, 398 | 0x99DF0F61, 399 | 0x8F49CF4C, 400 | 0xCCF960A5, 401 | 0x298FF166, 402 | 0x9823A50F, 403 | 0x57B36962, 404 | 0x94B7964A, 405 | 0xBBCE5EDE, 406 | 0x950C6B3D, 407 | 0xA2DE6F4B, 408 | 0x1AB991D8, 409 | 0x106CAC0E, 410 | 0x9F2C45C1, 411 | 0x27EC3902, 412 | 0x6AAC7041, 413 | 0xB5AC36D0, 414 | 0x6AEEA0C2, 415 | 0x2C7DA366, 416 | 0xC238350A, 417 | 0x037EC577, 418 | 0x3F760A59, 419 | 0x55277724, 420 | 0x314CCE00, 421 | 0xA4CBFC1D, 422 | 0x6D2DA1E2, 423 | 0xA04E160B, 424 | 0x7F7C94BA, 425 | 0xDAAE86F6, 426 | 0x87494A8C, 427 | 0x3D977FE3, 428 | 0x7EF4EF3C, 429 | 0xEC0D0F9D, 430 | 0x34FC9518, 431 | 0x93F70089, 432 | 0xCEFBAAB7, 433 | 0xAC030FD6, 434 | 0x50EEEBAA, 435 | 0x215D2C7D, 436 | 0x1ACCD7C3, 437 | 0x30BBBA36, 438 | 0xCC6D0616, 439 | 0x9DC8E84D, 440 | 0x37AC1411, 441 | 0xB1A74D96, 442 | 0x346D546A, 443 | 0x38B6E7F3, 444 | 0x63060A18, 445 | 0x6167AA3D, 446 | 0xFABF73A8, 447 | 0x039BC823, 448 | 0x0F799C38, 449 | 0x154A641A, 450 | 0x50D7EE9C, 451 | 0xF2D9D6E5, 452 | 0x8868DCAA, 453 | 0x21EE2611, 454 | 0xD05BE0E0, 455 | 0x374DC9F9, 456 | 0xE28DCC2E, 457 | 0x87E25059, 458 | 0xE463F764, 459 | 0x33D8A755, 460 | 0x3E98CA93, 461 | 0x952EB9E5, 462 | 0x5167929D, 463 | 0x8CA98E39, 464 | 0xBD12E305, 465 | 0xC55C5774, 466 | 0xC3B58EEA, 467 | 0x3ABA5399, 468 | 0xF2C1204E, 469 | 0x094681FA, 470 | 0xF5963414, 471 | 0x493AF296, 472 | 0xA0892330, 473 | 0xCE29EB7C, 474 | 0xA99AAD38, 475 | 0xC143963F, 476 | 0x82C1A900, 477 | 0x9040F34C, 478 | 0xA2EBF7B4, 479 | 0xF72FFDA1, 480 | 0xA06A2297, 481 | 0x54290939, 482 | 0xDAF58C13, 483 | 0xBBBA5FD9, 484 | 0xA7934DAF, 485 | 0xF4F32564, 486 | 0xD9BAC927, 487 | 0x07BFF897, 488 | 0xFE680C8C, 489 | 0x964F48B5, 490 | 0xBBFE403B, 491 | 0x52A1B3B5, 492 | 0x5FB4EE55, 493 | 0x96819C00, 494 | 0x653620EE, 495 | 0x6A0E88EA, 496 | 0x654CD99E, 497 | 0x4423B51D, 498 | 0xE3C57416, 499 | 0x10A1C020, 500 | 0x13DD4AE2, 501 | 0xAE90E7FD, 502 | 0x3824DC42, 503 | 0xE1B6D22A, 504 | 0xD0D1E9BD, 505 | 0xB5820BEE, 506 | 0xBA971749, 507 | 0x1FA7C856, 508 | 0x97FD1E9F, 509 | 0xEE924050, 510 | 0x6418B763, 511 | 0x4367E0F9, 512 | 0x8902E46A, 513 | 0xF0F3C15E, 514 | 0x87D4EF42, 515 | 0x7CE876A3, 516 | 0x4BFC04D7, 517 | 0x814DEC14, 518 | 0x8A72AAD6, 519 | 0xDE4B1A5A, 520 | 0xD382C6C1, 521 | 0xD178B428, 522 | 0x75393BB5, 523 | 0x7E470901, 524 | 0x7BB41002, 525 | 0xC7F10BC3, 526 | 0x18B428D2, 527 | 0xB46D5F1F, 528 | 0x79994F56, 529 | 0xFED9401C, 530 | 0x530521B6, 531 | 0xF9D3DF10, 532 | 0x20E5825A, 533 | 0x1142E0EF, 534 | 0x2155C573, 535 | 0x93F9D937, 536 | 0xA5FFF20D, 537 | 0x023043EF, 538 | 0xB0443CF7, 539 | 0xC45D2BBF, 540 | 0x22560B83, 541 | 0x20269E1A, 542 | 0xC1371D01, 543 | 0x69F17A39, 544 | 0xAE5D0151, 545 | 0x06107BCC, 546 | 0x5BF49A9A, 547 | 0xA9020B71, 548 | 0x3FF0DBEA, 549 | 0x706546AC, 550 | 0x9D025BF2, 551 | 0x02BE0EDB, 552 | 0x42BBC8AE, 553 | 0x0ACE336B, 554 | 0xA99C4873, 555 | 0x0596B5CA, 556 | 0xB24EE375, 557 | 0xA7853A61, 558 | 0x20C9CFB9, 559 | 0x6F57D570, 560 | 0x33049276, 561 | 0x2CDA996D, 562 | 0xD9F3C11E, 563 | 0x25789924, 564 | 0xFB201DD6, 565 | 0x5DA0C3DE, 566 | 0x2BC98863, 567 | 0xEA33D438, 568 | 0xFDF705C1, 569 | 0x21BF942F, 570 | 0xCBD1E56D, 571 | 0xA835868A, 572 | 0xDD9B74DF, 573 | 0x47482939, 574 | 0xCE7A4D84, 575 | 0xD91570E0, 576 | 0x8003F0AA, 577 | 0x60DDAFFD, 578 | 0xB572F25D, 579 | 0x55F25F95, 580 | 0x597BC8DA, 581 | 0x5F5A0939, 582 | 0xCE3D2755, 583 | 0xC2EB238A, 584 | 0xA11B0930, 585 | 0x0F3F0CE5, 586 | 0x71F519D3, 587 | 0xC0A00840, 588 | 0x10EFF824, 589 | 0xDAC057B7, 590 | 0x5D3C794E, 591 | 0xAA8477A2, 592 | 0x3D96E41A, 593 | 0x12B36089, 594 | 0xA09C23FE, 595 | 0xEC4CE008, 596 | 0xE269AA7E, 597 | 0xDED06ADB, 598 | 0xFBFB902E, 599 | 0xB92AE516, 600 | 0x82E733D1, 601 | 0xF9DB4A02, 602 | 0x469043A8, 603 | 0x346F88E6, 604 | 0x73CB79B7, 605 | 0xD1DD68E2, 606 | 0xEB3F1CE1, 607 | 0xF6476107, 608 | 0x73AD19E4, 609 | 0xB27A241B, 610 | 0x8928C691, 611 | 0x85FBD20F, 612 | 0x46C29B7D, 613 | 0xF380C3E3, 614 | 0x9A6A939F, 615 | 0x2CE5E087, 616 | 0xC4F7AD15, 617 | 0xA8AA6152, 618 | 0x504CF9B3, 619 | 0x146B9773, 620 | 0x21FDF8FD, 621 | 0x6B4E79FD, 622 | 0x72FD210C, 623 | 0xA0B9F401, 624 | 0x7F8F7D9F, 625 | 0x9F68EFE4, 626 | 0x1B8CEFF4, 627 | 0xC7E9C3B7, 628 | 0x795DFBFA, 629 | 0xB0023B56, 630 | 0xFF03D276, 631 | 0x7359E5E1, 632 | 0xD299C6C7, 633 | 0x6981A2D1, 634 | 0xEC4E1C0A, 635 | 0x28848606, 636 | 0xF65B0F57, 637 | 0xA70625D6, 638 | 0xD198E618, 639 | 0x42BABCDF, 640 | 0x3298EAA8, 641 | 0xF1A3F5F2, 642 | 0x9ED3DAD9, 643 | 0x248EAF58, 644 | 0x3B5BE3C0, 645 | 0x02D85347, 646 | 0xE9DD4FAC, 647 | 0xA361C719, 648 | 0x16C8C2DA, 649 | 0x8CDEF4B8, 650 | 0xF8ADCD97, 651 | 0xFB2E2ECF, 652 | 0xB2E92E55, 653 | 0x4D133095, 654 | 0x0BD74734, 655 | 0xDBC22373, 656 | 0x5282779F, 657 | 0x9C951028, 658 | 0x62510EF9, 659 | 0x53546DE1, 660 | 0x96FF7891, 661 | 0x6AD37BEB, 662 | 0xB0E5126E, 663 | 0xC6455F4C, 664 | 0x8196FDD7, 665 | 0x22716847, 666 | 0xA7AD03E9, 667 | 0x5FE5AA3B, 668 | 0x92A96007, 669 | 0xBD114B5A, 670 | 0x3394EC18, 671 | 0x1C34C3AD, 672 | 0xFD7CA1DE, 673 | 0x0543DF43, 674 | 0xA8A99451, 675 | 0x9F41246B, 676 | 0x92149687, 677 | 0xCB3B7289, 678 | 0xB116082D, 679 | 0x2312A14A, 680 | 0x5F656054, 681 | 0x956E5352, 682 | 0x34AD3B6B, 683 | 0x4434414B, 684 | 0xD98A422F, 685 | 0x34FC08F4, 686 | 0x50F371B9, 687 | 0x125A956D, 688 | 0xDB53EA93, 689 | 0x68D2905E, 690 | 0x9A3194BA, 691 | 0x0416FF87, 692 | 0x08F166C4, 693 | 0x6FE1D4EA, 694 | 0x4698632E, 695 | 0x621AC1F4, 696 | 0xEBA924A8, 697 | 0xE2DFFE69, 698 | 0x83A35346, 699 | 0xFD6B24BC, 700 | 0xDCF25A45, 701 | 0x30025BDD, 702 | 0xDE47444B, 703 | 0x1C556B0F, 704 | 0x948988E9, 705 | 0x7F78313E, 706 | 0x6FBF53E4, 707 | 0x3242BDA5, 708 | 0x4447AC25, 709 | 0xF6AA1C34, 710 | 0x30063DD1, 711 | 0x58A425EC, 712 | 0x4753193A, 713 | 0xD6C654AC, 714 | 0x8F64921D, 715 | 0xDA79A391, 716 | 0x57DD871D, 717 | 0x8E21752A, 718 | 0xA05540B5, 719 | 0x13D0FD0D, 720 | 0x86F25CCA, 721 | 0x9D5B9118, 722 | 0x31C81977, 723 | 0x512CCB2B, 724 | 0x8149EE62, 725 | 0xC5332756, 726 | 0xA63BB204, 727 | 0xFF63D321, 728 | 0xB59DC3E3, 729 | 0x24E3B4A7, 730 | 0xA18ACF31, 731 | 0x257F789E, 732 | 0x18BE0914, 733 | 0x6D779AF7, 734 | 0x28C881D3, 735 | 0x4BE85E8B, 736 | 0x4B5A0F7F, 737 | 0xB8A83831, 738 | 0x42EC5416, 739 | 0x589D8301, 740 | 0x5567E23C, 741 | 0x3AD0D054, 742 | 0xA5FB6004, 743 | 0x755B64F6, 744 | 0xE0C3F1DA, 745 | 0x36CAFF0C, 746 | 0x82958AE7, 747 | 0x779F5F3C, 748 | 0xF5B8D8C0, 749 | 0x92F389DF, 750 | 0x5161ED6D, 751 | 0x0194D33B, 752 | 0x603EF26D, 753 | 0xB69610F2, 754 | 0xF97AFA70, 755 | 0x559B2B4C, 756 | 0xCCFAADFD, 757 | 0x44494219, 758 | 0x537BC657, 759 | 0x033B6E42, 760 | 0x6F801AF7, 761 | 0x771C32C1, 762 | 0x549B1DD7, 763 | 0xE4ACA247, 764 | 0x3EB20FC2, 765 | 0xBEE9924A, 766 | 0xBC46A199, 767 | 0x5A408269, 768 | 0xF97F388A, 769 | 0xF602A8BC, 770 | 0xE0F29472, 771 | 0x97DDEF38, 772 | 0x2C69B4E4, 773 | 0xB64D9D59, 774 | 0xC39798F4, 775 | 0xBA024CA5, 776 | 0xA9005D4A, 777 | 0xC800B630, 778 | 0xEA2965EE, 779 | 0x7E68570B, 780 | 0xD25862AE, 781 | 0xA077EFA2, 782 | 0xC72990DD, 783 | 0xE57E39B4, 784 | 0x940FAB09, 785 | 0x8D7F618A, 786 | 0xCAE29E3B, 787 | 0x84D7C464, 788 | 0xA7184671, 789 | 0xF3BC5A08, 790 | 0xB06AE996, 791 | 0x7085285C, 792 | 0xDFB68F1F, 793 | 0x73F6C053, 794 | 0xB677A9B6, 795 | 0x3A8E5D7C, 796 | 0x111ED21A, 797 | 0x613EDCE6, 798 | 0xD473F8A5, 799 | 0xC67561FB, 800 | 0x6D7C8C81, 801 | 0x3FB3187E, 802 | 0x1D421BE8, 803 | 0xB259BC8E, 804 | 0x80AA9A05, 805 | 0xDDA8AA9C, 806 | 0x21A6F552, 807 | 0x91F4873D, 808 | 0xC71DA85F, 809 | 0x4E14102E, 810 | 0x682107FD, 811 | 0x153C4536, 812 | 0x1A5BD01D, 813 | 0xD2F1B7F3, 814 | 0x1C136363, 815 | 0xEBA6415D, 816 | 0x138D09B7, 817 | 0x9FFA2110, 818 | 0xAB61DBB6, 819 | 0x397D1A9C, 820 | 0x0FA5296F, 821 | 0x48A5E428, 822 | 0x76CF65C1, 823 | 0xA632D673, 824 | 0x8B802B41, 825 | 0xB9EE14CE, 826 | 0xCB0CA6D0, 827 | 0x0579104F, 828 | 0x7ABE294D, 829 | 0xDA5CD7E4, 830 | 0xB8A4C184, 831 | 0x5E6DCC72, 832 | 0x8C48E85A, 833 | 0x7AA81C9C, 834 | 0x618D1974, 835 | 0xB8927BFB, 836 | 0x5BF0DEE1, 837 | 0xF4003E3E, 838 | 0xC8ADE18D, 839 | 0x2894223F, 840 | 0x5650DB2B, 841 | 0x35C553FF, 842 | 0x19593A29, 843 | 0x4FA98676, 844 | 0xE3BD74B9, 845 | 0xD56BE9E8, 846 | 0xAA4033D1, 847 | 0x3FCA2433, 848 | 0x6EAC1A6F, 849 | 0xA2A63124, 850 | 0xA305D1F8, 851 | 0x55772D82, 852 | 0x4E05973D, 853 | 0xF1206C80, 854 | 0x71B41976, 855 | 0xEF2BB658, 856 | 0xF2AEFAE1, 857 | 0x8B983F45, 858 | 0x2296748C, 859 | 0x87EBC008, 860 | 0xBF05F6FC, 861 | 0xA08136E8, 862 | 0x2CD9DD52, 863 | 0xDC3EE0A2, 864 | 0xD3BBEBD9, 865 | 0x5F83F862, 866 | 0x79EDC74B, 867 | 0x9F48F8A6, 868 | 0xA0D2BE15, 869 | 0x10C77944, 870 | 0x1A248FC3, 871 | 0x1F80F5F8, 872 | 0x1E2A6911, 873 | 0x814AA9CE, 874 | 0x78657363, 875 | 0xD80E2B5B, 876 | 0xC5B7C4AD, 877 | 0x9C784CB0, 878 | 0xABF3344C, 879 | 0x2A7D7A0C, 880 | 0x17AFC08D, 881 | 0xFAFE52DE, 882 | 0x2E4072E9, 883 | 0x86F0FF26, 884 | 0x6B5CE6AD, 885 | 0x60FDB6DD, 886 | 0xF78B78CA, 887 | 0x66185444, 888 | 0x036F62E4, 889 | 0xDC4A360C, 890 | 0x4526A3CA, 891 | 0x20B28BE7, 892 | 0x0EE4B33B, 893 | 0x19A4C567, 894 | 0x3EF7DDDE, 895 | 0x3B2D6F1F, 896 | 0xEDA813C3, 897 | 0x6E16CF52, 898 | 0x23DF5A5B, 899 | 0x8FC2BE7F, 900 | 0x534A20EB, 901 | 0x5CCE6213, 902 | 0xD9B8F734, 903 | 0xBB7A6B2A, 904 | 0xFD41069C, 905 | 0xD82084B1, 906 | 0x7FBA825A, 907 | 0xCFE30C5E, 908 | 0xADB22A97, 909 | 0xF7A83E4C, 910 | 0x32460BB4, 911 | 0x19CAC570, 912 | 0x79D112AB, 913 | 0xB626FA0E, 914 | 0x785CA7F8, 915 | 0xC8DD26A5, 916 | 0xC4ADADC1, 917 | 0x8E2B912A, 918 | 0xD78F96A2, 919 | 0x88A9592D, 920 | 0xCF78B2A7, 921 | 0x89C0A37B, 922 | 0xAD000D72, 923 | 0xF4497448, 924 | 0x771E5FEF, 925 | 0xFF27D8C1, 926 | 0x4F036B06, 927 | 0x8943B5EC, 928 | 0xDCA4A196, 929 | 0x75BA9309, 930 | 0xCD1134E1, 931 | 0x998014FB, 932 | 0x0B69F351, 933 | 0x6D7F99F4, 934 | 0x83199DFF, 935 | 0x3EED56A2, 936 | 0x520A7A42, 937 | 0xF7523D0D, 938 | 0x1B4070D8, 939 | 0x691AC352, 940 | 0x6DEDB87E, 941 | 0xE545CD0A, 942 | 0xA316DDCB, 943 | 0xF845920D, 944 | 0xB2FCFAC5, 945 | 0xE0100243, 946 | 0xAE770955, 947 | 0x4B28D7D3, 948 | 0x3B6C0CA5, 949 | 0x5E2677BD, 950 | 0x53898790, 951 | 0x2BD7B591, 952 | 0x892E6BA7, 953 | 0x77EC7A1D, 954 | 0x2CAEEB6F, 955 | 0x93A543B2, 956 | 0x2AD12738, 957 | 0x94D02A72, 958 | 0x82B99541, 959 | 0x5FB78A8D, 960 | 0x00337DAA, 961 | 0xF01A076C, 962 | 0x1D43115A, 963 | 0x74633C35, 964 | 0x2B7C0246, 965 | 0x60F2B86A, 966 | 0xBC73BE3B, 967 | 0xD4EB5A9E, 968 | 0x9223B150, 969 | 0x079ED3F8, 970 | 0x834C6F2E, 971 | 0xCF057F27, 972 | 0x7DAA7F4A, 973 | 0xF38350D2, 974 | 0x9595436D, 975 | 0x5A433D2C, 976 | 0x033960C8, 977 | 0x09AD443A, 978 | 0x3BE32FA2, 979 | 0xFC7C33B6, 980 | 0xF463C71D, 981 | 0x88B08A53, 982 | 0x7515D061, 983 | 0xC0194A48, 984 | 0x85B2D598, 985 | 0xD912730B, 986 | 0x9C898C7E, 987 | 0x8A087903, 988 | 0x88A0DEA0, 989 | 0xE01F2B9E, 990 | 0xCB3A0335, 991 | 0xF493161A, 992 | 0xA7AB789B, 993 | 0x9FFB20BB, 994 | 0x6D13A7F7, 995 | 0x445AB370, 996 | 0x4207D91E, 997 | 0x08988A8B, 998 | 0xA9A13AD2, 999 | 0x7E5553CD, 1000 | 0xCD487638, 1001 | 0xA8B49E29, 1002 | 0xD76F4FBB, 1003 | 0x70BC168B, 1004 | 0x437A3C7E, 1005 | 0x4FB77296, 1006 | 0xD89FDF21, 1007 | 0xD3922695, 1008 | 0xA399002B, 1009 | 0xC2F4E68E, 1010 | 0x470F00A3, 1011 | 0x6F6245B6, 1012 | 0x0992648D, 1013 | 0x616498ED, 1014 | 0x78A58314, 1015 | 0x856D89FD, 1016 | 0x16AA49D3, 1017 | 0x0BCA417C, 1018 | 0x7CCB4BE7, 1019 | 0xF039AC51, 1020 | 0x1DAC7920, 1021 | 0xCCF9D3BB, 1022 | 0xFD432119, 1023 | 0x21D5D4A0, 1024 | 0xF401CD39, 1025 | 0x917BDF83, 1026 | 0x5F2F65A2, 1027 | 0x1DEAB74C, 1028 | 0x625A87B4, 1029 | 0x0BAD69BE, 1030 | 0x6A9896D0, 1031 | 0x21ECF07F, 1032 | 0x3D2B1822, 1033 | 0x8F862700, 1034 | 0xB0A49131, 1035 | 0x834815BD, 1036 | 0x8AD278C4, 1037 | 0x573A83FB, 1038 | 0x5C800AB8, 1039 | 0xA3DDA145, 1040 | 0xF2D90BD6, 1041 | 0xB972C401, 1042 | /* 1043 | }; 1044 | 1045 | const uint32_t BFLOC blowfish_P[18] __attribute__((aligned(0x100))) = 1046 | { 1047 | */ 1048 | 0x2683A24E, 1049 | 0xBFEFD1CD, 1050 | 0x3B9D95A9, 1051 | 0x9E26E9D0, 1052 | 0xD013180A, 1053 | 0x14061CC8, 1054 | 0xC79DCF73, 1055 | 0xF0F0D118, 1056 | 0xBFB3894E, 1057 | 0x04A16FF1, 1058 | 0xF758A8E4, 1059 | 0xA343C3AA, 1060 | 0x345B3D5B, 1061 | 0x967E842B, 1062 | 0x8A085327, 1063 | 0x783C8B8F, 1064 | 0xDA0FB98E, 1065 | 0x52B3FA03 1066 | }; 1067 | -------------------------------------------------------------------------------- /src/coreboot.c: -------------------------------------------------------------------------------- 1 | //#define COREBOOT_DBG 2 | 3 | #include 4 | #ifdef COREBOOT_DBG 5 | #include 6 | #endif 7 | #include "pico/platform.h" 8 | #include "pico/multicore.h" 9 | #include "hardware/irq.h" 10 | #include "hardware/regs/dreq.h" 11 | #include "hardware/structs/bus_ctrl.h" 12 | #include "hardware/structs/xip_ctrl.h" 13 | #include "hardware/structs/dma.h" 14 | 15 | 16 | //extern int __StackOneTop; 17 | 18 | extern int __memebank2_start__; 19 | extern int __memebank2_end__; 20 | extern int __memebank2_source__; 21 | extern int __memebank3_start__; 22 | extern int __memebank3_end__; 23 | extern int __memebank3_source__; 24 | extern int __memedata_start__; 25 | extern int __memedata_end__; 26 | extern int __memedata_source__; 27 | 28 | static __attribute__((noinline)) void data_cpy(int dummy, int* src, int* dst, int* end) 29 | { 30 | if((uintptr_t)src < 0x10000000 || (uintptr_t)src >= 0x14000000) 31 | return; 32 | 33 | end = (typeof(end))(((uintptr_t)end)+3); 34 | 35 | uint32_t cnt = (((uintptr_t)end) - ((uintptr_t)dst)) >> 2; 36 | if(!cnt) 37 | return; 38 | 39 | if(cnt >= (128 >> 2)) 40 | { 41 | while(!(xip_ctrl_hw->stat & XIP_STAT_FIFO_EMPTY_BITS)) 42 | (void)xip_ctrl_hw->stream_fifo; 43 | 44 | dma_channel_hw_t* dma = &dma_hw->ch[0]; 45 | dma->read_addr = (uintptr_t)&xip_ctrl_hw->stream_fifo; 46 | dma->write_addr = (uintptr_t)dst; 47 | dma->transfer_count = cnt; 48 | dma->ctrl_trig = 0 49 | | (DMA_CH0_CTRL_TRIG_EN_BITS) 50 | | (DMA_CH0_CTRL_TRIG_DATA_SIZE_VALUE_SIZE_WORD << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB) 51 | | ((0) << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB) 52 | | (DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS) 53 | | (DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS) 54 | | (DMA_CH0_CTRL_TRIG_IRQ_QUIET_BITS) 55 | | ((DREQ_XIP_STREAM) << DMA_CH0_CTRL_TRIG_TREQ_SEL_LSB) 56 | ; 57 | 58 | xip_ctrl_hw->stream_addr = (uintptr_t)src; 59 | xip_ctrl_hw->stream_ctr = cnt; 60 | 61 | // There are surely better ways to do this 62 | //while(__builtin_expect(dma->al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS, true)) 63 | while(__builtin_expect(dma->transfer_count, true)) 64 | tight_loop_contents(); 65 | 66 | /* 67 | do 68 | { 69 | while(__builtin_expect(xip_ctrl_hw->stat & XIP_STAT_FIFO_EMPTY_BITS, false)) 70 | tight_loop_contents(); 71 | 72 | *(dst++) = xip_ctrl_hw->stream_fifo; 73 | } 74 | while(__builtin_expect(--cnt, true)); 75 | */ 76 | } 77 | else 78 | { 79 | int dat; 80 | asm volatile( 81 | "n_loop:" 82 | "LDMIA %[src]!, {%[datp]}\n\t" 83 | "STMIA %[dst]!, {%[datp]}\n\t" 84 | "CMP %[endp], %[dst]\n\t" 85 | "BHI n_loop" 86 | : [datp]"=&r"(dat), [src]"+r"(src), [dst]"+r"(dst) 87 | : [endp]"r"(end) 88 | : "memory", "cc"); 89 | 90 | // gcc being garbage 91 | /* 92 | volatile int* dst_ = dst; 93 | 94 | while(dst_ < end) 95 | *(dst_++) = *(src++); 96 | */ 97 | } 98 | } 99 | 100 | void coreboot(void(*pfn)(void)) 101 | { 102 | bool isirq = irq_is_enabled(SIO_IRQ_PROC0); 103 | irq_set_enabled(SIO_IRQ_PROC0, false); 104 | 105 | #if !defined(PICO_NO_FLASH) || !PICO_NO_FLASH 106 | #ifdef COREBOOT_DBG 107 | puts("+ data_cpy"); 108 | #endif 109 | 110 | // Give way to DMA during init! 111 | bus_ctrl_hw->priority = 0 112 | | BUSCTRL_BUS_PRIORITY_DMA_R_BITS 113 | | BUSCTRL_BUS_PRIORITY_DMA_W_BITS 114 | ; 115 | //while(!(bus_ctrl_hw->priority_ack & BUSCTRL_BUS_PRIORITY_ACK_BITS)) 116 | // tight_loop_contents(); 117 | 118 | data_cpy(0, &__memebank2_source__, &__memebank2_start__, &__memebank2_end__); 119 | data_cpy(0, &__memebank3_source__, &__memebank3_start__, &__memebank3_end__); 120 | 121 | data_cpy(0, &__memedata_source__, &__memedata_start__, &__memedata_end__); 122 | #else 123 | #ifdef COREBOOT_DBG 124 | puts("+ no cpy (NO FLASH)"); 125 | #endif 126 | #endif 127 | 128 | #ifdef COREBOOT_DBG 129 | puts("+ bootseq"); 130 | #endif 131 | 132 | //const uint32_t cmd_sequence[] = {0, 0, 1, (uintptr_t)(*(io_ro_32*)0xE000ED08), (uintptr_t)&__StackOneTop, ((uintptr_t)pfn) | 1}; 133 | const uint32_t cmd_sequence[] = {0, 0, 1, (uintptr_t)(*(io_ro_32*)0xE000ED08), (uintptr_t)0x20041800, ((uintptr_t)pfn) | 1}; 134 | uint seq = 0; 135 | do 136 | { 137 | uint cmd = cmd_sequence[seq]; 138 | if(!cmd) 139 | { 140 | #ifdef COREBOOT_DBG 141 | puts("+ - drain"); 142 | #endif 143 | 144 | multicore_fifo_drain(); 145 | __sev(); 146 | } 147 | 148 | #ifdef COREBOOT_DBG 149 | printf("+ - push %08X\n", cmd); 150 | #endif 151 | 152 | multicore_fifo_push_blocking(cmd); 153 | 154 | uint32_t response = multicore_fifo_pop_blocking(); 155 | 156 | #ifdef COREBOOT_DBG 157 | printf("+ - pop %08X\n", response); 158 | #endif 159 | 160 | if(cmd == response) 161 | ++seq; 162 | else 163 | seq = 0; 164 | } 165 | while(seq < count_of(cmd_sequence)); 166 | 167 | #ifdef COREBOOT_DBG 168 | puts("+ booted?"); 169 | #endif 170 | 171 | irq_set_enabled(SIO_IRQ_PROC0, isirq); 172 | } 173 | -------------------------------------------------------------------------------- /src/frm.c: -------------------------------------------------------------------------------- 1 | // FIRM header 2 | // Currently contains https://github.com/aspargas2/minfirm 3 | 4 | const unsigned char nfirmdata[0x200] __attribute__((aligned(0x200))) = 5 | { 6 | 70, 73, 82, 77,127,176, 27,224, 1,160,255, 31, 5, 59, 0, 0, 7 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10 | 38,160, 33, 73, 32, 34, 1, 39, 0, 0, 0, 0,236,247, 80,236, 11 | 141, 1,156, 53,239, 97,238,247, 79,250,241,247,181,253,120, 2, 12 | 25, 78, 57, 7, 10,106, 2, 67,186, 67, 10, 98, 1, 48, 23, 75, 13 | 27,136,155, 10, 3,209, 55, 98, 0, 0, 0, 0,120, 2,241,247, 14 | 249,253, 44,106, 60, 67, 44, 98, 15, 74, 36, 50, 1, 33, 16, 72, 15 | 241,247, 50,253,112,106, 15, 73,136, 66,236,209, 4, 36,100, 54, 16 | 13,206, 89, 10, 6,208, 64, 10, 0, 0, 0, 0, 8, 75,192, 24, 17 | 241,247, 34,253, 36, 54, 1, 60,242,209, 3, 75, 28,107, 27, 98, 18 | 0, 32, 0, 33, 0, 34, 32, 71,224,191,255, 31, 0, 96, 20, 16, 19 | 0,192, 5, 0, 70, 73, 82, 77, 0, 0, 0, 0, 7, 72, 1, 40, 20 | 252,211, 1,208, 8, 72, 0, 71, 64, 7,133, 70, 2, 75, 3, 32, 21 | 41, 33, 6, 34,152, 71,241,231,205, 53, 1, 0, 0, 0, 0, 0, 22 | 55,233,107, 16,186,242,140,116,167, 16,239, 53,130, 76,147,245, 23 | 251,179, 65,206,228,251, 68,108,228,210,144,171,252,239,172,176, 24 | 99,169,181, 91, 62,138,101, 81, 29,144, 12, 90,110,148, 3,170, 25 | 181,148, 60,239, 58, 30,136, 43,119,210, 52,121, 66,185,233,235, 26 | 13,117,102, 55, 15, 12,183, 49, 12, 56,203, 74,201, 64,209,166, 27 | 187, 71,107,204, 44, 72,125, 28, 83, 33, 32,241,210,163,125,219, 28 | 62, 54,248,162,148, 91,216,177,111,179, 84,152, 3,132,153,142, 29 | 204, 56, 12,213,207,133, 48,241,218,210,253,116,186, 53,172,185, 30 | 201,218, 44, 19, 28,178,149,115,106,231,239,160,210,104,238, 1, 31 | 135, 46,240, 51, 5,138,186, 7,181,198,132,234,214, 13,118,234, 32 | 132,161,141,134, 99, 7,170,170,183,100,120,110, 57,111, 47,139, 33 | 99, 14, 96,227, 14, 63, 28,216,166,125, 2,240,168,129, 82,222, 34 | 122,158, 13,213,230, 74,183, 89, 58, 55, 1,228,132,107,111, 51, 35 | 141, 34,253, 69, 93, 69,223, 33, 44, 85,119, 38,106,168,195,103, 36 | 174,110, 76,232,157,244, 22,145,191, 31,127,229,143, 34, 97,245, 37 | 210, 81,223, 54,222,159, 90,241,243,104,230, 80,213,118,129, 11 38 | }; 39 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | main.c - Nitro Emulated Gamecart sequencer 3 | Copyright (C) 2022 Sono (https://github.com/SonoSooS) 4 | All Rights Reserved 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include "pico/stdlib.h" 11 | #include "pico/multicore.h" 12 | #include "pico/platform.h" 13 | #include "pico/sync.h" 14 | #include "hardware/exception.h" 15 | #include "hardware/dma.h" 16 | #include "hardware/irq.h" 17 | #include "hardware/structs/xip_ctrl.h" 18 | #include "hardware/structs/sio.h" 19 | #include "hardware/gpio.h" 20 | 21 | #include "memeloc.h" 22 | 23 | #include "neg.h" 24 | #include "bf.h" 25 | #include "png.h" 26 | 27 | #define ENSURE_MODE(f) MEMELOC_RAM_F(f) 28 | //#define ENSURE_MODE(f) __noinline MEMELOC_RAM_F(f) 29 | //#define ENSURE_MODE(f) __not_in_flash_func(f) 30 | //#define ENSURE_MODE(f) __no_inline_not_in_flash_func(f) 31 | #define ENSURE_MODE_NOINLINE(f) __noinline MEMELOC_RAM_F(f) 32 | //#define ENSURE_MODE_NOINLINE(f) __no_inline_not_in_flash_func(f) 33 | 34 | 35 | static uint32_t readhead; 36 | static uint32_t ensurehead; 37 | static volatile int32_t png_lastsize; 38 | 39 | void main1(void); 40 | 41 | static bool ENSURE_MODE(can)(int32_t count) 42 | { 43 | int32_t currpos = (*dmadstptr & DMALOG_BITS) >> 2; 44 | return (currpos - readhead) >= count; 45 | } 46 | 47 | static bool ENSURE_MODE(is)(void) 48 | { 49 | return can(1); 50 | } 51 | 52 | static void ENSURE_MODE_NOINLINE(ensure)(int32_t count) 53 | { 54 | ensurehead = readhead; 55 | int32_t until = readhead + count; 56 | for(;;) 57 | { 58 | int32_t currpos = (*dmadstptr & DMALOG_BITS) >> 2; 59 | if(currpos < until) 60 | continue; 61 | 62 | if(currpos > readhead) 63 | break; 64 | 65 | break; 66 | } 67 | 68 | readhead = until; 69 | } 70 | 71 | static uint32_t ENSURE_MODE(ensure1)(void) 72 | { 73 | ensure(1); 74 | return dmadstbuf[ensurehead]; 75 | } 76 | 77 | static void bfTest(uint32_t cmd_hi, uint32_t cmd_lo) 78 | { 79 | uint32_t dec_hi = cmd_hi; 80 | uint32_t dec_lo = cmd_lo; 81 | 82 | bfDecrypt(&dec_hi, &dec_lo); 83 | 84 | printf("- TEST: %08X %08X | %08X %08X\n", cmd_hi, cmd_lo, dec_hi, dec_lo); 85 | } 86 | 87 | static void bfTests(void) 88 | { 89 | puts("Doing Blowfish tests!"); 90 | 91 | bfTest(0xD1159B87, 0x34726BB6); 92 | bfTest(0xFF3945E0, 0xEA2F7482); 93 | bfTest(0xCB925087, 0xE6F5E201); 94 | puts(""); 95 | 96 | bfTest(0x5685C4A2, 0xED5C6690); 97 | bfTest(0xFD53D199, 0xA37E7D19); 98 | bfTest(0x7D2FFEA5, 0xCAC1FE71); 99 | bfTest(0xFD2CE53F, 0xEA7DD457); 100 | bfTest(0x8CE6C3E3, 0xAF485482); 101 | //bfTest(); 102 | 103 | puts("Blowfish test end."); 104 | } 105 | 106 | static void pngTest(void) 107 | { 108 | pngInit(0xBE5D0F, 0xE8); 109 | pngPreinit(); 110 | 111 | for(uint32_t i = 0; i < 16; i++) 112 | { 113 | printf("%5i: %02X\n", i, pngDo()); 114 | } 115 | } 116 | 117 | #define main1_fifo_pop multicore_fifo_pop_blocking 118 | #define main1_fifo_push multicore_fifo_push_blocking 119 | 120 | /* 121 | uint32_t MEMELOC_BANK2_F(main1_fifo_pop)(void) 122 | { 123 | sio_hw_t* sio = sio_hw; 124 | while(!(sio->fifo_st & SIO_FIFO_ST_VLD_BITS)) 125 | __wfe(); 126 | return sio->fifo_rd; 127 | } 128 | 129 | void MEMELOC_BANK2_F(main1_fifo_push)(uint32_t data) 130 | { 131 | sio_hw_t* sio = sio_hw; 132 | while(!(sio->fifo_st & SIO_FIFO_ST_RDY_BITS)) 133 | tight_loop_contents(); 134 | sio->fifo_wr = data; 135 | __sev(); 136 | } 137 | */ 138 | 139 | void MEMELOC_RAM_F(negDoHighperf)(void) 140 | { 141 | uint32_t irq = save_and_disable_interrupts(); 142 | 143 | ensure(2); // Read dummy 3C begin and end 144 | 145 | ensure(2); 146 | uint32_t cmd_hi = dmadstbuf[ensurehead + 0]; // Read 4x cmd hi 147 | uint32_t cmd_lo = dmadstbuf[ensurehead + 1]; // Read 4x cmd lo 148 | 149 | uint32_t dec_hi = cmd_hi; 150 | uint32_t dec_lo = cmd_lo; 151 | bfDecrypt(&dec_hi, &dec_lo); 152 | 153 | if(can(2)) 154 | { 155 | puts("Too late to decrypt cmd!"); 156 | 157 | printf("ENC: %08X %08X\n", cmd_hi, cmd_lo); 158 | printf("DEC: %08X %08X\n", dec_hi, dec_lo); 159 | } 160 | else 161 | { 162 | uint32_t seed = ((dec_lo >> (32 - 12)) | (dec_hi << 12)) & 0xFFFFFF; 163 | multicore_fifo_push_blocking(seed); // Kick off KEY2 stream init 164 | png_prog = 0; 165 | multicore_fifo_push_blocking(0x910 + 4); // Kick off KEY2 stream gen 166 | 167 | if(png_prog < (0x910 + 4)) 168 | { 169 | while(png_prog < (0x910 + 4)) // Wait to reach KEY2 stream 170 | tight_loop_contents(); 171 | } 172 | else 173 | { 174 | puts("Bad tight timing..."); 175 | } 176 | 177 | uint32_t key2 = png_buf[0x910 >> 2]; 178 | 179 | if(!can(2)) // KEY2 enable command still active(good) 180 | { 181 | ensure(2); // Read start and end flag 182 | 183 | negDMAFillFIFO(0x910); 184 | while((zerodma->al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS) && zerodma->transfer_count) 185 | tight_loop_contents(); 186 | 187 | //puts("Pushing data"); 188 | 189 | //negBlockingDummy(0x910, 0); 190 | negBlockingWrite(key2); 191 | negBlockingWrite(key2 >> 8); 192 | negBlockingWrite(key2 >> 16); 193 | negBlockingWrite(key2 >> 24); 194 | 195 | 196 | ensure(4); // Wait for sCardID query cmd to finish 197 | 198 | negDMAFillFIFO(0x910); 199 | multicore_fifo_push_blocking(0x910); // Restart HiZ area keygen 200 | 201 | 202 | if(can(1)) 203 | { 204 | puts("Key init done, but too late"); 205 | } 206 | else 207 | { 208 | //printf("Key init done 0x%06X\n", seed); 209 | 210 | //ensure(4); 211 | } 212 | 213 | // ??? 214 | 215 | //negBlockingRead(); // sChipID read cmd hi 216 | //negBlockingRead(); // sChipID read cmd lo 217 | //negBlockingRead(); // sChipID read cmd begin 218 | //negBlockingRead(); // sChipID read cmd end 219 | 220 | //puts("FUCK YEAH!"); 221 | } 222 | else 223 | { 224 | puts("Too late to write!"); 225 | } 226 | 227 | //printf("ENC: %08X %08X\n", cmd_hi, cmd_lo); 228 | //printf("DEC: %08X %08X\n", dec_hi, dec_lo); 229 | } 230 | 231 | restore_interrupts(irq); 232 | } 233 | 234 | 235 | static uint8_t MEMELOC_RAM_N("main") firmbuf[0x1000]; 236 | 237 | uint32_t MEMELOC_RAM_F(negDoKeyCmd)(uint32_t cmd_hi, uint32_t cmd_lo, uint32_t bad) 238 | { 239 | uint32_t irq = save_and_disable_interrupts(); 240 | 241 | uint32_t raw_cmd = cmd_hi >> 28; 242 | 243 | if(raw_cmd == 2) 244 | { 245 | while(png_prog < 0x910) 246 | tight_loop_contents(); 247 | 248 | png_prog = 0; 249 | int32_t datasize = (0x200 * 8) + (0x18 * (8 - 1)); 250 | multicore_fifo_push_blocking(datasize); 251 | 252 | const uint8_t* bufptr = ((const uint8_t*)png_buf); 253 | uint32_t sect = (cmd_hi >> 12) & 0xFFFF; 254 | 255 | if(!zerodma->transfer_count) 256 | { 257 | puts("DMA too slow"); 258 | } 259 | else 260 | { 261 | //puts("+ Waiting for DMA"); 262 | //while(zerodma->al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS) 263 | // tight_loop_contents(); 264 | 265 | while((zerodma->al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS) && zerodma->transfer_count) 266 | tight_loop_contents(); 267 | 268 | //puts("+ DMA done"); 269 | } 270 | 271 | if(!bad) 272 | { 273 | if(__builtin_expect(sect == 7, true)) 274 | //if(0) 275 | { 276 | const uint8_t* xorptr = ((const uint8_t*)firmbuf); 277 | 278 | for(uint32_t j = 0; j != 8; j++) 279 | { 280 | for(uint32_t i = 0; i != 0x200; i++) 281 | { 282 | if(__builtin_expect(png_prog >= i, true)) 283 | { 284 | uint8_t data = (*bufptr) ^ (*xorptr); 285 | negBlockingWrite(data); 286 | ++bufptr; 287 | ++xorptr; 288 | continue; 289 | } 290 | 291 | printf("KEYGEN TOO SLOW @ %X\n", i); 292 | goto fastend; 293 | } 294 | 295 | if(__builtin_expect(j != 7, true)) 296 | { 297 | for(uint32_t i = 0; i != 0x18; i++) 298 | { 299 | negBlockingWrite(*bufptr); 300 | ++bufptr; 301 | } 302 | } 303 | } 304 | } 305 | else 306 | { 307 | for(uint32_t i = 0; i != datasize; ++i) 308 | { 309 | if(__builtin_expect(png_prog >= i, true)) 310 | { 311 | negBlockingWrite(*bufptr); 312 | ++bufptr; 313 | continue; 314 | } 315 | 316 | printf("Keygen is too slow, oops @ %X\n", i); 317 | goto fastend; 318 | } 319 | } 320 | 321 | goto fastend; 322 | } 323 | } 324 | else 325 | { 326 | printf("Unknown cmd: %1X\n", raw_cmd); 327 | } 328 | 329 | if(__builtin_expect(png_prog < png_lastsize, false)) 330 | { 331 | printf("- Unfinished KEY2 stream! %X/%X\n", png_prog, png_lastsize); 332 | 333 | while(png_prog < png_lastsize) 334 | tight_loop_contents(); 335 | 336 | puts("- KEY2 stream done"); 337 | } 338 | 339 | if(__builtin_expect(zerodma->al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS, false)) 340 | { 341 | printf("- Unfinished fill DMA! rem=%X\n", zerodma->transfer_count); 342 | while(zerodma->al1_ctrl & DMA_CH0_CTRL_TRIG_BUSY_BITS) 343 | tight_loop_contents(); 344 | 345 | puts("- DMA fill done"); 346 | } 347 | 348 | fastend: 349 | restore_interrupts(irq); 350 | 351 | ensure(2); 352 | 353 | if(!can(1)) 354 | { 355 | negDMAFillFIFO(0x910); 356 | bad = 0; 357 | if(can(2)) 358 | bad |= 4; 359 | 360 | multicore_fifo_push_blocking(0x910); 361 | 362 | } 363 | else 364 | { 365 | bad = 0; 366 | 367 | bad |= 2; 368 | 369 | if(!negCanDrain()) 370 | bad |= 1; 371 | } 372 | 373 | return bad; 374 | } 375 | 376 | void MEMELOC_RAM_F(sMainLoop)(void) 377 | { 378 | bool had_KEY2 = false; 379 | 380 | uint32_t bad = 0; 381 | 382 | //uint32_t irq = save_and_disable_interrupts(); 383 | 384 | for(;;) 385 | { 386 | ensure(2); 387 | uint32_t cmd_hi = dmadstbuf[ensurehead + 0]; 388 | uint32_t cmd_lo = dmadstbuf[ensurehead + 1]; 389 | 390 | if(had_KEY2) 391 | { 392 | uint32_t dec_hi = cmd_hi; 393 | uint32_t dec_lo = cmd_lo; 394 | bfDecrypt(&dec_hi, &dec_lo); 395 | bad = negDoKeyCmd(dec_hi, dec_lo, bad); 396 | 397 | 398 | //ensure(1); 399 | //ensure(2); 400 | 401 | if(!bad) 402 | { 403 | //negDMAFillFIFO(0x910); 404 | //multicore_fifo_push_blocking(0x910); 405 | } 406 | else 407 | { 408 | if(bad & 1) 409 | { 410 | puts("! Write FIFO is bad"); 411 | } 412 | if(bad & 2) 413 | { 414 | puts("! Processing too slow"); 415 | } 416 | if(bad & 4) 417 | { 418 | puts("! Risky bullshit too late"); 419 | } 420 | 421 | printf("KC2: %08X %08X\n", dec_hi, dec_lo); 422 | } 423 | 424 | 425 | //printf("KC2: %08X %08X\n", dec_hi, dec_lo); 426 | //printf("CMD: %08X %08X\n", cmd_hi, cmd_lo); 427 | //ensure(1); 428 | 429 | //printf("db1: %08X\n", ensure1()); 430 | //printf("db2: %08X\n", ensure1()); 431 | //ensure(2); 432 | continue; 433 | } 434 | else if((cmd_hi >> 24) == 0x3C) 435 | { 436 | negDoHighperf(); 437 | had_KEY2 = true; 438 | //restore_interrupts(irq); 439 | continue; 440 | } 441 | 442 | //printf("CMD: %08X %08X\n", cmd_hi, cmd_lo); 443 | //printf("es1: %08X\n", ensure1()); 444 | //printf("es2: %08X\n", ensure1()); 445 | ensure(2); 446 | } 447 | } 448 | 449 | void coreboot(void(*pfn)(void)); 450 | 451 | static __attribute__((noinline)) void faulthandler_real(uint32_t* extdata) 452 | { 453 | printf("HARDFAULT Core%u\n", *(io_ro_32*)0xD0000000); 454 | printf("r0: %08X\n", extdata[0]); 455 | printf("r1: %08X\n", extdata[1]); 456 | printf("r2: %08X\n", extdata[2]); 457 | printf("r3: %08X\n", extdata[3]); 458 | printf("12: %08X\n", extdata[4]); 459 | printf("LR: %08X\n", extdata[5]); 460 | printf("PC: %08X\n", extdata[6]); 461 | printf("CP: %08X\n", extdata[7]); 462 | puts("yeah... well crap"); 463 | 464 | for(;;) 465 | { 466 | gpio_put(PICO_DEFAULT_LED_PIN, true); 467 | sleep_ms(200); 468 | gpio_put(PICO_DEFAULT_LED_PIN, false); 469 | sleep_ms(200); 470 | } 471 | } 472 | 473 | static __attribute__((noinline, naked)) void faulthandler(void) 474 | { 475 | asm volatile( 476 | "MRS r0, MSP\n\t" 477 | "BX %[asd]" 478 | : 479 | : [asd] "r" (faulthandler_real) 480 | : "memory"); 481 | } 482 | 483 | extern const uint8_t nfirmdata[0x200]; 484 | 485 | void main(void) 486 | { 487 | // Make regulator stable 488 | //gpio_init(23); 489 | //gpio_set_dir(23, GPIO_OUT); 490 | //gpio_put(23, true); 491 | 492 | //sleep_ms(150); // Wait for regulator to stabilize 493 | 494 | set_sys_clock_khz(250000, true); 495 | 496 | gpio_init(PICO_DEFAULT_LED_PIN); 497 | gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); 498 | gpio_put(PICO_DEFAULT_LED_PIN, false); 499 | 500 | gpio_init(1); 501 | gpio_set_dir(1, GPIO_OUT); 502 | gpio_put(1, false); 503 | 504 | gpio_init(0); 505 | gpio_set_dir(0, GPIO_IN); 506 | gpio_set_pulls(0, true, false); 507 | 508 | readhead = 0; 509 | ensurehead = 0; 510 | png_lastsize = 0; 511 | 512 | if(gpio_get(0)) 513 | { 514 | //stdio_usb_init(); 515 | //sleep_ms(1000); 516 | 517 | stdio_uart_init(); 518 | 519 | puts("Hello from USB!"); 520 | } 521 | 522 | gpio_set_pulls(0, false, false); 523 | gpio_set_dir(1, GPIO_IN); 524 | 525 | exception_set_exclusive_handler(HARDFAULT_EXCEPTION, faulthandler); 526 | 527 | memset(firmbuf, 0, sizeof(firmbuf)); 528 | firmbuf[0xE00] = (uint8_t)'F'; 529 | firmbuf[0xE01] = (uint8_t)'I'; 530 | firmbuf[0xE02] = (uint8_t)'R'; 531 | firmbuf[0xE03] = (uint8_t)'M'; 532 | memcpy(firmbuf + 0xE00, nfirmdata, 0x200); 533 | 534 | coreboot(main1); // Setup rest of the environment, and launch Core1 535 | //puts("- push"); 536 | 537 | //bfTests(); 538 | //pngTest(); 539 | 540 | //multicore_fifo_push_blocking(0xF00FC0CC); 541 | main1_fifo_push(0xF00FC0CC); 542 | 543 | //puts("- wait for pop"); 544 | while(main1_fifo_pop() != 0x55AA00F1) tight_loop_contents(); 545 | multicore_fifo_drain(); 546 | puts("Setup complete, running"); 547 | 548 | gpio_put(PICO_DEFAULT_LED_PIN, true); 549 | /* 550 | { 551 | 552 | volatile int lol = 125000000 / 4 / 4; 553 | while(--lol) 554 | ; 555 | 556 | gpio_put(PICO_DEFAULT_LED_PIN, false); 557 | } 558 | */ 559 | 560 | sMainLoop(); 561 | } 562 | 563 | void MEMELOC_BANK2_F(main1)(void) 564 | { 565 | //puts("? hello Core1"); 566 | 567 | while(main1_fifo_pop() != 0xF00FC0CC) 568 | tight_loop_contents(); 569 | 570 | //puts("? random init"); 571 | 572 | //puts("Hello from Core1!"); 573 | 574 | negInit(); 575 | negResetFull(); 576 | 577 | pngPreinit(); 578 | png_prog = 0; 579 | //png_buf[0] = 0x55AA69CC; 580 | //png_buf[1] = 0x55AA69CC; 581 | //png_buf[2] = 0x55AA69CC; 582 | //png_buf[3] = 0x55AA69CC; 583 | 584 | //puts("? push ready"); 585 | 586 | main1_fifo_push(0x55AA00F1); 587 | multicore_fifo_drain(); 588 | 589 | //puts("? pushed, initing..."); 590 | 591 | negEnable(); 592 | 593 | //puts("? wait for C&C"); 594 | 595 | pngInit(main1_fifo_pop(), 0xE8); 596 | for(;;) 597 | { 598 | uint32_t newsize = main1_fifo_pop() & ~3;; 599 | png_lastsize = newsize; 600 | 601 | if(png_lastsize <= PNGBUF_SIZE) 602 | { 603 | uint32_t irq = save_and_disable_interrupts(); 604 | { 605 | pngDoBuf(png_buf, newsize, &png_prog); 606 | } 607 | restore_interrupts(irq); 608 | } 609 | else 610 | { 611 | panic("PNG requested size out of bounds: %X > %X\n", newsize, PNGBUF_SIZE); 612 | } 613 | } 614 | } 615 | -------------------------------------------------------------------------------- /src/memeloc.h: -------------------------------------------------------------------------------- 1 | 2 | #define MEMELOC_BANK2_D(d) __attribute__((section(".memebank2." d))) 3 | #define MEMELOC_BANK2_N(d) __attribute__((section(".memenbank2." d))) 4 | #define MEMELOC_BANK2_F(f) __attribute__((section(".memebank2." #f))) f 5 | 6 | #define MEMELOC_BANK3_D(d) __attribute__((section(".memebank3." d))) 7 | #define MEMELOC_BANK3_N(d) __attribute__((section(".memenbank3." d))) 8 | #define MEMELOC_BANK3_F(f) __attribute__((section(".memebank3." #f))) f 9 | 10 | #define MEMELOC_RAM_D(d) __attribute__((section(".memedata." d))) 11 | #define MEMELOC_RAM_N(d) __attribute__((section(".memenodata." d))) 12 | #define MEMELOC_RAM_F(f) __attribute__((section(".memedata." #f))) f 13 | -------------------------------------------------------------------------------- /src/neg.c: -------------------------------------------------------------------------------- 1 | /* 2 | neg.c - Nitro Emulated Gamecart glue logic 3 | Copyright (C) 2022 Sono (https://github.com/SonoSooS) 4 | All Rights Reserved 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "pico/stdlib.h" 12 | #include "pico/platform.h" 13 | #include "hardware/pio.h" 14 | #include "hardware/dma.h" 15 | #include "hardware/structs/bus_ctrl.h" 16 | #include "hardware/structs/iobank0.h" 17 | #include "hardware/structs/padsbank0.h" 18 | 19 | #include "memeloc.h" 20 | #include "neg.h" 21 | #include "png.h" 22 | #include "picart_setup.h" 23 | 24 | 25 | #define NPIN_MIN (2+0) 26 | #define NPIN_MAX (2+12) 27 | 28 | #define NLOC __scratch_x("neg") 29 | #define NFUNC(f) MEMELOC_RAM_F(f) 30 | #define DMALOC MEMELOC_BANK3_N("neg_d") 31 | 32 | 33 | static PIO NLOC pio; 34 | static int NLOC sm_proto; 35 | static int NLOC sm_clk; 36 | static int NLOC dma_from_pio; 37 | static int NLOC dma_to_pio; 38 | static int NLOC dma_to_pio_fill; 39 | 40 | dma_channel_hw_t* zerodma; 41 | 42 | //static uint8_t dmazero[PNGBUF_SIZE]; 43 | static uint8_t DMALOC dmazero[0x910 + ((0x200 + 0x18) * 8) + 4]; 44 | 45 | uint32_t DMALOC dmadstbuf[DMALOG_SIZE >> 2] __attribute__((aligned(DMALOG_SIZE))); 46 | io_ro_32* dmadstptr; 47 | //static uint32_t* NLOC dmasrcbuf; 48 | 49 | 50 | io_ro_32* NFUNC(negGetPtrRead)(void) 51 | { 52 | return &pio->rxf[sm_proto]; 53 | } 54 | 55 | io_wo_32* NFUNC(negGetPtrWrite)(void) 56 | { 57 | return &pio->txf[sm_proto]; 58 | } 59 | 60 | bool NFUNC(negCanRead)(void) 61 | { 62 | uint32_t tm = 1 << (PIO_FSTAT_RXEMPTY_LSB + sm_proto); 63 | return !(pio->fstat & tm); 64 | } 65 | 66 | bool NFUNC(negCanDrain)(void) 67 | { 68 | uint32_t tm = 1 << (PIO_FSTAT_TXEMPTY_LSB + sm_proto); 69 | return !!(pio->fstat & tm); 70 | } 71 | 72 | bool NFUNC(negCanWrite)(void) 73 | { 74 | uint32_t tm = 1 << (PIO_FSTAT_TXFULL_LSB + sm_proto); 75 | return !(pio->fstat & tm); 76 | } 77 | 78 | uint32_t NFUNC(negBlockingRead)(void) 79 | { 80 | io_ro_32* fifo = negGetPtrRead(); 81 | uint32_t tm = 1 << (PIO_FSTAT_RXEMPTY_LSB + sm_proto); 82 | while(pio->fstat & tm) tight_loop_contents(); 83 | return *fifo; 84 | } 85 | 86 | void NFUNC(negBlockingWrite)(uint32_t data) 87 | { 88 | io_wo_32* fifo = negGetPtrWrite(); 89 | uint32_t tm = 1 << (PIO_FSTAT_TXFULL_LSB + sm_proto); 90 | while(pio->fstat & tm) tight_loop_contents(); 91 | *fifo = data; 92 | } 93 | 94 | void NFUNC(negBlockingSkip)(uint32_t cnt) 95 | { 96 | io_ro_32* fifo = negGetPtrRead(); 97 | uint32_t tm = 1 << (PIO_FSTAT_RXEMPTY_LSB + sm_proto); 98 | 99 | while(cnt--) 100 | { 101 | while(pio->fstat & tm) tight_loop_contents(); 102 | (void)*fifo; 103 | } 104 | } 105 | 106 | void NFUNC(negBlockingDummy)(uint32_t cnt, uint32_t data) 107 | { 108 | io_wo_32* fifo = negGetPtrWrite(); 109 | uint32_t tm = 1 << (PIO_FSTAT_TXFULL_LSB + sm_proto); 110 | 111 | while(cnt--) 112 | { 113 | while(pio->fstat & tm) tight_loop_contents(); 114 | *fifo = data; 115 | } 116 | } 117 | 118 | void negInit(void) 119 | { 120 | pio = pio0; 121 | sm_proto = pio_claim_unused_sm(pio, true); 122 | sm_clk = pio_claim_unused_sm(pio, true); 123 | 124 | dma_from_pio = dma_claim_unused_channel(true); 125 | dma_to_pio = dma_claim_unused_channel(true); 126 | dma_to_pio_fill = dma_claim_unused_channel(true); 127 | 128 | zerodma = dma_channel_hw_addr(dma_to_pio_fill); 129 | memset(&dmazero[0], 0, sizeof(dmazero)); 130 | 131 | bus_ctrl_hw->priority = 0 132 | | BUSCTRL_BUS_PRIORITY_DMA_R_BITS 133 | | BUSCTRL_BUS_PRIORITY_DMA_W_BITS 134 | //| BUSCTRL_BUS_PRIORITY_PROC1_BITS 135 | //| BUSCTRL_BUS_PRIORITY_PROC0_BITS 136 | ; // DMA must take over! Also Core1 must take over Core0 137 | while(!(bus_ctrl_hw->priority_ack & BUSCTRL_BUS_PRIORITY_ACK_BITS)) 138 | tight_loop_contents(); 139 | 140 | //padsbank0_hw->voltage_select = PADS_BANK0_VOLTAGE_SELECT_VALUE_3V3 << PADS_BANK0_VOLTAGE_SELECT_LSB; 141 | 142 | for(uint i = NPIN_MIN; i != NPIN_MAX; ++i) 143 | { 144 | iobank0_hw->io[i].ctrl = IO_BANK0_GPIO0_CTRL_FUNCSEL_VALUE_PIO0_0 << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB; 145 | 146 | // Lowest drive, due to bugs, do not trip short detection 147 | // Data move must be decisive and fast for edge detect 148 | padsbank0_hw->io[i] = PADS_BANK0_GPIO0_RESET 149 | //& ~(PADS_BANK0_GPIO0_DRIVE_BITS) 150 | //& ~(PADS_BANK0_GPIO0_SLEWFAST_BITS) 151 | //| (PADS_BANK0_GPIO0_SLEWFAST_BITS) 152 | //| (PADS_BANK0_GPIO0_DRIVE_VALUE_2MA << PADS_BANK0_GPIO0_DRIVE_LSB) 153 | ; 154 | } 155 | 156 | picartSetup(pio, sm_proto, sm_clk); 157 | } 158 | 159 | static void negPIOReset(PIO pio) 160 | { 161 | *hw_clear_alias(&pio->ctrl) = PIO_CTRL_SM_ENABLE_BITS; 162 | *hw_set_alias(&pio->ctrl) = PIO_CTRL_CLKDIV_RESTART_BITS | PIO_CTRL_SM_RESTART_BITS; 163 | *&pio->fdebug = PIO_FDEBUG_RXSTALL_BITS | PIO_FDEBUG_RXUNDER_BITS | PIO_FDEBUG_TXOVER_BITS | PIO_FDEBUG_TXSTALL_BITS; 164 | } 165 | 166 | static void negSMResetFull(PIO pio, int smid) 167 | { 168 | pio_sm_hw_t* sm = &pio->sm[smid]; 169 | 170 | sm->clkdiv = 1 << PIO_SM0_CLKDIV_INT_LSB; 171 | sm->execctrl = PIO_SM0_EXECCTRL_WRAP_TOP_RESET << PIO_SM0_EXECCTRL_WRAP_TOP_LSB; 172 | sm->shiftctrl = PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_BITS; // Enter from right, exit to right 173 | sm->pinctrl = PIO_SM0_PINCTRL_RESET; 174 | 175 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS; 176 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS; 177 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS; 178 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS; 179 | } 180 | 181 | static void negSMReset(PIO pio, int smid) 182 | { 183 | pio_sm_hw_t* sm = &pio->sm[smid]; 184 | 185 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS; 186 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_TX_BITS; 187 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS; 188 | *hw_xor_alias(&sm->shiftctrl) = PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS; 189 | } 190 | 191 | static void negDMAReset(int dmach) 192 | { 193 | dma_channel_hw_t* dma = dma_channel_hw_addr(dmach); 194 | dma->al1_ctrl = DMA_CH0_CTRL_TRIG_AHB_ERROR_BITS | DMA_CH0_CTRL_TRIG_READ_ERROR_BITS | DMA_CH0_CTRL_TRIG_WRITE_ERROR_BITS; 195 | 196 | dma_channel_abort(dmach); 197 | 198 | dma->al1_ctrl = DMA_CH0_CTRL_TRIG_AHB_ERROR_BITS | DMA_CH0_CTRL_TRIG_READ_ERROR_BITS | DMA_CH0_CTRL_TRIG_WRITE_ERROR_BITS; 199 | } 200 | 201 | static void negDMAPostinit(void) 202 | { 203 | dma_channel_hw_t* dma = dma_channel_hw_addr(dma_from_pio); 204 | 205 | dmadstptr = &dma->write_addr; 206 | 207 | dma->read_addr = (uint32_t)negGetPtrRead(); 208 | dma->write_addr = (uint32_t)&dmadstbuf[0]; 209 | dma->transfer_count = count_of(dmadstbuf); 210 | dma->ctrl_trig = 0 211 | | (DMA_CH0_CTRL_TRIG_EN_BITS) 212 | | (DMA_CH0_CTRL_TRIG_DATA_SIZE_VALUE_SIZE_WORD << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB) 213 | | ((dma_from_pio) << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB) 214 | | (DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS) 215 | | (DMA_CH0_CTRL_TRIG_INCR_WRITE_BITS) 216 | //| (DMA_CH0_CTRL_TRIG_IRQ_QUIET_BITS) // We want to crash on FIFO read overrun 217 | //| (DMA_CH0_CTRL_TRIG_RING_SEL_BITS) 218 | //| ((15) << DMA_CH0_CTRL_TRIG_RING_SIZE_LSB) // (1 << 15) 219 | | ((DREQ_PIO0_RX0 + sm_proto) << DMA_CH0_CTRL_TRIG_TREQ_SEL_LSB) 220 | ; 221 | } 222 | 223 | void __noinline NFUNC(negDMAFillReset)(void) 224 | { 225 | zerodma->write_addr = (uint32_t)negGetPtrWrite(); 226 | zerodma->al1_ctrl = 0 227 | | (DMA_CH0_CTRL_TRIG_EN_BITS) 228 | | (DMA_CH0_CTRL_TRIG_DATA_SIZE_VALUE_SIZE_BYTE << DMA_CH0_CTRL_TRIG_DATA_SIZE_LSB) 229 | | ((dma_to_pio_fill) << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB) 230 | | (DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS) 231 | | (DMA_CH0_CTRL_TRIG_INCR_READ_BITS) // No idea why it's broken without read increment 232 | | (DMA_CH0_CTRL_TRIG_IRQ_QUIET_BITS) // Do not crash after each fill 233 | | ((DREQ_PIO0_TX0 + sm_proto) << DMA_CH0_CTRL_TRIG_TREQ_SEL_LSB) 234 | ; 235 | } 236 | 237 | void __noinline NFUNC(negDMAFillFIFO)(uint32_t amount) 238 | { 239 | zerodma->read_addr = (uint32_t)&dmazero[0]; 240 | zerodma->al1_transfer_count_trig = amount; 241 | } 242 | 243 | void negResetFull(void) 244 | { 245 | negPIOReset(pio); 246 | 247 | negDMAReset(dma_from_pio); 248 | negDMAReset(dma_to_pio); 249 | negDMAReset(dma_to_pio_fill); 250 | 251 | negSMResetFull(pio, sm_proto); 252 | negSMResetFull(pio, sm_clk); 253 | 254 | picartResetFull(); 255 | 256 | negDMAFillReset(); 257 | } 258 | 259 | void negReset(void) 260 | { 261 | negPIOReset(pio); 262 | 263 | negDMAReset(dma_from_pio); 264 | negDMAReset(dma_to_pio); 265 | negDMAReset(dma_to_pio_fill); 266 | 267 | negSMReset(pio, sm_proto); 268 | negSMReset(pio, sm_clk); 269 | 270 | negDMAFillReset(); 271 | } 272 | 273 | void negEnable(void) 274 | { 275 | *hw_set_alias(&pio->ctrl) = (1 << sm_proto) | (1 << sm_clk); 276 | picartPreinit(); 277 | 278 | negDMAPostinit(); 279 | } 280 | -------------------------------------------------------------------------------- /src/neg.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #define DMALOG_SIZE (32768) 4 | #define DMALOG_BITS ((DMALOG_SIZE - 1) & ~3) 5 | 6 | extern uint32_t dmadstbuf[DMALOG_SIZE >> 2]; 7 | extern io_ro_32* dmadstptr; 8 | extern dma_channel_hw_t* zerodma; 9 | 10 | void negInit(void); 11 | void negResetFull(void); 12 | void negReset(void); 13 | void negEnable(void); 14 | io_ro_32* negGetPtrRead(void); 15 | io_wo_32* negGetPtrWrite(void); 16 | bool negCanRead(void); 17 | bool negCanDrain(void); 18 | bool negCanWrite(void); 19 | uint32_t negBlockingRead(void); 20 | void negBlockingWrite(uint32_t data); 21 | void negBlockingSkip(uint32_t cnt); 22 | void negBlockingDummy(uint32_t cnt, uint32_t data); 23 | void negDMAFillFIFO(uint32_t amount); 24 | -------------------------------------------------------------------------------- /src/nicart.pio: -------------------------------------------------------------------------------- 1 | /* 2 | nicart.pio - Nitro Emulated Gamecart Octo-SPI protocoll machine 3 | Copyright (C) 2022 Sono (https://github.com/SonoSooS) 4 | All Rights Reserved 5 | */ 6 | 7 | 8 | ; PIOASM stddef 9 | .define POL_LOW 0 10 | .define POL_HIGH 1 11 | .define POL_IRQ_WAIT 0 12 | .define POL_IRQ_ACK 1 13 | 14 | 15 | ; Startup program for preprogramming 16 | .program NINO 17 | .origin 0 18 | nino_spein: 19 | JMP nino_spein 20 | 21 | 22 | 23 | ; Octo-SPI protocoll mux 24 | ; Need: 25 | ; - JMP_PIN = 11 (/CS) 26 | ; - MOV X, #0 -- default bus value if FIFO starve 27 | ; - MOV OSR, NULL 28 | ; - OUT PINDIRS #12 29 | ; - OUT PINS #12 30 | .program NICHAN 31 | 32 | PUBLIC NICHAN_ENTRY: 33 | again: 34 | SET Y, (8 - 1) ; Should be adjusted for CTRCARD soon, although CTRCARD has different latching requirements 35 | 36 | clockloop: 37 | WAIT POL_IRQ_ACK IRQ 4 ; Wait for /CS and/or /CLK 38 | 39 | IN PINS, 8 40 | PUSH IFFULL NOBLOCK 41 | 42 | JMP PIN, cleanup ; Impossible to trigger, but happens sometimes 43 | JMP Y--, clockloop ; Clock in all eight comand bytes 44 | 45 | 46 | MOV OSR, ~NULL ; Set DAT pins as output 47 | OUT PINDIRS, 8 ; https://forums.raspberrypi.com/viewtopic.php?p=1816575#p1816575 48 | 49 | _lowpin: 50 | PUSH NOBLOCK ; Used to be debug, but now used for CMD begin detection 51 | 52 | newbit: 53 | .wrap_target 54 | WAIT POL_IRQ_ACK IRQ 4 ; Wait for ^CS or /CLK 55 | JMP PIN, cleanup ; Clean up if ^CS 56 | 57 | PULL NOBLOCK/*IFEMPTY*/; Even though there are no known commands which are !!(length & 3), this is still here due to weird hardware bugs 58 | OUT PINS, 8 ; Keep writing bits (or X on FIFO empty) until ^CS 59 | ;JMP newbit 60 | .wrap 61 | 62 | cleanup: 63 | MOV OSR, NULL 64 | OUT PINDIRS, 12 ; Reset pins to input 65 | 66 | PUSH NOBLOCK ; Used to be debug, but now necessarily used as necessary command end flag 67 | 68 | JMP again 69 | 70 | 71 | 72 | ; Octo-SPI latch and clock control 73 | ; Needs: 74 | ; - JMP_PIN = 11 (/CS) 75 | ; - MOV X, #0b01 (/CS low, /CLK high) 76 | ; - MOV OSR, NULL 77 | ; - OUT PINDIRS #12 78 | ; - OUT PINS #12 79 | .program NINACLOCK 80 | 81 | PUBLIC NINACLOCK_ENTRY: 82 | pinwatcher: 83 | WAIT POL_LOW GPIO 11 84 | WAIT POL_LOW GPIO 10 85 | 86 | pinwatcher_nocs: 87 | ;WAIT POL_HIGH GPIO 10 88 | 89 | pinagain: 90 | .wrap_target 91 | MOV ISR, NULL 92 | IN PINS, 2 93 | MOV Y, ISR 94 | JMP X!=Y, pinokay 95 | ;JMP pinagain 96 | .wrap 97 | 98 | pinokay: 99 | IRQ WAIT 4 100 | WAIT POL_HIGH GPIO 10 101 | 102 | JMP PIN, pinwatcher 103 | JMP pinwatcher_nocs 104 | 105 | -------------------------------------------------------------------------------- /src/picart_setup.c: -------------------------------------------------------------------------------- 1 | /* 2 | picart_setup.c - PIO and SM configuration for proper working 3 | Copyright (C) 2022 Sono (https://github.com/SonoSooS) 4 | All Rights Reserved 5 | */ 6 | 7 | #include 8 | #include "hardware/pio.h" 9 | #include "nicart.pio.h" 10 | 11 | 12 | #define SHIFT_IN_FROM_RIGHT (0) 13 | #define SHIFT_IN_FROM_LEFT (1) 14 | #define SHIFT_OUT_FROM_LEFT (0) 15 | #define SHIFT_OUT_FROM_RIGHT (1) 16 | 17 | #define SHIFT_IN_FROM_RIGHT_BITS (SHIFT_IN_FROM_RIGHT << PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_LSB) 18 | #define SHIFT_IN_FROM_LEFT_BITS (SHIFT_IN_FROM_LEFT << PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_LSB) 19 | #define SHIFT_OUT_FROM_LEFT_BITS (SHIFT_OUT_FROM_LEFT << PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_LSB) 20 | #define SHIFT_OUT_FROM_RIGHT_BITS (SHIFT_OUT_FROM_RIGHT << PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_LSB) 21 | 22 | static uint piof_mux; 23 | static uint piof_clk; 24 | static PIO _pio; 25 | static uint _sm1; 26 | static uint _sm2; 27 | 28 | 29 | static void picartInstall1(void) 30 | { 31 | pio_sm_config smcfg = NICHAN_program_get_default_config(piof_mux); 32 | sm_config_set_in_pins(&smcfg, 2); 33 | sm_config_set_out_pins(&smcfg, 2, 12); 34 | sm_config_set_set_pins(&smcfg, 10, 4); 35 | sm_config_set_jmp_pin(&smcfg, 11); 36 | 37 | smcfg.shiftctrl = smcfg.shiftctrl 38 | & ~(PIO_SM0_SHIFTCTRL_AUTOPULL_BITS | PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS | PIO_SM0_SHIFTCTRL_PULL_THRESH_BITS | PIO_SM0_SHIFTCTRL_PUSH_THRESH_BITS) 39 | | ((8 & 31) << PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB) 40 | | ((false & 1) << PIO_SM0_SHIFTCTRL_AUTOPULL_LSB) 41 | | ((32 & 31) << PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB) 42 | | ((true & 1) << PIO_SM0_SHIFTCTRL_AUTOPUSH_LSB) 43 | ; 44 | 45 | smcfg.shiftctrl = smcfg.shiftctrl 46 | & ~(PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_BITS | PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_BITS) 47 | | (SHIFT_IN_FROM_RIGHT_BITS) 48 | | (SHIFT_OUT_FROM_RIGHT_BITS) 49 | ; 50 | 51 | pio_sm_set_config(_pio, _sm1, &smcfg); 52 | } 53 | 54 | static void picartInstall2(void) 55 | { 56 | pio_sm_config smcfg = NINACLOCK_program_get_default_config(piof_clk); 57 | sm_config_set_in_pins(&smcfg, 10); 58 | sm_config_set_out_pins(&smcfg, 10, 2); 59 | sm_config_set_set_pins(&smcfg, 10, 2); 60 | sm_config_set_jmp_pin(&smcfg, 11); 61 | 62 | smcfg.shiftctrl = smcfg.shiftctrl 63 | & ~(PIO_SM0_SHIFTCTRL_AUTOPULL_BITS | PIO_SM0_SHIFTCTRL_AUTOPUSH_BITS | PIO_SM0_SHIFTCTRL_PULL_THRESH_BITS | PIO_SM0_SHIFTCTRL_PUSH_THRESH_BITS) 64 | | ((PIO_SM0_SHIFTCTRL_PULL_THRESH_RESET) << PIO_SM0_SHIFTCTRL_PULL_THRESH_LSB) 65 | | ((PIO_SM0_SHIFTCTRL_PUSH_THRESH_RESET) << PIO_SM0_SHIFTCTRL_PUSH_THRESH_LSB) 66 | ; 67 | 68 | smcfg.shiftctrl = smcfg.shiftctrl 69 | & ~(PIO_SM0_SHIFTCTRL_IN_SHIFTDIR_BITS | PIO_SM0_SHIFTCTRL_OUT_SHIFTDIR_BITS) 70 | | (SHIFT_IN_FROM_RIGHT_BITS) 71 | | (SHIFT_OUT_FROM_RIGHT_BITS) 72 | ; 73 | 74 | pio_sm_set_config(_pio, _sm2, &smcfg); 75 | } 76 | 77 | static void picartArm1(void) 78 | { 79 | pio_sm_hw_t* sm = &_pio->sm[_sm1]; 80 | io_rw_32* exec = &sm->instr; 81 | 82 | *exec = pio_encode_set(pio_x, 0); 83 | *exec = pio_encode_mov(pio_isr, pio_null); 84 | *exec = pio_encode_mov(pio_osr, pio_null); 85 | *exec = pio_encode_out(pio_pindirs, 12); 86 | *exec = pio_encode_out(pio_pins, 12); 87 | *exec = pio_encode_mov(pio_isr, pio_null); 88 | *exec = pio_encode_mov(pio_osr, pio_null); 89 | 90 | *exec = pio_encode_jmp(piof_mux); 91 | } 92 | 93 | static void picartArm2(void) 94 | { 95 | pio_sm_hw_t* sm = &_pio->sm[_sm2]; 96 | io_rw_32* exec = &sm->instr; 97 | 98 | *exec = pio_encode_set(pio_x, 0b01); 99 | *exec = pio_encode_mov(pio_isr, pio_null); 100 | *exec = pio_encode_mov(pio_osr, pio_null); 101 | *exec = pio_encode_out(pio_pindirs, 12); 102 | *exec = pio_encode_out(pio_pins, 12); 103 | *exec = pio_encode_mov(pio_isr, pio_null); 104 | *exec = pio_encode_mov(pio_osr, pio_null); 105 | 106 | *exec = pio_encode_jmp(piof_clk); 107 | } 108 | 109 | void picartResetFull(void) 110 | { 111 | picartInstall1(); 112 | picartInstall2(); 113 | } 114 | 115 | void picartSetup(PIO pio, int sm1, int sm2) 116 | { 117 | _pio = pio; 118 | _sm1 = sm1; 119 | _sm2 = sm2; 120 | 121 | pio_add_program(pio, &NINO_program); // Should be 0 122 | 123 | piof_mux = pio_add_program(pio, &NICHAN_program); 124 | piof_clk = pio_add_program(pio, &NINACLOCK_program); 125 | } 126 | 127 | void picartPreinit(void) 128 | { 129 | picartArm2(); 130 | picartArm1(); 131 | } 132 | -------------------------------------------------------------------------------- /src/picart_setup.h: -------------------------------------------------------------------------------- 1 | 2 | void picartSetup(PIO pio, int sm1, int sm2); 3 | void picartResetFull(void); 4 | void picartPreinit(void); 5 | -------------------------------------------------------------------------------- /src/png.c: -------------------------------------------------------------------------------- 1 | /* 2 | png.c - Nitro Gamecart encryption pseudonumber-generator 3 | Copyright (C) 2022 Sono (https://github.com/SonoSooS) 4 | All Rights Reserved 5 | */ 6 | 7 | #include 8 | #include "pico/platform.h" 9 | #include "pico/bit_ops.h" 10 | #include "pico/platform.h" 11 | 12 | #include "memeloc.h" 13 | #include "png.h" 14 | 15 | #define PNGLOC __scratch_y("png") 16 | //#define PNGLOC __not_in_flash("png") 17 | #define PNGNLOC MEMELOC_BANK2_N("png_shared") 18 | //#define PNGNLOC __not_in_flash("png_main") 19 | 20 | #define PNGFUNC(f) MEMELOC_BANK2_F(f) 21 | //#define PNGFUNC(f) __not_in_flash_func(f) 22 | 23 | typedef struct png_lohi 24 | { 25 | uint32_t x_lo; 26 | uint32_t x_hi; 27 | } png_lohi_t; 28 | 29 | 30 | volatile uint32_t PNGNLOC png_prog; 31 | uint32_t PNGNLOC png_buf[PNGBUF_SIZE >> 2]; 32 | 33 | static png_lohi_t PNGLOC key_x; 34 | static png_lohi_t PNGLOC key_y; 35 | 36 | 37 | static inline uint32_t PNGFUNC(F)(uint32_t x, uint32_t shift) 38 | { 39 | return ((x >> 5) ^ (x >> shift) ^ (x >> 18)) & 0xFF; 40 | } 41 | 42 | static inline uint32_t PNGFUNC(pngRunDo)(png_lohi_t* __restrict x, uint32_t shift) 43 | { 44 | uint32_t new_hi = (x->x_lo >> 23) & 0xFF; 45 | uint32_t new_dat = F(x->x_lo, shift) ^ x->x_hi; 46 | x->x_lo = (x->x_lo << 8) | new_dat; 47 | x->x_hi = new_hi; 48 | 49 | return new_dat; 50 | } 51 | 52 | static void PNGFUNC(pngRunInit)(png_lohi_t* __restrict x, uint32_t x_lo, uint32_t x_hi) 53 | { 54 | x_lo = __rev(x_lo); 55 | x_hi = __rev(x_hi); 56 | 57 | x->x_lo = (x_hi >> (32 - 7)) | (x_lo << 7); 58 | x->x_hi = (x_lo >> 24); 59 | } 60 | 61 | uint32_t PNGFUNC(pngDo)(void) 62 | { 63 | uint32_t nx = pngRunDo(&key_x, 17); 64 | uint32_t ny = pngRunDo(&key_y, 23); 65 | 66 | return nx ^ ny; 67 | } 68 | 69 | void PNGFUNC(pngDoBuf)(uint32_t* __restrict buf, uint32_t size, volatile uint32_t* __restrict const progbuf) 70 | { 71 | uint32_t prog = 0; 72 | 73 | while(prog < size) 74 | { 75 | uint32_t dat; 76 | 77 | dat = pngDo(); 78 | dat |= pngDo() << 8; 79 | dat |= pngDo() << 16; 80 | dat |= pngDo() << 24; 81 | 82 | *buf = dat; 83 | prog += 4; 84 | 85 | __compiler_memory_barrier(); 86 | 87 | *progbuf = prog; 88 | 89 | ++buf; 90 | } 91 | } 92 | 93 | void PNGFUNC(pngPreinit)(void) 94 | { 95 | // 0x5C879B9B05 96 | pngRunInit(&key_y, 0x879B9B05, 0x5C); 97 | } 98 | 99 | void PNGFUNC(pngInit)(uint32_t seed, uint32_t ek) 100 | { 101 | pngRunInit(&key_x, (seed << 15) | (0x60 << 8) | ek, seed >> (24 - 7)); 102 | } 103 | -------------------------------------------------------------------------------- /src/png.h: -------------------------------------------------------------------------------- 1 | 2 | //#define PNGBUF_SIZE (0x910 + 0x910 + 4 + ((0x910 + 0x1000 + 0x18) * 4)) 3 | #define PNGBUF_SIZE (0x910 + 0x1000 + 0x18 + 0x914 + 4) 4 | 5 | 6 | extern volatile uint32_t png_prog; 7 | extern uint32_t png_buf[PNGBUF_SIZE >> 2]; 8 | 9 | 10 | void pngPreinit(void); 11 | void pngInit(uint32_t seed, uint32_t ek); 12 | 13 | uint32_t pngDo(void); 14 | void pngDoBuf(uint32_t* __restrict buf, uint32_t size, volatile uint32_t* __restrict const progbuf); 15 | --------------------------------------------------------------------------------