├── .clang-format ├── .gitignore ├── .gitmodules ├── README.md ├── docs └── .keep ├── platforms ├── esp32 │ └── .keep ├── pc │ ├── CMakeLists.txt │ ├── src │ │ ├── CMakeLists.txt │ │ ├── clock.c │ │ ├── clock.h │ │ ├── common.h │ │ ├── gfx.c │ │ ├── gfx.h │ │ ├── prof.c │ │ ├── prof.h │ │ ├── shaders.glsl │ │ ├── shaders.glsl.h │ │ ├── shell.html │ │ ├── sokol.c │ │ ├── ui.cc │ │ └── ui.h │ └── systems │ │ ├── CMakeLists.txt │ │ ├── apple2 │ │ ├── CMakeLists.txt │ │ └── src │ │ │ └── apple2.c │ │ ├── apple2e │ │ ├── CMakeLists.txt │ │ └── src │ │ │ └── apple2e.c │ │ └── oric │ │ ├── CMakeLists.txt │ │ └── src │ │ └── oric.c ├── rp2040 │ ├── CMakeLists.txt │ ├── lib │ │ └── fatfs │ │ │ ├── LICENSE.txt │ │ │ ├── documents │ │ │ ├── 00index_e.html │ │ │ ├── css_e.css │ │ │ ├── doc │ │ │ │ ├── appnote.html │ │ │ │ ├── chdir.html │ │ │ │ ├── chdrive.html │ │ │ │ ├── chmod.html │ │ │ │ ├── close.html │ │ │ │ ├── closedir.html │ │ │ │ ├── config.html │ │ │ │ ├── dinit.html │ │ │ │ ├── dioctl.html │ │ │ │ ├── dread.html │ │ │ │ ├── dstat.html │ │ │ │ ├── dwrite.html │ │ │ │ ├── eof.html │ │ │ │ ├── error.html │ │ │ │ ├── expand.html │ │ │ │ ├── fattime.html │ │ │ │ ├── fdisk.html │ │ │ │ ├── filename.html │ │ │ │ ├── findfirst.html │ │ │ │ ├── findnext.html │ │ │ │ ├── forward.html │ │ │ │ ├── getcwd.html │ │ │ │ ├── getfree.html │ │ │ │ ├── getlabel.html │ │ │ │ ├── gets.html │ │ │ │ ├── lseek.html │ │ │ │ ├── mkdir.html │ │ │ │ ├── mkfs.html │ │ │ │ ├── mount.html │ │ │ │ ├── open.html │ │ │ │ ├── opendir.html │ │ │ │ ├── printf.html │ │ │ │ ├── putc.html │ │ │ │ ├── puts.html │ │ │ │ ├── rc.html │ │ │ │ ├── read.html │ │ │ │ ├── readdir.html │ │ │ │ ├── rename.html │ │ │ │ ├── sdir.html │ │ │ │ ├── setcp.html │ │ │ │ ├── setlabel.html │ │ │ │ ├── sfatfs.html │ │ │ │ ├── sfile.html │ │ │ │ ├── sfileinfo.html │ │ │ │ ├── size.html │ │ │ │ ├── stat.html │ │ │ │ ├── sync.html │ │ │ │ ├── tell.html │ │ │ │ ├── truncate.html │ │ │ │ ├── unlink.html │ │ │ │ ├── utime.html │ │ │ │ └── write.html │ │ │ ├── res │ │ │ │ ├── app1.c │ │ │ │ ├── app2.c │ │ │ │ ├── app3.c │ │ │ │ ├── app4.c │ │ │ │ ├── app5.c │ │ │ │ ├── app6.c │ │ │ │ ├── f1.png │ │ │ │ ├── f2.png │ │ │ │ ├── f3.png │ │ │ │ ├── f4.png │ │ │ │ ├── f5.png │ │ │ │ ├── f6.png │ │ │ │ ├── f7.png │ │ │ │ ├── funcs.png │ │ │ │ ├── layers.png │ │ │ │ ├── layers1.png │ │ │ │ ├── layers2.png │ │ │ │ ├── layers3.png │ │ │ │ ├── mkfatimg.zip │ │ │ │ ├── mkfs.xlsx │ │ │ │ ├── modules.png │ │ │ │ ├── rwtest1.png │ │ │ │ ├── rwtest2.png │ │ │ │ ├── rwtest3.png │ │ │ │ └── uniconv.zip │ │ │ └── updates.html │ │ │ └── source │ │ │ ├── 00history.txt │ │ │ ├── 00readme.txt │ │ │ ├── CMakeLists.txt │ │ │ ├── diskio.c │ │ │ ├── diskio.h │ │ │ ├── ff.c │ │ │ ├── ff.h │ │ │ ├── ffconf.h │ │ │ ├── ffsystem.c │ │ │ └── ffunicode.c │ ├── pico_sdk_import.cmake │ ├── src │ │ ├── audio.c │ │ ├── audio.h │ │ ├── chips │ │ │ └── wdc65C02cpu.h │ │ ├── hid_app.c │ │ ├── msc_app.c │ │ └── tusb_config.h │ └── systems │ │ ├── CMakeLists.txt │ │ ├── apple2 │ │ ├── CMakeLists.txt │ │ └── src │ │ │ ├── apple2.c │ │ │ └── utils.S │ │ ├── apple2e │ │ ├── CMakeLists.txt │ │ └── src │ │ │ ├── apple2e.c │ │ │ └── utils.S │ │ └── oric │ │ ├── CMakeLists.txt │ │ └── src │ │ ├── oric.c │ │ └── utils.S └── rp2350 │ └── .keep ├── src ├── chips │ ├── ay38910psg.h │ ├── beeper.h │ ├── chips_common.h │ ├── clk.h │ ├── kbd.h │ ├── mem.h │ ├── mos6502cpu.h │ └── mos6522via.h ├── devices │ ├── apple2_fdc_rom.h │ ├── apple2_lc.h │ ├── disk2_fdc.h │ ├── disk2_fdd.h │ ├── oric_fdc_rom.h │ ├── oric_td.h │ ├── prodos_hdc.h │ ├── prodos_hdc_rom.S │ ├── prodos_hdc_rom.h │ ├── prodos_hdd.h │ └── prodos_hdd_msc.h ├── images │ ├── .keep │ ├── apple2_images.h.example │ └── oric_images.h.example ├── roms │ ├── apple2_roms.h.example │ ├── apple2e_roms.h.example │ ├── apple2ee_roms.h.example │ ├── oric_roms.h.example │ └── pravetz8d_roms.h.example └── systems │ ├── apple2.h │ ├── apple2e.h │ └── oric.h └── tools ├── bin2hdr └── src │ └── main.c ├── dsk2nib └── src │ └── main.c └── tap2wave └── src └── main.c /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | AlignAfterOpenBracket: BlockIndent 3 | AlignConsecutiveMacros: 4 | Enabled: true 5 | ColumnLimit: 120 6 | IndentWidth: 4 7 | SortIncludes: false 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | src/images/*.h 2 | src/roms/*.h 3 | **/.DS_Store 4 | **/.vscode 5 | **/build 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "platforms/pc/lib/imgui"] 2 | path = platforms/pc/lib/imgui 3 | url = https://github.com/veselin-sladkov/imgui.git 4 | branch = docking 5 | [submodule "platforms/pc/lib/sokol"] 6 | path = platforms/pc/lib/sokol 7 | url = https://github.com/vsladkov/sokol.git 8 | [submodule "platforms/rp2040/lib/pico-sdk"] 9 | path = platforms/rp2040/lib/pico-sdk 10 | url = https://github.com/vsladkov/pico-sdk.git 11 | [submodule "platforms/rp2040/lib/PicoDVI"] 12 | path = platforms/rp2040/lib/PicoDVI 13 | url = https://github.com/vsladkov/PicoDVI.git 14 | [submodule "platforms/rp2040/lib/tinyusb"] 15 | path = platforms/rp2040/lib/tinyusb 16 | url = https://github.com/vsladkov/tinyusb.git 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Reload - Portable Cycle-Stepped Emulator for Retro Computers 2 | 3 | Emulated systems: 4 | 5 | ### Apple //e 6 | - 128 KB RAM installed 7 | - Extended 80 column card in the AUX slot 8 | - Disk II controller and 1 drive in slot 6 9 | - ProDOS hard disk controller in slot 7 10 | 11 | ### Apple ][+ 12 | - 64 KB RAM installed 13 | - 16K Language Card in slot 0, 14 | - Disk II controller and 1 drive in slot 6 15 | - ProDOS hard disk controller in slot 7 16 | 17 | ### Oric Atmos 18 | - 64 KB RAM installed 19 | - 16 KB Overlay RAM installed 20 | - Disk II controller installed and 1 drive 21 | 22 | ## Requirements (RP2040) 23 | ### Tools 24 | - cmake 25 | - arm-none-eabi-gcc 26 | 27 | ### External Libraries (included as git submodules) 28 | - pico-sdk 29 | - PicoDVI 30 | - tinyusb 31 | 32 | ## Quickstart (RP2040) 33 | 34 | ```bash 35 | # Checkout pico-sdk & PicoDVI & tinyusb as git submodules 36 | cd platforms/rp2040/lib 37 | git submodule update --init -- pico-sdk PicoDVI tinyusb 38 | 39 | cd .. 40 | 41 | # Build 42 | mkdir build && cd build 43 | cmake .. 44 | make 45 | 46 | # Done 47 | find . -type f -name "*.uf2" -ls 48 | ``` 49 | 50 | ## Quickstart (Mac OS, Linux and Windows) 51 | 52 | ```bash 53 | # Checkout sokol as git submodule 54 | cd platforms/pc/lib 55 | git submodule update --init -- sokol 56 | 57 | cd .. 58 | 59 | # Build 60 | mkdir build && cd build 61 | cmake .. 62 | make 63 | 64 | # Done 65 | ``` 66 | 67 | ## Building firmware 68 | Original firmware is not distributed with emulator sources. Please, make sure you have the proper license to use and build the headers from your own binaries. 69 | 70 | Example header files for each system are included, together with ROM file names and MD5 checksums. 71 | 72 | You can use bin2hdr tool to generate firmware header files. Please, make sure MD5 checksums are identical. 73 | 74 | 75 | ## Building games 76 | ### UPDATE (RP2040): Apple //e and Apple ][+ emulators now support USB flash drives with FAT and ExFAT file systems. 77 | 78 | Apple //e and Apple ][+ emulators are working with embedded ProDOS images and NIB images as C headers. 79 | 80 | Oric emulator is working with embedded NIB and WAVE images as C headers. 81 | 82 | Building headers from DSK file (Apple ][, Oric): 83 | 84 | ```bash 85 | # Moon Patrol.DSK 86 | dsk2nib -i Moon Patrol.DSK -o Moon Patrol.NIB 87 | bin2hdr -i Moon Patrol.NIB -o moon_patrol.h -a moon_patrol_nib_image 88 | 89 | # Karateka.DSK 90 | dsk2nib -i Karateka.DSK -o Karateka.NIB 91 | bin2hdr -i Karateka.NIB -o karateka.h -a karateka_nib_image 92 | 93 | #ProDOS 94 | bin2hdr -i neo6502.po -o neo6502.h -a neo6502_po_image 95 | ``` 96 | 97 | Example apple2_images.h file for Apple ][ emulator: 98 | 99 | ``` 100 | #include "moon_patrol.h" 101 | #include "karateka.h" 102 | #include "neo6502.h" 103 | 104 | uint8_t* apple2_nib_images[] = { 105 | moon_patrol_nib_image, 106 | karateka_nib_image, 107 | }; 108 | 109 | uint8_t* apple2_po_images[] = { 110 | neo6502_po_image, 111 | }; 112 | 113 | uint32_t apple2_po_image_sizes[] = { 114 | sizeof(neo6502_po_image), 115 | }; 116 | 117 | char* apple2_msc_images[] = { 118 | "Total Replay v5.2.hdv", 119 | }; 120 | 121 | ``` 122 | 123 | Building headers from TAP file (Oric): 124 | 125 | ```bash 126 | # Pulsoids-UK.TAP 127 | tap2wave -i Pulsoids-UK.TAP -o Pulsoids-UK.WAVE 128 | bin2hdr -i Pulsoids-UK.WAVE -o pulsoids.h -a pulsoids_wave_image 129 | ``` 130 | 131 | Example oric_images.h file for Oric emulator: 132 | 133 | ``` 134 | #include "rdos_231.h" 135 | #include "oric_games.h" 136 | #include "pulsoids.h" 137 | 138 | uint8_t* oric_nib_images[] = { 139 | rdos_231_nib_image, 140 | oric_games_nib_image, 141 | }; 142 | 143 | uint8_t* oric_wave_images[] = { 144 | pulsoids_wave_image, 145 | }; 146 | ``` 147 | 148 | First NIB file is loaded in floppy disk drive on startup. Images can be loaded dynamically at runtime in floppy disk drive and / or tape drive using F1-F9. 149 | 150 | Up to 9 disk images can be embedded in single UF2 binary (for 2MB flash). 151 | 152 | Please, make sure you have the proper license to use the games. 153 | 154 | ## Hardware 155 | ### Neo6502 156 | For Oric emulator to work correctly you must connect pin 10 of UEXT connector (GPIO 25) to pin 24 of 6502 bus connector (IRQ) using external wire. 157 | 158 | To use F12 as RESET button (both Apple ][ and Oric) you have to connect pin 9 of UEXT connector (GPIO 26) to pin 40 of 6502 bus connector (RESET). 159 | 160 | To use F11 as NMI button (Oric) you have to connect pin 8 of UEXT connector (GPIO 27) to pin 26 of 6502 bus connector (NMI). 161 | -------------------------------------------------------------------------------- /docs/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/docs/.keep -------------------------------------------------------------------------------- /platforms/esp32/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/esp32/.keep -------------------------------------------------------------------------------- /platforms/pc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.20) 2 | project(pc) 3 | set(CMAKE_C_STANDARD 11) 4 | 5 | # Linux -pthread shenanigans 6 | if (CMAKE_SYSTEM_NAME STREQUAL Linux) 7 | set(THREADS_PREFER_PTHREAD_FLAG ON) 8 | find_package(Threads REQUIRED) 9 | endif() 10 | 11 | include_directories( 12 | ${CMAKE_CURRENT_SOURCE_DIR}/lib/sokol 13 | ${CMAKE_CURRENT_SOURCE_DIR}/lib/sokol/util 14 | ${CMAKE_CURRENT_SOURCE_DIR}/src 15 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src 16 | ) 17 | 18 | add_subdirectory(src) 19 | add_subdirectory(systems) 20 | -------------------------------------------------------------------------------- /platforms/pc/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #=== LIBRARY: platform 2 | 3 | # add headers to the the file list because they are useful to have in IDEs 4 | set(SOKOL_HEADERS 5 | ../lib/sokol/sokol_gfx.h 6 | ../lib/sokol/sokol_app.h 7 | ../lib/sokol/sokol_audio.h 8 | ../lib/sokol/sokol_glue.h 9 | ) 10 | 11 | add_library(platform INTERFACE) 12 | target_sources(platform INTERFACE clock.c gfx.c prof.c sokol.c ${SOKOL_HEADERS}) 13 | 14 | if(CMAKE_SYSTEM_NAME STREQUAL Darwin) 15 | # compile sokol.c as Objective-C 16 | target_compile_options(platform INTERFACE -x objective-c) 17 | target_link_libraries(platform INTERFACE 18 | "-framework QuartzCore" 19 | "-framework Cocoa" 20 | "-framework MetalKit" 21 | "-framework Metal" 22 | "-framework OpenGL" 23 | "-framework AudioToolbox") 24 | else() 25 | if (CMAKE_SYSTEM_NAME STREQUAL Linux) 26 | target_link_libraries(platform INTERFACE X11 Xi Xcursor GL asound dl m) 27 | target_link_libraries(platform INTERFACE Threads::Threads) 28 | endif() 29 | endif() 30 | -------------------------------------------------------------------------------- /platforms/pc/src/clock.c: -------------------------------------------------------------------------------- 1 | #include "sokol_app.h" 2 | #include "clock.h" 3 | #include 4 | 5 | typedef struct { 6 | bool valid; 7 | uint64_t cur_time; 8 | } clock_state_t; 9 | static clock_state_t state; 10 | 11 | void clock_init(void) { 12 | state = (clock_state_t) { 13 | .valid = true, 14 | .cur_time = 0, 15 | }; 16 | } 17 | 18 | uint32_t clock_frame_time(void) { 19 | assert(state.valid); 20 | uint32_t frame_time_us = (uint32_t) (sapp_frame_duration() * 1000000.0); 21 | // prevent death-spiral on host systems that are too slow to emulate 22 | // in real time, or during long frames (e.g. debugging) 23 | if (frame_time_us > 24000) { 24 | frame_time_us = 24000; 25 | } 26 | state.cur_time += frame_time_us; 27 | return frame_time_us; 28 | } 29 | 30 | uint32_t clock_frame_count_60hz(void) { 31 | assert(state.valid); 32 | return (uint32_t) (state.cur_time / 16667); 33 | } 34 | -------------------------------------------------------------------------------- /platforms/pc/src/clock.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void clock_init(void); 5 | uint32_t clock_frame_time(void); 6 | uint32_t clock_frame_count_60hz(void); 7 | -------------------------------------------------------------------------------- /platforms/pc/src/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "sokol_app.h" 3 | #include "sokol_gfx.h" 4 | #include "sokol_audio.h" 5 | #include "sokol_args.h" 6 | #include "sokol_time.h" 7 | #include "sokol_debugtext.h" 8 | #include "sokol_log.h" 9 | #include "clock.h" 10 | #include "prof.h" 11 | #include "gfx.h" 12 | #include // isupper, islower, toupper, tolower 13 | -------------------------------------------------------------------------------- /platforms/pc/src/gfx.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /* 3 | Common graphics functions for the chips-test example emulators. 4 | 5 | REMINDER: consider using this CRT shader? 6 | 7 | https://github.com/mattiasgustavsson/rebasic/blob/master/source/libs/crtemu.h 8 | */ 9 | #include 10 | #include 11 | #include 12 | #include "sokol_gfx.h" 13 | #include "chips/chips_common.h" 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | typedef struct { 20 | int top, bottom, left, right; 21 | } gfx_border_t; 22 | 23 | typedef struct { 24 | sg_image display_image; 25 | sg_sampler display_sampler; 26 | chips_display_info_t display_info; 27 | } gfx_draw_info_t; 28 | 29 | typedef void(*gfx_draw_extra_t)(const gfx_draw_info_t* draw_info); 30 | 31 | typedef struct { 32 | bool disable_speaker_icon; 33 | gfx_border_t border; 34 | chips_display_info_t display_info; 35 | chips_dim_t pixel_aspect; // optional pixel aspect ratio, default is 1:1 36 | gfx_draw_extra_t draw_extra_cb; 37 | } gfx_desc_t; 38 | 39 | void gfx_init(const gfx_desc_t* desc); 40 | void gfx_draw(chips_display_info_t display_info); 41 | void gfx_shutdown(void); 42 | void gfx_flash_success(void); 43 | void gfx_flash_error(void); 44 | void gfx_disable_speaker_icon(void); 45 | chips_dim_t gfx_pixel_aspect(void); 46 | sg_image gfx_create_icon_texture(const uint8_t* packed_pixels, int width, int height, int stride); 47 | 48 | #ifdef __cplusplus 49 | } /* extern "C" */ 50 | #endif 51 | -------------------------------------------------------------------------------- /platforms/pc/src/prof.c: -------------------------------------------------------------------------------- 1 | #include "sokol_time.h" 2 | #include "prof.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #define PROF_BUCKET_SIZE (128) 8 | 9 | // a simple ring buffer struct 10 | typedef struct { 11 | int head; // next slot to write to 12 | int tail; // oldest valid slot 13 | float values[PROF_BUCKET_SIZE]; 14 | } prof_ring_t; 15 | 16 | typedef struct { 17 | prof_ring_t ring; 18 | } prof_bucket_t; 19 | 20 | typedef struct { 21 | bool valid; 22 | prof_bucket_t buckets[PROF_NUM_BUCKET_TYPES]; 23 | } prof_state_t; 24 | static prof_state_t state; 25 | 26 | static int prof_ring_idx(int i) { 27 | return (i % PROF_BUCKET_SIZE); 28 | } 29 | 30 | static int prof_ring_count(const prof_ring_t* ring) { 31 | if (ring->head >= ring->tail) { 32 | return ring->head - ring->tail; 33 | } 34 | else { 35 | return (ring->head + PROF_BUCKET_SIZE) - ring->tail; 36 | } 37 | } 38 | 39 | static void prof_ring_put(prof_ring_t* ring, float value) { 40 | ring->values[ring->head] = value; 41 | ring->head = prof_ring_idx(ring->head + 1); 42 | if (ring->head == ring->tail) { 43 | ring->tail = prof_ring_idx(ring->tail + 1); 44 | } 45 | } 46 | 47 | static float prof_ring_get(prof_ring_t* ring, int index) { 48 | return ring->values[prof_ring_idx(ring->tail + index)]; 49 | } 50 | 51 | void prof_init(void) { 52 | stm_setup(); 53 | memset(&state, 0, sizeof(state)); 54 | state.valid = true; 55 | } 56 | 57 | void prof_push(prof_bucket_type_t type, float val) { 58 | assert(state.valid); 59 | assert((type >= 0) && (type < PROF_NUM_BUCKET_TYPES)); 60 | prof_ring_put(&state.buckets[type].ring, val); 61 | } 62 | 63 | int prof_count(prof_bucket_type_t type) { 64 | assert(state.valid); 65 | assert((type >= 0) && (type < PROF_NUM_BUCKET_TYPES)); 66 | return prof_ring_count(&state.buckets[type].ring); 67 | } 68 | 69 | float prof_value(prof_bucket_type_t type, int index) { 70 | assert(state.valid); 71 | assert((type >= 0) && (type < PROF_NUM_BUCKET_TYPES)); 72 | return prof_ring_get(&state.buckets[type].ring, index); 73 | } 74 | 75 | prof_stats_t prof_stats(prof_bucket_type_t type) { 76 | assert(state.valid); 77 | assert((type >= 0) && (type < PROF_NUM_BUCKET_TYPES)); 78 | prof_stats_t stats = {0}; 79 | prof_ring_t* ring = &state.buckets[type].ring; 80 | stats.count = prof_ring_count(ring); 81 | if (stats.count > 0) { 82 | stats.min_val = 1000.0f; 83 | for (int i = 0; i < stats.count; i++) { 84 | float val = prof_ring_get(ring, i); 85 | stats.avg_val += val; 86 | if (val < stats.min_val) { 87 | stats.min_val = val; 88 | } 89 | if (val > stats.max_val) { 90 | stats.max_val = val; 91 | } 92 | } 93 | stats.avg_val /= (float)stats.count; 94 | } 95 | return stats; 96 | } 97 | -------------------------------------------------------------------------------- /platforms/pc/src/prof.h: -------------------------------------------------------------------------------- 1 | /* 2 | A simple profiling helper module. 3 | */ 4 | typedef enum { 5 | PROF_FRAME, // frame time 6 | PROF_EMU, // emulator time 7 | PROF_NUM_BUCKET_TYPES, 8 | } prof_bucket_type_t; 9 | 10 | typedef struct { 11 | int count; 12 | float avg_val; 13 | float min_val; 14 | float max_val; 15 | } prof_stats_t; 16 | 17 | // initialize profiling system 18 | void prof_init(void); 19 | // push a value into a profiler bucket 20 | void prof_push(prof_bucket_type_t type, float val); 21 | // get number of values in profiler bucket 22 | int prof_count(prof_bucket_type_t type); 23 | // get a value from profiler bucket 24 | float prof_value(prof_bucket_type_t type, int index); 25 | // get average value in bucket 26 | prof_stats_t prof_stats(prof_bucket_type_t type); 27 | -------------------------------------------------------------------------------- /platforms/pc/src/shaders.glsl: -------------------------------------------------------------------------------- 1 | @vs offscreen_vs 2 | layout(location=0) in vec2 in_pos; 3 | layout(location=1) in vec2 in_uv; 4 | 5 | layout(binding=0) uniform offscreen_vs_params { 6 | vec2 uv_offset; 7 | vec2 uv_scale; 8 | }; 9 | 10 | out vec2 uv; 11 | void main() { 12 | gl_Position = vec4(in_pos*2.0-1.0, 0.5, 1.0); 13 | uv = (in_uv * uv_scale) + uv_offset; 14 | } 15 | @end 16 | 17 | @fs offscreen_fs 18 | layout(binding=0) uniform texture2D fb_tex; 19 | layout(binding=0) uniform sampler smp; 20 | in vec2 uv; 21 | out vec4 frag_color; 22 | void main() { 23 | frag_color = texture(sampler2D(fb_tex, smp), uv); 24 | } 25 | @end 26 | 27 | // offscreen shader with color palette decoding 28 | @fs offscreen_pal_fs 29 | layout(binding=0) uniform texture2D fb_tex; 30 | layout(binding=1) uniform texture2D pal_tex; 31 | layout(binding=0) uniform sampler smp; 32 | in vec2 uv; 33 | out vec4 frag_color; 34 | void main() { 35 | float pix = texture(sampler2D(fb_tex, smp), uv).x; 36 | frag_color = vec4(texture(sampler2D(pal_tex, smp), vec2(pix,0)).xyz, 1.0); 37 | } 38 | @end 39 | 40 | @vs display_vs 41 | layout(location=0) in vec2 in_pos; 42 | layout(location=1) in vec2 in_uv; 43 | out vec2 uv; 44 | void main() { 45 | gl_Position = vec4(in_pos*2.0-1.0, 0.5, 1.0); 46 | uv = in_uv; 47 | } 48 | @end 49 | 50 | @fs display_fs 51 | layout(binding=0) uniform texture2D tex; 52 | layout(binding=0) uniform sampler smp; 53 | in vec2 uv; 54 | out vec4 frag_color; 55 | 56 | void main() { 57 | frag_color = vec4(texture(sampler2D(tex, smp), uv).xyz, 1.0); 58 | } 59 | @end 60 | 61 | @program offscreen offscreen_vs offscreen_fs 62 | @program offscreen_pal offscreen_vs offscreen_pal_fs 63 | @program display display_vs display_fs 64 | -------------------------------------------------------------------------------- /platforms/pc/src/shell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Emscripten-Generated Code 6 | 28 | 29 | 30 | 31 | 49 | {{{ SCRIPT }}} 50 | 51 | 52 | -------------------------------------------------------------------------------- /platforms/pc/src/sokol.c: -------------------------------------------------------------------------------- 1 | #define SOKOL_IMPL 2 | #if defined(_MSC_VER) 3 | #define SOKOL_D3D11 4 | #elif defined(__EMSCRIPTEN__) 5 | #define SOKOL_GLES3 6 | #elif defined(__APPLE__) 7 | // NOTE: on macOS, sokol.c is compiled explicitly as ObjC 8 | //#define SOKOL_GLCORE 9 | #define SOKOL_METAL 10 | #else 11 | #define SOKOL_GLCORE 12 | #endif 13 | #include "sokol_app.h" 14 | #include "sokol_args.h" 15 | #include "sokol_audio.h" 16 | #include "sokol_fetch.h" 17 | #include "sokol_gfx.h" 18 | #include "sokol_gl.h" 19 | #include "sokol_glue.h" 20 | #include "sokol_log.h" 21 | #include "sokol_time.h" 22 | #include "sokol_debugtext.h" 23 | -------------------------------------------------------------------------------- /platforms/pc/src/ui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "sokol_app.h" 3 | #include "sokol_gfx.h" 4 | #include "sokol_imgui.h" 5 | #include "chips/chips_common.h" 6 | #include "ui/ui_settings.h" 7 | #include "ui/ui_util.h" 8 | #include "ui/ui_display.h" 9 | #include "gfx.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | typedef struct { 16 | ui_display_frame_t display; 17 | } ui_draw_info_t; 18 | 19 | typedef void (*ui_draw_t)(const ui_draw_info_t* draw_info); 20 | typedef void (*ui_save_settings_t)(ui_settings_t* settings); 21 | 22 | typedef struct { 23 | ui_draw_t draw_cb; 24 | ui_save_settings_t save_settings_cb; 25 | const char* imgui_ini_key; 26 | } ui_desc_t; 27 | 28 | void ui_init(const ui_desc_t* desc); 29 | const ui_settings_t* ui_settings(void); 30 | void ui_discard(void); 31 | void ui_draw(const gfx_draw_info_t* draw_info); 32 | bool ui_input(const sapp_event* event); 33 | ui_texture_t ui_create_texture(int w, int h); 34 | void ui_update_texture(ui_texture_t h, void* data, int data_byte_size); 35 | void ui_destroy_texture(ui_texture_t h); 36 | ui_texture_t ui_create_screenshot_texture(chips_display_info_t display_info); 37 | ui_texture_t ui_shared_empty_snapshot_texture(void); 38 | 39 | #ifdef __cplusplus 40 | } /* extern "C" */ 41 | #endif 42 | -------------------------------------------------------------------------------- /platforms/pc/systems/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(apple2) 2 | add_subdirectory(apple2e) 3 | add_subdirectory(oric) 4 | -------------------------------------------------------------------------------- /platforms/pc/systems/apple2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #=== EXECUTABLE: apple2 2 | 3 | if(CMAKE_SYSTEM_NAME STREQUAL Windows) 4 | add_executable(apple2 WIN32 ./src/apple2.c) 5 | else() 6 | add_executable(apple2 ./src/apple2.c) 7 | endif() 8 | 9 | target_link_libraries(apple2 platform) 10 | 11 | if (CMAKE_SYSTEM_NAME STREQUAL Emscripten) 12 | set(CMAKE_EXECUTABLE_SUFFIX ".html") 13 | target_link_options(apple2 PUBLIC --shell-file ../sokol/shell.html) 14 | target_link_options(apple2 PUBLIC -sUSE_WEBGL2=1 -sNO_FILESYSTEM=1 -sASSERTIONS=0 -sMALLOC=emmalloc --closure=1) 15 | endif() 16 | 17 | if (MSVC) 18 | target_compile_options(apple2 PUBLIC /W3) 19 | else() 20 | target_compile_options(apple2 PUBLIC -Wall -Wextra -Wsign-compare) 21 | endif() 22 | 23 | # explicitly strip dead code 24 | if (CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_SYSTEM_NAME STREQUAL Emscripten) 25 | target_link_options(apple2 PRIVATE LINKER:-dead_strip) 26 | endif() 27 | -------------------------------------------------------------------------------- /platforms/pc/systems/apple2e/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #=== EXECUTABLE: apple2e 2 | 3 | if(CMAKE_SYSTEM_NAME STREQUAL Windows) 4 | add_executable(apple2e WIN32 ./src/apple2e.c) 5 | else() 6 | add_executable(apple2e ./src/apple2e.c) 7 | endif() 8 | 9 | target_link_libraries(apple2e platform) 10 | 11 | if (CMAKE_SYSTEM_NAME STREQUAL Emscripten) 12 | set(CMAKE_EXECUTABLE_SUFFIX ".html") 13 | target_link_options(apple2e PUBLIC --shell-file ../sokol/shell.html) 14 | target_link_options(apple2e PUBLIC -sUSE_WEBGL2=1 -sNO_FILESYSTEM=1 -sASSERTIONS=0 -sMALLOC=emmalloc --closure=1) 15 | endif() 16 | 17 | if (MSVC) 18 | target_compile_options(apple2e PUBLIC /W3) 19 | else() 20 | target_compile_options(apple2e PUBLIC -Wall -Wextra -Wsign-compare) 21 | endif() 22 | 23 | # explicitly strip dead code 24 | if (CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_SYSTEM_NAME STREQUAL Emscripten) 25 | target_link_options(apple2e PRIVATE LINKER:-dead_strip) 26 | endif() 27 | -------------------------------------------------------------------------------- /platforms/pc/systems/oric/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #=== EXECUTABLE: oric 2 | 3 | if(CMAKE_SYSTEM_NAME STREQUAL Windows) 4 | add_executable(oric WIN32 ./src/oric.c) 5 | else() 6 | add_executable(oric ./src/oric.c) 7 | endif() 8 | 9 | target_link_libraries(oric platform) 10 | 11 | if (CMAKE_SYSTEM_NAME STREQUAL Emscripten) 12 | set(CMAKE_EXECUTABLE_SUFFIX ".html") 13 | target_link_options(oric PUBLIC --shell-file ../sokol/shell.html) 14 | target_link_options(oric PUBLIC -sUSE_WEBGL2=1 -sNO_FILESYSTEM=1 -sASSERTIONS=0 -sMALLOC=emmalloc --closure=1) 15 | endif() 16 | 17 | if (MSVC) 18 | target_compile_options(oric PUBLIC /W3) 19 | else() 20 | target_compile_options(oric PUBLIC -Wall -Wextra -Wsign-compare) 21 | endif() 22 | 23 | # explicitly strip dead code 24 | if (CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT CMAKE_SYSTEM_NAME STREQUAL Emscripten) 25 | target_link_options(oric PRIVATE LINKER:-dead_strip) 26 | endif() 27 | -------------------------------------------------------------------------------- /platforms/rp2040/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.12) 2 | 3 | set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR}/lib/pico-sdk) 4 | set(PICO_TINYUSB_PATH ${CMAKE_CURRENT_LIST_DIR}/lib/tinyusb) 5 | 6 | include(pico_sdk_import.cmake) 7 | 8 | project(rp2040 C CXX ASM) 9 | set(CMAKE_C_STANDARD 11) 10 | set(CMAKE_CXX_STANDARD 17) 11 | set(PICO_BOARD olimex_neo6502) 12 | # set(PICO_BOARD olimex_rp2040pc) 13 | # set(PICO_BOARD pico_zero) 14 | 15 | pico_sdk_init() 16 | 17 | add_compile_options(-Wall) 18 | 19 | include_directories( 20 | ${CMAKE_CURRENT_SOURCE_DIR}/lib/PicoDVI/software/include 21 | ${CMAKE_CURRENT_SOURCE_DIR}/lib/fatfs/source 22 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src 23 | ${CMAKE_CURRENT_SOURCE_DIR}/src 24 | ) 25 | 26 | add_subdirectory(lib/PicoDVI/software/libdvi) 27 | add_subdirectory(lib/fatfs/source) 28 | add_subdirectory(systems) 29 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/LICENSE.txt: -------------------------------------------------------------------------------- 1 | FatFs License 2 | 3 | FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files. 4 | 5 | /*----------------------------------------------------------------------------/ 6 | / FatFs - Generic FAT Filesystem Module Rx.xx / 7 | /-----------------------------------------------------------------------------/ 8 | / 9 | / Copyright (C) 20xx, ChaN, all right reserved. 10 | / 11 | / FatFs module is an open source software. Redistribution and use of FatFs in 12 | / source and binary forms, with or without modification, are permitted provided 13 | / that the following condition is met: 14 | / 15 | / 1. Redistributions of source code must retain the above copyright notice, 16 | / this condition and the following disclaimer. 17 | / 18 | / This software is provided by the copyright holder and contributors "AS IS" 19 | / and any warranties related to this software are DISCLAIMED. 20 | / The copyright owner or contributors be NOT LIABLE for any damages caused 21 | / by use of this software. 22 | /----------------------------------------------------------------------------*/ 23 | 24 | Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license. 25 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/css_e.css: -------------------------------------------------------------------------------- 1 | * {margin: 0; padding: 0; border-width: 0;} 2 | body {margin: 8px; background-color: #e0ffff; font-color: black; font-family: serif; line-height: 133%; max-width: 1024px;} 3 | a:link {color: blue;} 4 | a:visited {color: darkmagenta;} 5 | a:hover {background-color: #a0ffff;} 6 | a:active {color: darkmagenta; overflow: hidden; outline:none; position: relative; top: 1px; left: 1px;} 7 | abbr {border-width: 1px;} 8 | 9 | p {margin: 0 0 0.3em 1em;} 10 | i {margin: 0 0.3em 0 0;} 11 | b {margin: 0 0.1em;} 12 | em {font-style: normal; font-weight: bold; margin: 0 0.1em;} 13 | strong {} 14 | pre {border: 1px dashed gray; margin: 0.5em 1em; padding: 0.5em; line-height: 1.2em; font-size: 85%; font-family: "Consolas", "Courier New", monospace; background-color: white;} 15 | pre span.c {color: green;} 16 | pre span.k {color: blue;} 17 | pre span.e {color: red;} 18 | pre span.b {font-weight: bold;} 19 | pre span.arg {font-style: italic;} 20 | tt {margin: 0 0.2em; font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; } 21 | tt.arg {font-style: italic;} 22 | ol {margin: 0.5em 2.5em;} 23 | ul {margin: 0.5em 2em;} 24 | ul ul {margin: 0 2em 0.5em 1em;} 25 | dl {margin: 0.5em 1em;} 26 | dd {margin: 0 2em;} 27 | dt {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace;} 28 | dl.par dt {margin: 0.5em 0 0 0 ; font-style: italic; } 29 | dl.ret dt {margin: 0.5em 0 0 0 ; font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; font-weight: bold; } 30 | hr {border-width: 1px; margin: 1em;} 31 | div.abst {font-family: sans-serif;} 32 | div.para {clear: both; font-family: serif;} 33 | div.ret a {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; } 34 | .equ {text-indent: 0; margin: 1em 2em 1em;} 35 | .indent {margin-left: 2em;} 36 | .rset {float: right; margin: 0.3em 0 0.5em 0.5em;} 37 | .lset {float: left; margin: 0.3em 0.5em 0.5em 0.5em;} 38 | ul.flat li {list-style-type: none; margin: 0;} 39 | a.imglnk img {border: 1px solid;} 40 | .iequ {white-space: nowrap; font-weight: bold;} 41 | .clr {clear: both;} 42 | .it {font-style: italic;} 43 | .mfd {font-size: 0.7em; padding: 0 1px; border: 1px solid; white-space : nowrap} 44 | .ral {text-align: right; } 45 | .lal {text-align: left; } 46 | .cal {text-align: center; } 47 | 48 | h1 {line-height: 1em; font-size: 2em; font-family: sans-serif; padding: 0.3em 0 0.3em;} 49 | h2 {font-size: 2em; font-family: sans-serif; background-color: #d8d8FF; padding: 0.5em 0.5em; margin: 0 0 0.5em;} 50 | h3 {font-size: 1.5em; font-family: sans-serif; margin: 1.5em 0 0.5em;} 51 | div.doc h3 {border-color: #b0d8d8; border-style: solid; border-width: 0px 0px 4px 12px; padding: 4px; margin-top: 3em;} 52 | h4 {font-size: 1.2em; font-family: sans-serif; margin: 2em 0 0.2em;} 53 | h5 {font-size: 1em; font-family: sans-serif; margin: 1em 0 0em;} 54 | p.hdd {float: right; text-align: right; margin-top: 0.5em;} 55 | hr.hds {clear: both; margin-bottom: 1em;} 56 | kbd {letter-spacing: 0;} 57 | small {font-size: 80%;} 58 | .indent {margin-left: 2em;} 59 | 60 | /* Tables */ 61 | table {margin: 0.5em 1em; border-collapse: collapse; border: 2px solid gray; } 62 | table caption {font-family: sans-serif; font-weight: bold;} 63 | table th {background-color: white; border-style: solid; border-width: 1px 1px 2px; border-color: gray; padding: 0 3px; vertical-align: top; white-space: nowrap;} 64 | table td {background-color: white; border: 1px solid gray; padding: 0 3px; vertical-align: top; line-height: 1.3em;} 65 | table.lst td:first-child {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; white-space: nowrap;} 66 | table.lst2 td {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; white-space: nowrap;} 67 | table.lst3 td {font-family: "Consolas", "Courier New", monospace; white-space: nowrap;} 68 | tr.lst3 td {border-width: 2px 1px 1px; } 69 | table.lst4 td {padding: 0.3em;} 70 | table.lst4 td:nth-child(2) {width: 45%;} 71 | table.lst4 td:nth-child(3) {width: 45%;} 72 | 73 | p.foot {clear: both; text-indent: 0; margin: 1em 0.5em 1em;} 74 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/chdir.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_chdir 10 | 11 | 12 | 13 | 14 |
15 |

f_chdir

16 |

The f_chdir function changes the current directory of the logical drive.

17 |
18 | FRESULT f_chdir (
19 |   const TCHAR* path /* [IN] Path name */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameters

26 |
27 |
path
28 |
Pointer to the null-terminated string that specifies the directory to be set as current directory.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_DISK_ERR, 38 | FR_INT_ERR, 39 | FR_NOT_READY, 40 | FR_NO_PATH, 41 | FR_INVALID_NAME, 42 | FR_INVALID_DRIVE, 43 | FR_NOT_ENABLED, 44 | FR_NO_FILESYSTEM, 45 | FR_TIMEOUT, 46 | FR_NOT_ENOUGH_CORE 47 |

48 |
49 | 50 | 51 |
52 |

Description

53 |

The f_chdir function changes the current directory of the logical drive. Also the current drive will be changed when in Unix style drive prefix, FF_STR_VOLUME_ID == 2. The current directory of each logical drive is initialized to the root directory on mount.

54 |

Note that the current directory is retained in the each file system object and the current drive is retained in a static variable, so that it also affects other tasks that use the file functions.

55 |
56 | 57 | 58 |
59 |

QuickInfo

60 |

Available when FF_FS_RPATH >= 1.

61 |
62 | 63 | 64 |
65 |

Example

66 |
67 |     /* Change current direcoty of the current drive ("dir1" under root directory) */
68 |     f_chdir("/dir1");
69 | 
70 |     /* Change current direcoty of current drive (parent directory of drive 2) */
71 |     f_chdir("2:..");
72 | 
73 |     /* Change current direcoty of the drive "sdcard" (at DOS/Windows style volume ID) */
74 |     f_chdir("sdcard:/dir1");
75 | 
76 |     /* Change current direcoty of the drive "flash" and set it as current drive (at Unix style volume ID) */
77 |     f_chdir("/flash/dir1");
78 | 
79 |
80 | 81 |
82 |

See Also

83 |

f_chdrive, f_getcwd

84 |
85 | 86 |

Return

87 | 88 | 89 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/chdrive.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_chdrive 10 | 11 | 12 | 13 | 14 |
15 |

f_chdrive

16 |

The f_chdrive function changes the current drive.

17 |
18 | FRESULT f_chdrive (
19 |   const TCHAR* path  /* [IN] Logical drive number */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameters

26 |
27 |
path
28 |
Specifies the logical drive number to be set as the current drive.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_INVALID_DRIVE 38 |

39 |
40 | 41 | 42 |
43 |

Description

44 |

The f_chdrive function changes only the current drive. The initial value of the current drive number is 0. In Unix style drive prefix configuration, this function will not be needed because f_chdir function changes also the current drive. Note that the current drive is retained in a static variable, so that it also affects other tasks that using the file functions.

45 |
46 | 47 |
48 |

QuickInfo

49 |

Available when FF_FS_RPATH >= 1.

50 |
51 | 52 | 53 |
54 |

Example

55 |
56 |     f_chdrive("2:");  /* Set drive 2 as current drive */
57 | 
58 |     f_chdrive("");    /* No effect (set current drive as current drive) */
59 | 
60 |
61 | 62 | 63 |
64 |

See Also

65 |

f_chdir, f_getcwd

66 |
67 | 68 |

Return

69 | 70 | 71 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/chmod.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_chmod 10 | 11 | 12 | 13 | 14 |
15 |

f_chmod

16 |

The f_chmod function changes the attribute of a file or sub-directory.

17 |
18 | FRESULT f_chmod (
19 |   const TCHAR* path, /* [IN] Object name */
20 |   BYTE attr,         /* [IN] Attribute flags */
21 |   BYTE mask          /* [IN] Attribute masks */
22 | );
23 | 
24 |
25 | 26 |
27 |

Parameters

28 |
29 |
path
30 |
Pointer to the null-terminated string that specifies an object to be changed
31 |
attr
32 |
Attribute flags to be set in one or more combination of the following flags. The specified flags are set and others are cleard.
33 | 34 | 35 | 36 | 37 | 38 | 39 |
AttributeDescription
AM_RDORead only
AM_ARCArchive
AM_SYSSystem
AM_HIDHidden
40 |
41 |
mask
42 |
Attribute mask that specifies which attribute is changed. The specified attributes are set or cleard and others are left unchanged.
43 |
44 |
45 | 46 | 47 |
48 |

Return Values

49 |

50 | FR_OK, 51 | FR_DISK_ERR, 52 | FR_INT_ERR, 53 | FR_NOT_READY, 54 | FR_NO_FILE, 55 | FR_NO_PATH, 56 | FR_INVALID_NAME, 57 | FR_WRITE_PROTECTED, 58 | FR_INVALID_DRIVE, 59 | FR_NOT_ENABLED, 60 | FR_NO_FILESYSTEM, 61 | FR_TIMEOUT, 62 | FR_NOT_ENOUGH_CORE 63 |

64 |
65 | 66 | 67 |
68 |

Description

69 |

The f_chmod function changes the attribute of a file or sub-directory.

70 |
71 | 72 | 73 |
74 |

QuickInfo

75 |

Available when FF_FS_READONLY == 0 and FF_USE_CHMOD == 1.

76 |
77 | 78 | 79 |
80 |

Example

81 |
82 |     /* Set Read-only, clear Archive and others are left unchanged. */
83 |     f_chmod("file.txt", AM_RDO, AM_RDO | AM_ARC);
84 | 
85 |
86 | 87 |

Return

88 | 89 | 90 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/close.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_close 10 | 11 | 12 | 13 | 14 |
15 |

f_close

16 |

The f_close function closes an open file.

17 |
18 | FRESULT f_close (
19 |   FIL* fp     /* [IN] Pointer to the file object */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
fp
28 |
Pointer to the open file object structure to be closed.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_DISK_ERR, 38 | FR_INT_ERR, 39 | FR_INVALID_OBJECT, 40 | FR_TIMEOUT 41 |

42 |
43 | 44 | 45 |
46 |

Description

47 |

The f_close function closes an open file object. If the file has been changed, the cached information of the file is written back to the volume. After the function succeeded, the file object is no longer valid and it can be discarded.

48 |

Note that if the file object is in read-only mode and FF_FS_LOCK is not enabled, the file object can also be discarded without this procedure. However this is not recommended for future compatibility.

49 |
50 | 51 | 52 |
53 |

QuickInfo

54 |

Always available.

55 |
56 | 57 | 58 |
59 |

See Also

60 |

f_open, f_read, f_write, f_sync, FIL, FATFS

61 |
62 | 63 |

Return

64 | 65 | 66 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/closedir.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_closedir 10 | 11 | 12 | 13 | 14 |
15 |

f_closedir

16 |

The f_closedir function closes an open directory.

17 |
18 | FRESULT f_closedir (
19 |   DIR* dp     /* [IN] Pointer to the directory object */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
dp
28 |
Pointer to the open directory object structure to be closed.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_INT_ERR, 38 | FR_INVALID_OBJECT, 39 | FR_TIMEOUT 40 |

41 |
42 | 43 | 44 |
45 |

Description

46 |

The f_closedir function closes an open directory object. After the function succeeded, the directory object is no longer valid and it can be discarded.

47 |

Note that the directory object can also be discarded without this procedure when option FF_FS_LOCK is not enabled. However this is not recommended for future compatibility.

48 |
49 | 50 | 51 |
52 |

QuickInfo

53 |

Available when FF_FS_MINIMIZE <= 1.

54 |
55 | 56 | 57 |
58 |

See Also

59 |

f_opendir, f_readdir, DIR

60 |
61 | 62 |

Return

63 | 64 | 65 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/dinit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - disk_initialize 10 | 11 | 12 | 13 | 14 |
15 |

disk_initialize

16 |

The disk_initialize function is called to initializes the storage device.

17 |
18 | DSTATUS disk_initialize (
19 |   BYTE pdrv           /* [IN] Physical drive number */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
pdrv
28 |
Physical drive number to identify the target device. Always zero at single drive system.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

This function returns the current drive status flags as the result. For details of the drive status, refer to the disk_status function.

36 |
37 | 38 |
39 |

Description

40 |

This function initializes the storage device and put it ready to generic read/write. When the function succeeded, STA_NOINIT flag in the return value is cleared.

41 |

Remarks: This function needs to be under control of FatFs module. Application program MUST NOT call this function while FatFs is in use, or FAT structure on the volume can be broken. To re-initialize the filesystem, use f_mount function instead.

42 |
43 | 44 |

Return

45 | 46 | 47 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/dread.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - disk_read 10 | 11 | 12 | 13 | 14 |
15 |

disk_read

16 |

The disk_read function is called to read data from the storage device.

17 |
18 | DRESULT disk_read (
19 |   BYTE pdrv,     /* [IN] Physical drive number */
20 |   BYTE* buff,    /* [OUT] Pointer to the read data buffer */
21 |   LBA_t sector,  /* [IN] Start sector number */
22 |   UINT count     /* [IN] Number of sectros to read */
23 | );
24 | 
25 |
26 | 27 |
28 |

Parameters

29 |
30 |
pdrv
31 |
Physical drive number to identify the target device.
32 |
buff
33 |
Pointer to the first item of the byte array to store read data. Size of read data will be the sector size * count bytes.
34 |
sector
35 |
Start sector number in LBA. The data type LBA_t is an alias of DWORD or QWORD depends on the configuration option.
36 |
count
37 |
Number of sectors to read.
38 |
39 |
40 | 41 | 42 |
43 |

Return Value

44 |
45 |
RES_OK (0)
46 |
The function succeeded.
47 |
RES_ERROR
48 |
An unrecoverable hard error occured during the read operation.
49 |
RES_PARERR
50 |
Invalid parameter.
51 |
RES_NOTRDY
52 |
The device has not been initialized.
53 |
54 |
55 | 56 | 57 |
58 |

Description

59 |

Read/write operation to the generic storage devices, such as memory card, hadddisk and optical disk, is done in unit of block of data bytes called sector. FatFs supports the sector size in range of 512 to 4096 bytes. When FatFs is configured for fixed sector size (FF_MIN_SS == FF_MAX_SS, this is the most case), the generic read/write function must work at this sector size only. When FatFs is configured for variable sector size (FF_MIN_SS < FF_MAX_SS), the sector size of medium is inquired with disk_ioctl function after disk_initialize function succeeds.

60 |

There are some considerations about the memory addres passed via buff. It is not that always aligned with the word boundary, because the argument is defined as BYTE*. The unaligned transfer request can occure at direct transfer. If the bus architecture, especially DMA controller, does not allow unaligned memory access, it should be solved in this function. If it is the case, there are some workarounds described below to avoid this issue.

61 |
    62 |
  • Convert word transfer to byte transfer with some trick in this function. - Recommended.
  • 63 |
  • On the f_read() calls, avoid long read request that includes a whole of sector. - Any direct transfer never occures.
  • 64 |
  • On the f_read(fp, data, btw, bw) calls, make sure that (((UINT)data & 3) == (f_tell(fp) & 3)) is true. - Word alignment of buff is guaranteed.
  • 65 |
66 |

Also the memory area may be out of reach in DMA. This is the case if it is located on the tightly coupled memory which is usually used for stack. Use double buffered transfer, or avoid to define file I/O buffer, FATFS and FIL structure as local variables where on the stack.

67 |

Generally, a multiple sector read request must not be split into single sector transactions to the storage device, or read throughput gets worse.

68 |
69 | 70 | 71 |

Return

72 | 73 | 74 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/dstat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - disk_status 10 | 11 | 12 | 13 | 14 |
15 |

disk_status

16 |

The disk_status function is called to inquire the current drive status.

17 |
18 | DSTATUS disk_status (
19 |   BYTE pdrv     /* [IN] Physical drive number */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
pdrv
28 |
Physical drive number to identify the target device. Always zero in single drive system.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

The current drive status is returned in combination of status flags described below. FatFs refers only STA_NOINIT and STA_PROTECT.

36 |
37 |
STA_NOINIT
38 |
Indicates that the device has not been initialized and not ready to work. This flag is set on system reset, media removal or failure of disk_initialize function. It is cleared on disk_initialize function succeeded. Any media change that occurs asynchronously must be captured and reflect it to the status flags, or auto-mount function will not work correctly. If the system does not support media change detection, application program needs to explicitly re-mount the volume with f_mount function after each media change.
39 |
STA_NODISK
40 |
Indicates that no medium in the drive. This is always cleared when the drive is non-removable class. Note that FatFs does not refer this flag.
41 |
STA_PROTECT
42 |
Indicates that the medium is write protected. This is always cleared when the drive has no write protect function. Not valid if STA_NODISK is set.
43 |
44 |
45 | 46 |

Return

47 | 48 | 49 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/dwrite.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - disk_write 10 | 11 | 12 | 13 | 14 |
15 |

disk_write

16 |

The disk_write function is called to write data to the storage device.

17 |
18 | DRESULT disk_write (
19 |   BYTE pdrv,        /* [IN] Physical drive number */
20 |   const BYTE* buff, /* [IN] Pointer to the data to be written */
21 |   LBA_t sector,     /* [IN] Sector number to write from */
22 |   UINT count        /* [IN] Number of sectors to write */
23 | );
24 | 
25 |
26 | 27 |
28 |

Parameters

29 |
30 |
pdrv
31 |
Physical drive number to identify the target device.
32 |
buff
33 |
Pointer to the first item of the byte array to be written. The size of data to be written is sector size * count bytes.
34 |
sector
35 |
Start sector number in LBA. The data type LBA_t is an alias of DWORD or QWORD depends on the configuration option.
36 |
count
37 |
Number of sectors to write.
38 |
39 |
40 | 41 | 42 |
43 |

Return Values

44 |
45 |
RES_OK (0)
46 |
The function succeeded.
47 |
RES_ERROR
48 |
An unrecoverable hard error occured during the write operation.
49 |
RES_WRPRT
50 |
The medium is write protected.
51 |
RES_PARERR
52 |
Invalid parameter.
53 |
RES_NOTRDY
54 |
The device has not been initialized.
55 |
56 |
57 | 58 | 59 |
60 |

Description

61 |

The specified memory address is not that always aligned to word boundary because the argument is defined as BYTE*. For more information, refer to the description of disk_read function.

62 |

Generally, a multiple sector write request (count > 1) must not be split into single sector transactions to the storage device, or the file write throughput will be drastically decreased.

63 |

FatFs expects delayed write function of the disk control layer. The write operation to the media does not need to be completed when return from this function by what write operation is in progress or data is only stored into the write-back cache. But write data on the buff is invalid after return from this function. The write completion request is done by CTRL_SYNC command of disk_ioctl function. Therefore, if a delayed write function is implemented, the write throughput of the filesystem will be improved.

64 |

Remarks: Application program MUST NOT call this function, or FAT structure on the volume can be collapsed.

65 |
66 | 67 | 68 |
69 |

QuickInfo

70 |

This function is not needed when FF_FS_READONLY == 1.

71 |
72 | 73 | 74 |

Return

75 | 76 | 77 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/eof.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_eof 10 | 11 | 12 | 13 | 14 |
15 |

f_eof

16 |

The f_eof function tests for end-of-file on a file.

17 |
18 | int f_eof (
19 |   FIL* fp   /* [IN] File object */
20 | );
21 | 
22 |
23 | 24 | 25 |
26 |

Parameters

27 |
28 |
fp
29 |
Pointer to the open file object structure.
30 |
31 |
32 | 33 | 34 |
35 |

Return Values

36 |

The f_eof function returns a non-zero value if the read/write pointer has reached end of the file; otherwise it returns a zero.

37 |
38 | 39 | 40 |
41 |

Description

42 |

In this revision, this function is implemented as a macro. It does not have any validation and mutual exclusion.

43 |
44 | #define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
45 | 
46 |
47 | 48 | 49 |
50 |

QuickInfo

51 |

Always available.

52 |
53 | 54 | 55 |
56 |

See Also

57 |

f_open, f_lseek, FIL

58 |
59 | 60 |

Return

61 | 62 | 63 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/error.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_error 10 | 11 | 12 | 13 | 14 |
15 |

f_error

16 |

The f_error tests for an error on a file.

17 |
18 | int f_error (
19 |   FIL* fp   /* [IN] File object */
20 | );
21 | 
22 |
23 | 24 | 25 |
26 |

Parameters

27 |
28 |
fp
29 |
Pointer to the open file object structure.
30 |
31 |
32 | 33 | 34 |
35 |

Return Values

36 |

Returns a non-zero value if a hard error has occured; otherwise it returns a zero.

37 |
38 | 39 | 40 |
41 |

Description

42 |

In this revision, this function is implemented as a macro. It does not have any validation and mutual exclusion.

43 |
44 | #define f_error(fp) ((fp)->err)
45 | 
46 |
47 | 48 | 49 |
50 |

QuickInfo

51 |

Always available.

52 |
53 | 54 | 55 |
56 |

See Also

57 |

f_open, FIL

58 |
59 | 60 |

Return

61 | 62 | 63 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/fattime.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - get_fattime 10 | 11 | 12 | 13 | 14 |
15 |

get_fattime

16 |

The get_fattime function is called to get the current time.

17 |
18 | DWORD get_fattime (void);
19 | 
20 |
21 | 22 | 23 |
24 |

Return Value

25 |

Currnet local time shall be returned as bit-fields packed into a DWORD value. The bit fields are as follows:

26 |
27 |
bit31:25
28 |
Year origin from the 1980 (0..127, e.g. 37 for 2017)
29 |
bit24:21
30 |
Month (1..12)
31 |
bit20:16
32 |
Day of the month (1..31)
33 |
bit15:11
34 |
Hour (0..23)
35 |
bit10:5
36 |
Minute (0..59)
37 |
bit4:0
38 |
Second / 2 (0..29, e.g. 25 for 50)
39 |
40 |
41 | 42 | 43 |
44 |

Description

45 |

The get_fattime function shall return any valid time even if the system does not support a real time clock. If a zero is returned, the file will not have a valid timestamp.

46 |
47 | 48 | 49 |
50 |

QuickInfo

51 |

This function is not needed when FF_FS_READONLY == 1 or FF_FS_NORTC == 1.

52 |
53 | 54 | 55 |
56 |

Example

57 |
58 | DWORD get_fattime (void)
59 | {
60 |     time_t t;
61 |     struct tm *stm;
62 | 
63 | 
64 |     t = time(0);
65 |     stm = localtime(&t);
66 | 
67 |     return (DWORD)(stm->tm_year - 80) << 25 |
68 |            (DWORD)(stm->tm_mon + 1) << 21 |
69 |            (DWORD)stm->tm_mday << 16 |
70 |            (DWORD)stm->tm_hour << 11 |
71 |            (DWORD)stm->tm_min << 5 |
72 |            (DWORD)stm->tm_sec >> 1;
73 | }
74 | 
75 |
76 | 77 | 78 |

Return

79 | 80 | 81 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/findnext.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_findnext 10 | 11 | 12 | 13 | 14 |
15 |

f_findnext

16 |

The f_findnext function searches for a next matched object

17 |
18 | FRESULT f_findnext (
19 |   DIR* dp,              /* [IN] Poninter to the directory object */
20 |   FILINFO* fno          /* [OUT] Pointer to the file information structure */
21 | );
22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
dp
29 |
Pointer to the valid directory object created by f_findfirst function.
30 |
fno
31 |
Pointer to the file information structure to store the information about the found directory item.
32 |
33 |
34 | 35 | 36 |
37 |

Return Values

38 |

39 | FR_OK, 40 | FR_DISK_ERR, 41 | FR_INT_ERR, 42 | FR_NOT_READY, 43 | FR_INVALID_OBJECT, 44 | FR_TIMEOUT, 45 | FR_NOT_ENOUGH_CORE 46 |

47 |
48 | 49 | 50 |
51 |

Description

52 |

It continues the search from a previous call to the f_findfirst or f_findnext function. If found, the information about the object is stored into the file information structure. If no item to be read, a null string will be returned into fno->fname[].

53 |
54 | 55 | 56 |
57 |

QuickInfo

58 |

This is a wrapper function of f_readdir function. Available when FF_USE_FIND == 1 and FF_FS_MINIMIZE <= 1.

59 |
60 | 61 | 62 |
63 |

See Also

64 |

f_findfirst, f_closedir, DIR, FILINFO

65 |
66 | 67 |

Return

68 | 69 | 70 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/getcwd.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_getcwd 10 | 11 | 12 | 13 | 14 |
15 |

f_getcwd

16 |

The f_getcwd function retrieves the current directory of the current drive.

17 |
18 | FRESULT f_getcwd (
19 |   TCHAR* buff, /* [OUT] Buffer to return path name */
20 |   UINT len     /* [IN] The length of the buffer */
21 | );
22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
buff
29 |
Pointer to the buffer to receive the current directory string.
30 |
len
31 |
Size of the buffer in unit of TCHAR.
32 |
33 |
34 | 35 | 36 |
37 |

Return Values

38 |

39 | FR_OK, 40 | FR_DISK_ERR, 41 | FR_INT_ERR, 42 | FR_NOT_READY, 43 | FR_NOT_ENABLED, 44 | FR_NO_FILESYSTEM, 45 | FR_TIMEOUT, 46 | FR_NOT_ENOUGH_CORE 47 |

48 |
49 | 50 | 51 |
52 |

Description

53 |

The f_getcwd function retrieves full path name of the current directory of the current drive. When FF_VOLUMES >= 2, a heading drive prefix is added to the path name. The style of drive prefix depends on FF_STR_VOLUME_ID.

54 |

Note: In this revision, this function cannot retrieve the current directory path on the exFAT volume. It always returns the root directory path.

55 |
56 | 57 | 58 |
59 |

QuickInfo

60 |

Available when FF_FS_RPATH == 2.

61 |
62 | 63 | 64 |
65 |

Example

66 |
67 |     FRESULT fr;
68 |     TCHAR str[SZ_STR];
69 | 
70 |     fr = f_getcwd(str, SZ_STR);  /* Get current directory path */
71 | 
72 | 
73 |
74 | 75 | 76 |
77 |

See Also

78 |

f_chdrive, f_chdir

79 |
80 | 81 |

Return

82 | 83 | 84 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/getfree.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_getfree 10 | 11 | 12 | 13 | 14 |
15 |

f_getfree

16 |

The f_getfree function gets number of the free clusters on the volume.

17 |
18 | FRESULT f_getfree (
19 |   const TCHAR* path,  /* [IN] Logical drive number */
20 |   DWORD* nclst,       /* [OUT] Number of free clusters */
21 |   FATFS** fatfs       /* [OUT] Corresponding filesystem object */
22 | );
23 | 
24 |
25 | 26 |
27 |

Parameters

28 |
29 |
path
30 |
Pointer to the null-terminated string that specifies the logical drive. A null-string means the default drive.
31 |
nclst
32 |
Pointer to the DWORD variable to store number of free clusters.
33 |
fatfs
34 |
Pointer to pointer that to store a pointer to the corresponding filesystem object.
35 |
36 |
37 | 38 | 39 |
40 |

Return Values

41 |

42 | FR_OK, 43 | FR_DISK_ERR, 44 | FR_INT_ERR, 45 | FR_NOT_READY, 46 | FR_INVALID_DRIVE, 47 | FR_NOT_ENABLED, 48 | FR_NO_FILESYSTEM, 49 | FR_TIMEOUT 50 |

51 |
52 | 53 | 54 |
55 |

Descriptions

56 |

The f_getfree function gets number of free clusters on the volume. The member csize in the filesystem object indicates number of sectors per cluster, so that the free space in unit of sector can be calcurated with this information. In case of FSINFO structure on the FAT32 volume is not in sync, this function can return an incorrect free cluster count. To avoid this problem, FatFs can be forced full FAT scan by FF_FS_NOFSINFO option.

57 |
58 | 59 | 60 |
61 |

QuickInfo

62 |

Available when FF_FS_READONLY == 0 and FF_FS_MINIMIZE == 0.

63 |
64 | 65 | 66 |
67 |

Example

68 |
69 |     FATFS *fs;
70 |     DWORD fre_clust, fre_sect, tot_sect;
71 | 
72 | 
73 |     /* Get volume information and free clusters of drive 1 */
74 |     res = f_getfree("1:", &fre_clust, &fs);
75 |     if (res) die(res);
76 | 
77 |     /* Get total sectors and free sectors */
78 |     tot_sect = (fs->n_fatent - 2) * fs->csize;
79 |     fre_sect = fre_clust * fs->csize;
80 | 
81 |     /* Print the free space (assuming 512 bytes/sector) */
82 |     printf("%10lu KiB total drive space.\n%10lu KiB available.\n", tot_sect / 2, fre_sect / 2);
83 | 
84 |
85 | 86 | 87 |
88 |

See Also

89 |

FATFS

90 |
91 | 92 |

Return

93 | 94 | 95 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/getlabel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_getlabel 10 | 11 | 12 | 13 | 14 |
15 |

f_getlabel

16 |

The f_getlabel function returns volume label and volume serial number of a volume.

17 |
18 | FRESULT f_getlabel (
19 |   const TCHAR* path,  /* [IN] Drive number */
20 |   TCHAR* label,       /* [OUT] Volume label */
21 |   DWORD* vsn          /* [OUT] Volume serial number */
22 | );
23 | 
24 |
25 | 26 |
27 |

Parameters

28 |
29 |
path
30 |
Pointer to the null-terminated string that specifies the logical drive. Null-string specifies the default drive.
31 |
label
32 |
Pointer to the buffer to store the volume label. If the volume has no label, a null-string will be returned. Set null pointer if this information is not needed. The buffer size should be shown below at least to avoid buffer overflow.
33 | 34 | 35 | 36 | 37 | 38 | 39 |
ConfigurationFF_FS_EXFAT == 0FF_FS_EXFAT == 1
FF_USE_LFN == 012 items-
FF_LFN_UNICODE == 012 items23 items
FF_LFN_UNICODE == 1,312 items12 items
FF_LFN_UNICODE == 234 items34 items
40 |
41 |
vsn
42 |
Pointer to the DWORD variable to store the volume serial number. Set null pointer if this information is not needed.
43 |
44 |
45 | 46 | 47 |
48 |

Return Values

49 |

50 | FR_OK, 51 | FR_DISK_ERR, 52 | FR_INT_ERR, 53 | FR_NOT_READY, 54 | FR_INVALID_DRIVE, 55 | FR_NOT_ENABLED, 56 | FR_NO_FILESYSTEM, 57 | FR_TIMEOUT 58 |

59 |
60 | 61 | 62 |
63 |

QuickInfo

64 |

Available when FF_USE_LABEL == 1.

65 |
66 | 67 | 68 |
69 |

Example

70 |
71 |     char str[12];
72 | 
73 |     /* Get volume label of the default drive */
74 |     f_getlabel("", str, 0);
75 | 
76 |     /* Get volume label of the drive 2 */
77 |     f_getlabel("2:", str, 0);
78 | 
79 |
80 | 81 | 82 |
83 |

See Also

84 | f_setlabel 85 |
86 | 87 | 88 |

Return

89 | 90 | 91 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/gets.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_gets 10 | 11 | 12 | 13 | 14 |
15 |

f_gets

16 |

The f_gets reads a string from the file.

17 |
18 | TCHAR* f_gets (
19 |   TCHAR* buff, /* [OUT] Read buffer */
20 |   int len,     /* [IN] Size of the read buffer */
21 |   FIL* fp      /* [IN] File object */
22 | );
23 | 
24 |
25 | 26 |
27 |

Parameters

28 |
29 |
buff
30 |
Pointer to read buffer to store the read string.
31 |
len
32 |
Size of the read buffer in unit of item.
33 |
fp
34 |
Pointer to the open file object structure.
35 |
36 |
37 | 38 | 39 |
40 |

Return Values

41 |

When the function succeeded, buff will be returuned.

42 |
43 | 44 | 45 |
46 |

Description

47 |

The read operation continues until a '\n' is stored, reached end of the file or the buffer is filled with len - 1 characters. The read string is terminated with a '\0'. When no character to read or any error occured during read operation, it returns a null pointer. The status of EOF and error can be examined with f_eof and f_error function.

48 |

When FatFs is configured to Unicode API (FF_LFN_UNICODE >= 1), data types on the srting fuctions, f_putc, f_puts, f_printf and f_gets, is also switched to Unicode. The character encoding on the file to be read via this function is assumed as FF_STRF_ENCODE. If the character encoding on the file differs from that on the API, it is converted in this function. In this case, input characters with wrong encoding will be lost.

49 |
50 | 51 | 52 |
53 |

QuickInfo

54 |

This is a wrapper function of f_read function. Available when FF_USE_STRFUNC >= 1. When it is set to 2, '\r's contained in the file are stripped out.

55 |
56 | 57 | 58 |
59 |

See Also

60 |

f_open, f_read, f_putc, f_puts, f_printf, f_close, FIL

61 |
62 | 63 |

Return

64 | 65 | 66 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/mkdir.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_mkdir 10 | 11 | 12 | 13 | 14 |
15 |

f_mkdir

16 |

The f_mkdir function creates a new directory.

17 |
18 | FRESULT f_mkdir (
19 |   const TCHAR* path /* [IN] Directory name */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
path
28 |
Pointer to the null-terminated string that specifies the directory name to create.
29 |
30 |
31 | 32 | 33 |
34 |

Return Value

35 |

36 | FR_OK, 37 | FR_DISK_ERR, 38 | FR_INT_ERR, 39 | FR_NOT_READY, 40 | FR_NO_PATH, 41 | FR_INVALID_NAME, 42 | FR_DENIED, 43 | FR_EXIST, 44 | FR_WRITE_PROTECTED, 45 | FR_INVALID_DRIVE, 46 | FR_NOT_ENABLED, 47 | FR_NO_FILESYSTEM, 48 | FR_TIMEOUT, 49 | FR_NOT_ENOUGH_CORE 50 |

51 |
52 | 53 | 54 |
55 |

Description

56 |

This function creates a new directory. To remove a directory, use f_unlink function.

57 |
58 | 59 | 60 |
61 |

QuickInfo

62 |

Available when FF_FS_READONLY == 0 and FF_FS_MINIMIZE == 0.

63 |
64 | 65 | 66 |
67 |

Example

68 |
69 |     res = f_mkdir("sub1");
70 |     if (res) die(res);
71 |     res = f_mkdir("sub1/sub2");
72 |     if (res) die(res);
73 |     res = f_mkdir("sub1/sub2/sub3");
74 |     if (res) die(res);
75 | 
76 |
77 | 78 |

Return

79 | 80 | 81 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/opendir.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_opendir 10 | 11 | 12 | 13 | 14 |
15 |

f_opendir

16 |

The f_opendir function opens a directory.

17 |
18 | FRESULT f_opendir (
19 |   DIR* dp,           /* [OUT] Pointer to the directory object structure */
20 |   const TCHAR* path  /* [IN] Directory name */
21 | );
22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
dp
29 |
Pointer to the blank directory object to create a new one.
30 |
path
31 |
Pointer to the null-terminated string that specifies the directory name to be opened.
32 |
33 |
34 | 35 | 36 |
37 |

Return Values

38 |

39 | FR_OK, 40 | FR_DISK_ERR, 41 | FR_INT_ERR, 42 | FR_NOT_READY, 43 | FR_NO_PATH, 44 | FR_INVALID_NAME, 45 | FR_INVALID_OBJECT, 46 | FR_INVALID_DRIVE, 47 | FR_NOT_ENABLED, 48 | FR_NO_FILESYSTEM, 49 | FR_TIMEOUT, 50 | FR_NOT_ENOUGH_CORE, 51 | FR_TOO_MANY_OPEN_FILES 52 |

53 |
54 | 55 | 56 |
57 |

Description

58 |

The f_opendir function opens an exsisting directory and creates a directory object for subsequent f_readdir function.

59 |
60 | 61 | 62 |
63 |

QuickInfo

64 |

Available when FF_FS_MINIMIZE <= 1.

65 |
66 | 67 | 68 |
69 |

See Also

70 |

f_readdir, f_closedir, DIR

71 |
72 | 73 |

Return

74 | 75 | 76 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/putc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_putc 10 | 11 | 12 | 13 | 14 |
15 |

f_putc

16 |

The f_putc funciton puts a character to the file.

17 |
18 | int f_putc (
19 |   TCHAR chr,  /* [IN] A character to write */
20 |   FIL* fp     /* [IN] File object */
21 | );
22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
chr
29 |
A character to write.
30 |
fp
31 |
Pointer to the open file object structuer.
32 |
33 |
34 | 35 | 36 |
37 |

Return Values

38 |

When the character was written successfuly, it returns number of character encoding units written to the file. When the function failed due to disk full or any error, a negative value will be returned.

39 |
40 | 41 | 42 |
43 |

Description

44 |

When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The character encoding on the file to be read/written via those functions is selected by FF_STRF_ENCODE. The Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, cannot be written with this function.

45 |
46 | 47 |
48 |

QuickInfo

49 |

This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC >= 1. When FF_USE_STRFUNC == 2, a '\n' is output as '\r'+'\n'.

50 |
51 | 52 | 53 |
54 |

See Also

55 |

f_open, f_puts, f_printf, f_gets, f_close, FIL

56 |
57 | 58 |

Return

59 | 60 | 61 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/puts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_puts 10 | 11 | 12 | 13 | 14 |
15 |

f_puts

16 |

The f_puts function writes a string to the file.

17 |
18 | int f_puts (
19 |   const TCHAR* str, /* [IN] String */
20 |   FIL* fp           /* [IN] File object */
21 | );
22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
str
29 |
Pointer to the null terminated string to be written. The terminator character will not be written.
30 |
fp
31 |
Pointer to the open file object structure.
32 |
33 |
34 | 35 | 36 |
37 |

Return Value

38 |

When the string was written successfuly, it returns number of character encoding units written to the file. When the function failed due to disk full or any error, a negative value will be returned.

39 |
40 | 41 | 42 |
43 |

Description

44 |

When FatFs is configured for Unicode API (FF_LFN_UNICODE >= 1), character encoding on the string fuctions, f_putc, f_puts, f_printf and f_gets function, is also switched to Unicode. The input Unicode characters in multiple encoding unit, such as surrogate pair and multi-byte sequence, should not be divided into two function calls, or the character will be lost. The character encoding on the file to be written via this functions is selected by FF_STRF_ENCODE. The characters with wrong encoding or invalid for the output encoding will be lost.

45 |
46 | 47 | 48 |
49 |

QuickInfo

50 |

This is a wrapper function of f_write function. Available when FF_FS_READONLY == 0 and FF_USE_STRFUNC >= 1. When FF_USE_STRFUNC == 2, '\n's contained in the input string are output as '\r'+'\n' each.

51 |
52 | 53 | 54 |
55 |

See Also

56 |

f_open, f_putc, f_printf, f_gets, f_close, FIL

57 |
58 | 59 |

Return

60 | 61 | 62 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/read.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_read 10 | 11 | 12 | 13 | 14 |
15 |

f_read

16 |

The f_read function reads data from a file.

17 |
18 | FRESULT f_read (
19 |   FIL* fp,     /* [IN] File object */
20 |   void* buff,  /* [OUT] Buffer to store read data */
21 |   UINT btr,    /* [IN] Number of bytes to read */
22 |   UINT* br     /* [OUT] Number of bytes read */
23 | );
24 | 
25 |
26 | 27 |
28 |

Parameters

29 |
30 |
fp
31 |
Pointer to the open file object.
32 |
buff
33 |
Pointer to the buffer to store the read data.
34 |
btr
35 |
Number of bytes to read in range of UINT type. If the file needs to be read fast, it should be read in large chunk as possible.
36 |
br
37 |
Pointer to the UINT variable that receives number of bytes read. This value is always valid after the function call regardless of the function return code. If the return value is equal to btr, the function return code should be FR_OK.
38 |
39 |
40 | 41 | 42 |
43 |

Return Values

44 |

45 | FR_OK, 46 | FR_DISK_ERR, 47 | FR_INT_ERR, 48 | FR_DENIED, 49 | FR_INVALID_OBJECT, 50 | FR_TIMEOUT 51 |

52 |
53 | 54 | 55 |
56 |

Description

57 |

The function starts to read data from the file at the file offset pointed by read/write pointer. The read/write pointer advances as number of bytes read. After the function succeeded, *br should be checked to detect end of the file. In case of *br < btr, it means the read/write pointer hit end of the file during read operation.

58 |
59 | 60 | 61 |
62 |

QuickInfo

63 |

Always available.

64 |
65 | 66 | 67 |
68 |

Example

69 |

Refer to the example in f_open.

70 |
71 | 72 | 73 |
74 |

See Also

75 |

f_open, fgets, f_write, f_close, FIL

76 |
77 | 78 |

Return

79 | 80 | 81 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/rename.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_rename 10 | 11 | 12 | 13 | 14 |
15 |

f_rename

16 |

The f_rename function renames and/or moves a file or sub-directory.

17 |
18 | FRESULT f_rename (
19 |   const TCHAR* old_name, /* [IN] Old object name */
20 |   const TCHAR* new_name  /* [IN] New object name */
21 | );
22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
old_name
29 |
Pointer to a null-terminated string that specifies the existing file or sub-directory to be renamed.
30 |
new_name
31 |
Pointer to a null-terminated string that specifies the new object name. A drive number may be specified in this string but it is ignored and assumed as the same drive of the old_name. Any object with this path name except old_name must not be exist, or the function fails with FR_EXIST.
32 |
33 |
34 | 35 | 36 |
37 |

Return Values

38 |

39 | FR_OK, 40 | FR_DISK_ERR, 41 | FR_INT_ERR, 42 | FR_NOT_READY, 43 | FR_NO_FILE, 44 | FR_NO_PATH, 45 | FR_INVALID_NAME, 46 | FR_EXIST, 47 | FR_WRITE_PROTECTED, 48 | FR_INVALID_DRIVE, 49 | FR_NOT_ENABLED, 50 | FR_NO_FILESYSTEM, 51 | FR_TIMEOUT, 52 | FR_LOCKED, 53 | FR_NOT_ENOUGH_CORE 54 |

55 |
56 | 57 | 58 |
59 |

Description

60 |

Renames a file or sub-directory and can also move it to other directory in the same volume. The object to be renamed must not be an open object, or the FAT volume can be collapsed. Such the wrong operation is rejected safely when file lock function is enabled.

61 |
62 | 63 | 64 |
65 |

QuickInfo

66 |

Available when FF_FS_READONLY == 0 and FF_FS_MINIMIZE == 0.

67 |
68 | 69 | 70 |
71 |

Example

72 |
73 |     /* Rename an object in the default drive */
74 |     f_rename("oldname.txt", "newname.txt");
75 | 
76 |     /* Rename an object in the drive 2 */
77 |     f_rename("2:oldname.txt", "newname.txt");
78 | 
79 |     /* Rename an object and move it to another directory in the drive */
80 |     f_rename("log.txt", "old/log0001.txt");
81 | 
82 |
83 | 84 | 85 |

Return

86 | 87 | 88 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/sdir.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - DIR 10 | 11 | 12 | 13 | 14 |
15 |

DIR

16 |

The DIR structure is used for the work area to read a directory by f_oepndir, f_readdir, f_findfirst and f_findnext function. Application program must not modify any member in this structure, or f_readdir function will not work properly.

17 |
18 | typedef struct {
19 |     FFOBJID obj;        /* Object identifier */
20 |     DWORD   dptr;       /* Current read/write offset */
21 |     DWORD   clust;      /* Current cluster */
22 |     LBA_t   sect;       /* Current sector */
23 |     BYTE*   dir;        /* Pointer to the current SFN entry in the win[] */
24 |     BYTE*   fn;         /* Pointer to the SFN buffer (in/out) {file[8],ext[3],status[1]} */
25 | #if FF_USE_LFN
26 |     DWORD   blk_ofs;    /* Offset of the entry block (0xFFFFFFFF:Invalid) */
27 |     WCHAR*  lfn;        /* Pointer to the LFN working buffer (in/out) */
28 | #endif
29 | #if FF_USE_FIND
30 |     const TCHAR*  pat;  /* Ponter to the matching pattern */
31 | #endif
32 | } DIR;
33 | 
34 |
35 | 36 |

Return

37 | 38 | 39 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/setcp.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_setcp 10 | 11 | 12 | 13 | 14 |
15 |

f_setcp

16 |

The f_setcp function sets the active code page.

17 |
18 | FRESULT f_setcp (
19 |   WORD cp     /* [IN] Code page to be set */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameters

26 |
27 |
cp
28 |
OEM code page to be used for the path name. Valid values are as follows.
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 |
ValueMeaning
0Initial value (any extended character cannot be used)
437U.S.
720Arabic
737Greek
771KBL
775Baltic
850Latin 1
852Latin 2
855Cyrillic
857Turkish
860Portuguese
861Icelandic
862Hebrew
863Canadian French
864Arabic
865Nordic
866Russian
869Greek 2
932Japanese (DBCS)
936Simplified Chinese (DBCS)
949Korean (DBCS)
950Traditional Chinese (DBCS)
54 |
55 |
56 |
57 | 58 | 59 |
60 |

Return Values

61 |

62 | FR_OK, 63 | FR_INVALID_PARAMETER 64 |

65 |
66 | 67 | 68 |
69 |

Description

70 |

The f_setcp function sets the active code page for the path name. Also code conversion of string functions will be affected by the setting of code page when FF_LFN_UNICODE >= 1 and FF_STRF_ENCODE == 0. Because the initial setting of the code page is 0 and API function with extended character will not work properly, a valid code page needs to be set on the system start-up and it should not be changed on the fly.

71 |
72 | 73 | 74 |
75 |

QuickInfo

76 |

Available when FF_CODE_PAGE == 0.

77 |
78 | 79 | 80 |

Return

81 | 82 | 83 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/setlabel.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_setlabel 10 | 11 | 12 | 13 | 14 |
15 |

f_setlabel

16 |

The f_setlabel function sets/removes the label of a volume.

17 |
18 | FRESULT f_setlabel (
19 |   const TCHAR* label  /* [IN] Volume label to be set */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameters

26 |
27 |
label
28 |
Pointer to the null-terminated string that specifies the volume label to be set.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_DISK_ERR, 38 | FR_INT_ERR, 39 | FR_NOT_READY, 40 | FR_INVALID_NAME, 41 | FR_WRITE_PROTECTED, 42 | FR_INVALID_DRIVE, 43 | FR_NOT_ENABLED, 44 | FR_NO_FILESYSTEM, 45 | FR_TIMEOUT 46 |

47 |
48 | 49 | 50 |
51 |

Description

52 |

When the string has a drive prefix, the volume label will be set to the volume specified by the drive prefix. Unix style volume ID cannot be used to specify the volume. If drive number is not specified, the volume label will be set to the default drive. If length of the given volume label is zero, the volume label on the volume will be removed. The format of the volume label is as shown below:

53 |
    54 |
  • Up to 11 bytes long as conversion of OEM code page at FAT volume.
  • 55 |
  • Up to 11 characters long at exFAT volume.
  • 56 |
  • Allowable characters for FAT volume are: characters allowed for SFN excludes dot. Low-case characters are up converted.
  • 57 |
  • Allowable characters for exFAT volume are: characters allowed for LFN includes dot. Low-case characters are preserved.
  • 58 |
  • Spaces can be embedded anywhere in the volume label. Trailing spaces are truncated off at FAT volume.
  • 59 |
60 |

Remark: The standard system (Windows) has a problem at the volume label with a heading \xE5 on the FAT volume. To avoid this problem, this function rejects such volume label as invalid name.

61 |
62 | 63 |
64 |

QuickInfo

65 |

Available when FF_FS_READONLY == 0 and FF_USE_LABEL == 1.

66 |
67 | 68 | 69 |
70 |

Example

71 |
72 |     /* Set volume label to the default drive */
73 |     f_setlabel("DATA DISK");
74 | 
75 |     /* Set volume label to the drive 2 */
76 |     f_setlabel("2:DISK 3 OF 4");
77 | 
78 |     /* Remove volume label of the drive 2 */
79 |     f_setlabel("2:");
80 | 
81 |
82 | 83 | 84 |
85 |

See Also

86 | f_getlabel 87 |
88 | 89 | 90 |

Return

91 | 92 | 93 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/sfatfs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - FATFS 10 | 11 | 12 | 13 | 14 |
15 |

FATFS

16 |

The FATFS structure (filesystem object) holds dynamic work area of individual logical drives. It is given by application program and registerd/unregisterd to the FatFs module with f_mount function. Initialization of the structure is done by volume mount process whenever necessary. Application program must not modify any member in this structure, or the FAT volume will be collapsed.

17 |
18 | typedef struct {
19 |     BYTE    fs_type;      /* FAT type (0, FS_FAT12, FS_FAT16, FS_FAT32 or FS_EXFAT) */
20 |     BYTE    pdrv;         /* Hosting physical drive of this volume */
21 |     BYTE    n_fats;       /* Number of FAT copies (1,2) */
22 |     BYTE    wflag;        /* win[] flag (b0:win[] is dirty) */
23 |     BYTE    fsi_flag;     /* FSINFO flags (b7:Disabled, b0:Dirty) */
24 |     WORD    id;           /* Volume mount ID */
25 |     WORD    n_rootdir;    /* Number of root directory entries (FAT12/16) */
26 |     WORD    csize;        /* Sectors per cluster */
27 | #if FF_MAX_SS != FF_MIN_SS
28 |     WORD    ssize;        /* Sector size (512,1024,2048 or 4096) */
29 | #endif
30 | #if FF_FS_EXFAT
31 |     BYTE*   dirbuf;       /* Directory entry block scratchpad buffer */
32 | #endif
33 | #if FF_FS_REENTRANT
34 |     FF_SYNC_t sobj;       /* Identifier of sync object */
35 | #endif
36 | #if !FF_FS_READONLY
37 |     DWORD   last_clust;   /* FSINFO: Last allocated cluster (0xFFFFFFFF if invalid) */
38 |     DWORD   free_clust;   /* FSINFO: Number of free clusters (0xFFFFFFFF if invalid) */
39 | #endif
40 | #if FF_FS_RPATH
41 |     DWORD   cdir;         /* Cluster number of current directory (0:root) */
42 | #if FF_FS_EXFAT
43 |     DWORD   cdc_scl;      /* Containing directory start cluster (invalid when cdir is 0) */
44 |     DWORD   cdc_size;     /* b31-b8:Size of containing directory, b7-b0: Chain status */
45 |     DWORD   cdc_ofs;      /* Offset in the containing directory (invalid when cdir is 0) */
46 | #endif
47 | #endif
48 |     DWORD   n_fatent;     /* Number of FAT entries (Number of clusters + 2) */
49 |     DWORD   fsize;        /* Sectors per FAT */
50 |     LBA_t   volbase;      /* Volume base LBA */
51 |     LBA_t   fatbase;      /* FAT base LBA */
52 |     LBA_t   dirbase;      /* Root directory base (LBA|Cluster) */
53 |     LBA_t   database;     /* Data base LBA */
54 |     LBA_t   winsect;      /* Sector LBA appearing in the win[] */
55 |     BYTE    win[FF_MAX_SS]; /* Disk access window for directory, FAT (and file data at tiny cfg) */
56 | } FATFS;
57 | 
58 |
59 | 60 |

Return

61 | 62 | 63 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/sfile.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - FIL 10 | 11 | 12 | 13 | 14 |
15 |

FIL

16 |

The FIL structure (file object) holds the state of an open file. It is created by f_open function and discarded by f_close function. Application program must not modify any member in this structure except for cltbl, or the FAT volume will be collapsed. Note that a sector buffer is defined in this structure at non-tiny configuration (FF_FS_TINY == 0), so that the FIL structures at that configuration should not be defined as auto variable.

17 | 18 |
19 | typedef struct {
20 |     FFOBJID obj;          /* Object identifier */
21 |     BYTE    flag;         /* File object status flags */
22 |     BYTE    err;          /* Abort flag (error code) */
23 |     FSIZE_t fptr;         /* File read/write pointer (Byte offset origin from top of the file) */
24 |     DWORD   clust;        /* Current cluster of fptr (One cluster behind if fptr is on the cluster boundary. Invalid if fptr == 0.) */
25 |     LBA_t   sect;         /* Current data sector (Can be invalid if fptr is on the cluster boundary.)*/
26 | #if !FF_FS_READONLY
27 |     LBA_t   dir_sect;     /* Sector number containing the directory entry */
28 |     BYTE*   dir_ptr;      /* Ponter to the directory entry in the window */
29 | #endif
30 | #if FF_USE_FASTSEEK
31 |     DWORD*  cltbl;        /* Pointer to the cluster link map table (Nulled on file open. Set by application.) */
32 | #endif
33 | #if !FF_FS_TINY
34 |     BYTE    buf[FF_MAX_SS]; /* File private data transfer buffer (Always valid if fptr is not on the sector boundary but can be invalid if fptr is on the sector boundary.) */
35 | #endif
36 | } FIL;
37 | 
38 | 39 |
40 | 41 |

Return

42 | 43 | 44 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/sfileinfo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - FILINFO 10 | 11 | 12 | 13 | 14 |
15 |

FILINFO

16 |

The FILINFO structure holds information about the object retrieved by f_readdir, f_findfirst, f_findnext and f_stat function. Be careful in the size of structure when LFN is enabled.

17 |
18 | typedef struct {
19 |     FSIZE_t fsize;               /* File size */
20 |     WORD    fdate;               /* Last modified date */
21 |     WORD    ftime;               /* Last modified time */
22 |     BYTE    fattrib;             /* Attribute */
23 | #if FF_USE_LFN
24 |     TCHAR   altname[FF_SFN_BUF + 1]; /* Alternative object name */
25 |     TCHAR   fname[FF_LFN_BUF + 1];   /* Primary object name */
26 | #else
27 |     TCHAR   fname[12 + 1];       /* Object name */
28 | #endif
29 | } FILINFO;
30 | 
31 |
32 | 33 |

Members

34 |
35 |
fsize
36 |
Size of the file in unit of byte. FSIZE_t is an alias of integer type either DWORD(32-bit) or QWORD(64-bit) depends on the configuration option FF_FS_EXFAT. Do not care if the item is a sub-directory.
37 |
fdate
38 |
The date when the file was modified or the directory was created.
39 |
40 |
bit15:9
41 |
Year origin from 1980 (0..127)
42 |
bit8:5
43 |
Month (1..12)
44 |
bit4:0
45 |
Day (1..31)
46 |
47 |
48 |
ftime
49 |
The time when the file was modified or the directory was created.
50 |
51 |
bit15:11
52 |
Hour (0..23)
53 |
bit10:5
54 |
Minute (0..59)
55 |
bit4:0
56 |
Second / 2 (0..29)
57 |
58 |
59 |
fattrib
60 |
The attribute flags in combination of:
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 |
FlagMeaning
AM_RDORead-only. Write mode open and deleting is rejected.
AM_HIDHidden. Should not be shown in normal directory listing.
AM_SYSSystem. Used by system and should not be accessed.
AM_ARCArchive. Set on new creation or any modification to the file.
AM_DIRDirectory. This is not a file but a sub-directory container.
69 |
70 |
fname[]
71 |
Null-terminated object name. A null string is stored when no item to read and it indicates this structure is invalid. The size of fname[] and altname[] each can be configured in LFN configuration.
72 |
altname[]
73 |
Alternative object name is stored if available. This member is not available in non-LFN configuration.
74 |
75 | 76 |

Return

77 | 78 | 79 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/size.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_size 10 | 11 | 12 | 13 | 14 |
15 |

f_size

16 |

The f_size function gets the size of a file.

17 |
18 | FSIZE_t f_size (
19 |   FIL* fp   /* [IN] File object */
20 | );
21 | 
22 |
23 | 24 | 25 |
26 |

Parameters

27 |
28 |
fp
29 |
Pointer to the open file object structure.
30 |
31 |
32 | 33 | 34 |
35 |

Return Values

36 |

Returns the size of the file in unit of byte.

37 |
38 | 39 | 40 |
41 |

Description

42 |

In this revision, the f_size function is implemented as a macro. It does not have any validation and mutual exclusion.

43 |
44 | #define f_size(fp) ((fp)->obj.objsize)
45 | 
46 |
47 | 48 | 49 |
50 |

QuickInfo

51 |

Always available.

52 |
53 | 54 | 55 |
56 |

See Also

57 |

f_open, f_lseek, FIL

58 |
59 | 60 |

Return

61 | 62 | 63 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/stat.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_stat 10 | 11 | 12 | 13 | 14 |
15 |

f_stat

16 |

The f_stat function checks the existence of a file or sub-directory.

17 |
 18 | FRESULT f_stat (
 19 |   const TCHAR* path,  /* [IN] Object name */
 20 |   FILINFO* fno        /* [OUT] FILINFO structure */
 21 | );
 22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
path
29 |
Pointer to the null-terminated string that specifies the object to get its information. The object must not be the root direcotry.
30 |
fno
31 |
Pointer to the blank FILINFO structure to store the information of the object. Set null pointer if this information is not needed.
32 |
33 |
34 | 35 | 36 |
37 |

Return Values

38 |

39 | FR_OK, 40 | FR_DISK_ERR, 41 | FR_INT_ERR, 42 | FR_NOT_READY, 43 | FR_NO_FILE, 44 | FR_NO_PATH, 45 | FR_INVALID_NAME, 46 | FR_INVALID_DRIVE, 47 | FR_NOT_ENABLED, 48 | FR_NO_FILESYSTEM, 49 | FR_TIMEOUT, 50 | FR_NOT_ENOUGH_CORE 51 |

52 |
53 | 54 | 55 |
56 |

Description

57 |

The f_stat function checks the existence of a file or sub-directory in the directory. If it is not exist, the function returns with FR_NO_FILE. If it is exist, the function returns with FR_OK and the informations about the object, size, timestamp and attribute, is stored to the file information structure. For details of the file information, refer to the FILINFO structure and f_readdir function.

58 |

Note that the file information comes from the meta data in the directory. If the file has been opend and modified, the file will need to be synched or closed in order to obtain the latest file information.

59 |
60 | 61 | 62 |
63 |

QuickInfo

64 |

Available when FF_FS_MINIMIZE == 0.

65 |
66 | 67 | 68 |
69 |

Example

70 |
 71 |     FRESULT fr;
 72 |     FILINFO fno;
 73 |     const char *fname = "file.txt";
 74 | 
 75 | 
 76 |     printf("Test for \"%s\"...\n", fname);
 77 | 
 78 |     fr = f_stat(fname, &fno);
 79 |     switch (fr) {
 80 | 
 81 |     case FR_OK:
 82 |         printf("Size: %lu\n", fno.fsize);
 83 |         printf("Timestamp: %u-%02u-%02u, %02u:%02u\n",
 84 |                (fno.fdate >> 9) + 1980, fno.fdate >> 5 & 15, fno.fdate & 31,
 85 |                fno.ftime >> 11, fno.ftime >> 5 & 63);
 86 |         printf("Attributes: %c%c%c%c%c\n",
 87 |                (fno.fattrib & AM_DIR) ? 'D' : '-',
 88 |                (fno.fattrib & AM_RDO) ? 'R' : '-',
 89 |                (fno.fattrib & AM_HID) ? 'H' : '-',
 90 |                (fno.fattrib & AM_SYS) ? 'S' : '-',
 91 |                (fno.fattrib & AM_ARC) ? 'A' : '-');
 92 |         break;
 93 | 
 94 |     case FR_NO_FILE:
 95 |         printf("\"%s\" is not exist.\n", fname);
 96 |         break;
 97 | 
 98 |     default:
 99 |         printf("An error occured. (%d)\n", fr);
100 |     }
101 | 
102 |
103 | 104 | 105 |
106 |

References

107 |

f_opendir, f_readdir, FILINFO

108 |
109 | 110 |

Return

111 | 112 | 113 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/sync.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_sync 10 | 11 | 12 | 13 | 14 |
15 |

f_sync

16 |

The f_sync function flushes the cached information of a writing file.

17 |
18 | FRESULT f_sync (
19 |   FIL* fp     /* [IN] File object */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
fp
28 |
Pointer to the open file object to be flushed.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_DISK_ERR, 38 | FR_INT_ERR, 39 | FR_INVALID_OBJECT, 40 | FR_TIMEOUT 41 |

42 |
43 | 44 | 45 |
46 |

Description

47 |

The f_sync function performs the same process as f_close function but the file is left opened and can continue read/write/seek operations to the file. This is suitable for the applications that open files for a long time in write mode, such as data logger. Performing f_sync function in certain interval can minimize the risk of data loss due to a sudden blackout, wrong media removal or unrecoverable disk error. For more information, refer to application note.

48 |
49 | Case 1. Normal write sequence
50 | 
51 |                                 Time -->                                     ↓Normal shutdown
52 | OwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwC <Power off>
53 | 
54 | 
55 | Case 2. Without using f_sync()
56 | 
57 |                                 Time -->                             ↓System crush
58 | Owwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
59 |  |<--------------- All data written will be lost ------------------>|
60 | 
61 | 
62 | Case 3. Using f_sync()
63 |                                 Time -->                             ↓System crush
64 | OwwwwwwwwSwwwwwwwwSwwwwwwwwSwwwwwwwwSwwwwwwwwSwwwwwwwwSwwwwwwwwSwwwww
65 |                             Data after last f_sync will be lost |<->| 
66 | O - f_open()
67 | C - f_close()
68 | w - f_write()
69 | S - f_sync()
70 | 
71 |

However there is no sense in f_sync function immediataly before f_close function because it performs f_sync function in it. In other words, the differnce between those functions is that the file object is invalidated or not.

72 |
73 | 74 | 75 |
76 |

QuickInfo

77 |

Available when FF_FS_READONLY == 0.

78 |
79 | 80 | 81 |
82 |

See Also

83 |

f_close, Critical section

84 |
85 | 86 |

Return

87 | 88 | 89 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/tell.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_tell 10 | 11 | 12 | 13 | 14 |
15 |

f_tell

16 |

The f_tell function gets the current read/write pointer of a file.

17 |
18 | FSIZE_t f_tell (
19 |   FIL* fp   /* [IN] File object */
20 | );
21 | 
22 |
23 | 24 | 25 |
26 |

Parameters

27 |
28 |
fp
29 |
Pointer to the open file object structure.
30 |
31 |
32 | 33 | 34 |
35 |

Return Values

36 |

Returns current read/write pointer of the file.

37 |
38 | 39 | 40 |
41 |

Description

42 |

In this revision, the f_tell function is implemented as a macro. It does not have any validation and mutual exclusion.

43 |
44 | #define f_tell(fp) ((fp)->fptr)
45 | 
46 |
47 | 48 | 49 |
50 |

QuickInfo

51 |

Always available.

52 |
53 | 54 | 55 |
56 |

See Also

57 |

f_open, f_lseek, FIL

58 |
59 | 60 |

Return

61 | 62 | 63 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/truncate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_truncate 10 | 11 | 12 | 13 | 14 |
15 |

f_truncate

16 |

The f_truncate function truncates the file size.

17 |
18 | FRESULT f_truncate (
19 |   FIL* fp     /* [IN] File object */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
fp
28 |
Pointer to the open file object to be truncated.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_DISK_ERR, 38 | FR_INT_ERR, 39 | FR_DENIED, 40 | FR_INVALID_OBJECT, 41 | FR_TIMEOUT 42 |

43 |
44 | 45 | 46 |
47 |

Description

48 |

The f_truncate function truncates the file size to the current file read/write pointer. This function has no effect if the file read/write pointer is already pointing end of the file.

49 |
50 | 51 | 52 |
53 |

QuickInfo

54 |

Available when FF_FS_READONLY == 0 and FF_FS_MINIMIZE == 0.

55 |
56 | 57 | 58 |
59 |

See Also

60 |

f_open, f_lseek, FIL

61 |
62 | 63 | 64 |

Return

65 | 66 | 67 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/unlink.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_unlink 10 | 11 | 12 | 13 | 14 |
15 |

f_unlink

16 |

The f_unlink function removes a file or sub-directory from the volume.

17 |
18 | FRESULT f_unlink (
19 |   const TCHAR* path  /* [IN] Object name */
20 | );
21 | 
22 |
23 | 24 |
25 |

Parameter

26 |
27 |
path
28 |
Pointer to a null-terminated string that specifies the file or sub-directory to be removed.
29 |
30 |
31 | 32 | 33 |
34 |

Return Values

35 |

36 | FR_OK, 37 | FR_DISK_ERR, 38 | FR_INT_ERR, 39 | FR_NOT_READY, 40 | FR_NO_FILE, 41 | FR_NO_PATH, 42 | FR_INVALID_NAME, 43 | FR_DENIED, 44 | FR_WRITE_PROTECTED, 45 | FR_INVALID_DRIVE, 46 | FR_NOT_ENABLED, 47 | FR_NO_FILESYSTEM, 48 | FR_TIMEOUT, 49 | FR_LOCKED, 50 | FR_NOT_ENOUGH_CORE 51 |

52 |
53 | 54 | 55 |
56 |

Description

57 |

58 | If condition of the object to be removed is applicable to the following terms, the function will be rejected.

    59 |
  • The file/sub-directory must not have read-only attribute (AM_RDO), or the function will be rejected with FR_DENIED.
  • 60 |
  • The sub-directory must be empty and must not be current directory, or the function will be rejected with FR_DENIED.
  • 61 |
  • The file/sub-directory must not be opened, or the FAT volume can be collapsed. It will be rejected safely when file lock function is enabled.
  • 62 |
63 |
64 | 65 | 66 |
67 |

QuickInfo

68 |

Available when FF_FS_READONLY == 0 and FF_FS_MINIMIZE == 0.

69 |
70 | 71 | 72 |

Return

73 | 74 | 75 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/utime.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_utime 10 | 11 | 12 | 13 | 14 |
15 |

f_utime

16 |

The f_utime function changes the timestamp of a file or sub-directory.

17 |
 18 | FRESULT f_utime (
 19 |   const TCHAR* path,  /* [IN] Object name */
 20 |   const FILINFO* fno  /* [IN] Time and data to be set */
 21 | );
 22 | 
23 |
24 | 25 |
26 |

Parameters

27 |
28 |
path
29 |
Pointer to the null-terminated string that specifies an object to be changed.
30 |
fno
31 |
Pointer to the file information structure that has a timestamp to be set in member fdate and ftime. Do not care any other members.
32 |
33 |
34 | 35 | 36 |
37 |

Return Values

38 |

39 | FR_OK, 40 | FR_DISK_ERR, 41 | FR_INT_ERR, 42 | FR_NOT_READY, 43 | FR_NO_FILE, 44 | FR_NO_PATH, 45 | FR_INVALID_NAME, 46 | FR_WRITE_PROTECTED, 47 | FR_INVALID_DRIVE, 48 | FR_NOT_ENABLED, 49 | FR_NO_FILESYSTEM, 50 | FR_TIMEOUT, 51 | FR_NOT_ENOUGH_CORE 52 |

53 |
54 | 55 | 56 |
57 |

Description

58 |

The f_utime function changes the timestamp of a file or sub-directory

59 |
60 | 61 | 62 |
63 |

Example

64 |
 65 | FRESULT set_timestamp (
 66 |     char *obj,     /* Pointer to the file name */
 67 |     int year,
 68 |     int month,
 69 |     int mday,
 70 |     int hour,
 71 |     int min,
 72 |     int sec
 73 | )
 74 | {
 75 |     FILINFO fno;
 76 | 
 77 |     fno.fdate = (WORD)(((year - 1980) * 512U) | month * 32U | mday);
 78 |     fno.ftime = (WORD)(hour * 2048U | min * 32U | sec / 2U);
 79 | 
 80 |     return f_utime(obj, &fno);
 81 | }
 82 | 
83 |
84 | 85 | 86 |
87 |

QuickInfo

88 |

Available when FF_FS_READONLY == 0 and FF_USE_CHMOD == 1.

89 |
90 | 91 | 92 |
93 |

See Also

94 |

f_stat, FILINFO

95 |
96 | 97 |

Return

98 | 99 | 100 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/doc/write.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | FatFs - f_write 10 | 11 | 12 | 13 | 14 |
15 |

f_write

16 |

The f_write writes data to a file.

17 |
18 | FRESULT f_write (
19 |   FIL* fp,          /* [IN] Pointer to the file object structure */
20 |   const void* buff, /* [IN] Pointer to the data to be written */
21 |   UINT btw,         /* [IN] Number of bytes to write */
22 |   UINT* bw          /* [OUT] Pointer to the variable to return number of bytes written */
23 | );
24 | 
25 |
26 | 27 |
28 |

Parameters

29 |
30 |
fp
31 |
Pointer to the open file object structure.
32 |
buff
33 |
Pointer to the data to be written.
34 |
btw
35 |
Specifies number of bytes to write in range of UINT type. If the data needs to be written fast, it should be written in large chunk as possible.
36 |
bw
37 |
Pointer to the UINT variable that receives the number of bytes written. This value is always valid after the function call regardless of the function return code. If the return value is equal to btw, the function return code should be FR_OK.
38 |
39 |
40 | 41 | 42 |
43 |

Return Values

44 |

45 | FR_OK, 46 | FR_DISK_ERR, 47 | FR_INT_ERR, 48 | FR_DENIED, 49 | FR_INVALID_OBJECT, 50 | FR_TIMEOUT 51 |

52 |
53 | 54 | 55 |
56 |

Description

57 |

The function starts to write data to the file at the file offset pointed by read/write pointer. The read/write pointer advances as number of bytes written. After the function succeeded, *bw should be checked to detect the disk full. In case of *bw < btw, it means the volume got full during the write operation. The function can take a time when the volume is full or close to full.

58 |
59 | 60 | 61 |
62 |

QuickInfo

63 |

Available when FF_FS_READONLY == 0.

64 |
65 | 66 | 67 |
68 |

Example

69 |

Refer to the example in f_open.

70 |
71 | 72 | 73 |
74 |

See Also

75 |

f_open, f_read, fputc, fputs, fprintf, f_close, FIL

76 |
77 | 78 |

Return

79 | 80 | 81 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/app1.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------/ 2 | / Open or create a file in append mode 3 | / (This function was sperseded by FA_OPEN_APPEND flag at FatFs R0.12a) 4 | /------------------------------------------------------------*/ 5 | 6 | FRESULT open_append ( 7 | FIL* fp, /* [OUT] File object to create */ 8 | const char* path /* [IN] File name to be opened */ 9 | ) 10 | { 11 | FRESULT fr; 12 | 13 | /* Opens an existing file. If not exist, creates a new file. */ 14 | fr = f_open(fp, path, FA_WRITE | FA_OPEN_ALWAYS); 15 | if (fr == FR_OK) { 16 | /* Seek to end of the file to append data */ 17 | fr = f_lseek(fp, f_size(fp)); 18 | if (fr != FR_OK) 19 | f_close(fp); 20 | } 21 | return fr; 22 | } 23 | 24 | 25 | int main (void) 26 | { 27 | FRESULT fr; 28 | FATFS fs; 29 | FIL fil; 30 | 31 | /* Open or create a log file and ready to append */ 32 | f_mount(&fs, "", 0); 33 | fr = open_append(&fil, "logfile.txt"); 34 | if (fr != FR_OK) return 1; 35 | 36 | /* Append a line */ 37 | f_printf(&fil, "%02u/%02u/%u, %2u:%02u\n", Mday, Mon, Year, Hour, Min); 38 | 39 | /* Close the file */ 40 | f_close(&fil); 41 | 42 | return 0; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/app2.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------/ 2 | / Delete a sub-directory even if it contains any file 3 | /-------------------------------------------------------------/ 4 | / The delete_node() function is for R0.12+. 5 | / It works regardless of FF_FS_RPATH. 6 | */ 7 | 8 | 9 | FRESULT delete_node ( 10 | TCHAR* path, /* Path name buffer with the sub-directory to delete */ 11 | UINT sz_buff, /* Size of path name buffer (items) */ 12 | FILINFO* fno /* Name read buffer */ 13 | ) 14 | { 15 | UINT i, j; 16 | FRESULT fr; 17 | DIR dir; 18 | 19 | 20 | fr = f_opendir(&dir, path); /* Open the sub-directory to make it empty */ 21 | if (fr != FR_OK) return fr; 22 | 23 | for (i = 0; path[i]; i++) ; /* Get current path length */ 24 | path[i++] = _T('/'); 25 | 26 | for (;;) { 27 | fr = f_readdir(&dir, fno); /* Get a directory item */ 28 | if (fr != FR_OK || !fno->fname[0]) break; /* End of directory? */ 29 | j = 0; 30 | do { /* Make a path name */ 31 | if (i + j >= sz_buff) { /* Buffer over flow? */ 32 | fr = 100; break; /* Fails with 100 when buffer overflow */ 33 | } 34 | path[i + j] = fno->fname[j]; 35 | } while (fno->fname[j++]); 36 | if (fno->fattrib & AM_DIR) { /* Item is a sub-directory */ 37 | fr = delete_node(path, sz_buff, fno); 38 | } else { /* Item is a file */ 39 | fr = f_unlink(path); 40 | } 41 | if (fr != FR_OK) break; 42 | } 43 | 44 | path[--i] = 0; /* Restore the path name */ 45 | f_closedir(&dir); 46 | 47 | if (fr == FR_OK) fr = f_unlink(path); /* Delete the empty sub-directory */ 48 | return fr; 49 | } 50 | 51 | 52 | 53 | 54 | int main (void) /* How to use */ 55 | { 56 | FRESULT fr; 57 | FATFS fs; 58 | TCHAR buff[256]; 59 | FILINFO fno; 60 | 61 | 62 | f_mount(&fs, _T("5:"), 0); 63 | 64 | /* Directory to be deleted */ 65 | _tcscpy(buff, _T("5:dir")); 66 | 67 | /* Delete the directory */ 68 | fr = delete_node(buff, sizeof buff / sizeof buff[0], &fno); 69 | 70 | /* Check the result */ 71 | if (fr) { 72 | _tprintf(_T("Failed to delete the directory. (%u)\n"), fr); 73 | return fr; 74 | } else { 75 | _tprintf(_T("The directory and the contents have successfully been deleted.\n"), buff); 76 | return 0; 77 | } 78 | } 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/app3.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------/ 2 | / Allocate a contiguous area to the file 3 | /-----------------------------------------------------------------------/ 4 | / This function checks if the file is contiguous with desired size. 5 | / If not, a block of contiguous sectors is allocated to the file. 6 | / If the file has been opened without FA_WRITE flag, it only checks if 7 | / the file is contiguous and returns the resulut. 8 | /-----------------------------------------------------------------------/ 9 | / This function can work with FatFs R0.09 - R0.11a. 10 | / It is incompatible with R0.12+. Use f_expand function instead. 11 | /----------------------------------------------------------------------*/ 12 | 13 | /* Declarations of FatFs internal functions accessible from applications. 14 | / This is intended to be used for disk checking/fixing or dirty hacks :-) */ 15 | DWORD clust2sect (FATFS* fs, DWORD clst); 16 | DWORD get_fat (FATFS* fs, DWORD clst); 17 | FRESULT put_fat (FATFS* fs, DWORD clst, DWORD val); 18 | 19 | 20 | DWORD allocate_contiguous_clusters ( /* Returns the first sector in LBA (0:error or not contiguous) */ 21 | FIL* fp, /* Pointer to the open file object */ 22 | DWORD len /* Number of bytes to allocate */ 23 | ) 24 | { 25 | DWORD csz, tcl, ncl, ccl, cl; 26 | 27 | 28 | if (f_lseek(fp, 0) || !len) /* Check if the given parameters are valid */ 29 | return 0; 30 | csz = 512UL * fp->fs->csize; /* Cluster size in unit of byte (assuming 512 bytes/sector) */ 31 | tcl = (len + csz - 1) / csz; /* Total number of clusters required */ 32 | len = tcl * csz; /* Round-up file size to the cluster boundary */ 33 | 34 | /* Check if the existing cluster chain is contiguous */ 35 | if (len == fp->fsize) { 36 | ncl = 0; ccl = fp->sclust; 37 | do { 38 | cl = get_fat(fp->fs, ccl); /* Get the cluster status */ 39 | if (cl + 1 < 3) return 0; /* Hard error? */ 40 | if (cl != ccl + 1 && cl < fp->fs->n_fatent) break; /* Not contiguous? */ 41 | ccl = cl; 42 | } while (++ncl < tcl); 43 | if (ncl == tcl) /* Is the file contiguous? */ 44 | return clust2sect(fp->fs, fp->sclust); /* File is contiguous. Return the start sector */ 45 | } 46 | 47 | /* File is not contiguous */ 48 | #if _FS_READONLY 49 | return 0; /* Exit if in read-only cfg. */ 50 | #else 51 | if (!(fp->flag & FA_WRITE)) return 0; /* Exit if the file object is for read-only */ 52 | 53 | if (f_truncate(fp)) return 0; /* Remove the non-contiguous chain */ 54 | 55 | /* Find a free contiguous area */ 56 | ccl = cl = 2; ncl = 0; 57 | do { 58 | if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */ 59 | if (get_fat(fp->fs, cl)) { /* Encounterd a cluster in use */ 60 | do { /* Skip the block of used clusters */ 61 | cl++; 62 | if (cl >= fp->fs->n_fatent) return 0; /* No contiguous area is found. */ 63 | } while (get_fat(fp->fs, cl)); 64 | ccl = cl; ncl = 0; 65 | } 66 | cl++; ncl++; 67 | } while (ncl < tcl); 68 | 69 | /* Create a contiguous cluster chain */ 70 | fp->fs->last_clust = ccl - 1; 71 | if (f_lseek(fp, len)) return 0; 72 | 73 | return clust2sect(fp->fs, fp->sclust); /* Return file start sector */ 74 | #endif 75 | } 76 | 77 | 78 | int main (void) 79 | { 80 | FRESULT fr; 81 | DRESULT dr; 82 | FATFS fs; 83 | FIL fil; 84 | DWORD org; 85 | 86 | 87 | /* Open or create a file to write */ 88 | f_mount(&fs, "", 0); 89 | fr = f_open(&fil, "fastrec.log", FA_READ | FA_WRITE | FA_OPEN_ALWAYS); 90 | if (fr) return 1; 91 | 92 | /* Check if the file is 256MB in size and occupies a contiguous area. 93 | / If not, a contiguous area will be re-allocated to the file. */ 94 | org = allocate_contiguous_clusters(&fil, 0x10000000); 95 | if (!org) { 96 | printf("Function failed due to any error or insufficient contiguous area.\n"); 97 | f_close(&fil); 98 | return 1; 99 | } 100 | 101 | /* Now you can read/write the file without filesystem layer. */ 102 | ... 103 | dr = disk_write(fil.fs->drv, Buff, org, 1024); /* Write 512KiB from top of the file */ 104 | ... 105 | 106 | f_close(&fil); 107 | return 0; 108 | } 109 | 110 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/app5.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------/ 2 | / Test if the file is contiguous / 3 | /----------------------------------------------------------------------*/ 4 | 5 | FRESULT test_contiguous_file ( 6 | FIL* fp, /* [IN] Open file object to be checked */ 7 | int* cont /* [OUT] 1:Contiguous, 0:Fragmented or zero-length */ 8 | ) 9 | { 10 | DWORD clst, clsz, step; 11 | FSIZE_t fsz; 12 | FRESULT fr; 13 | 14 | 15 | *cont = 0; 16 | fr = f_rewind(fp); /* Validates and prepares the file */ 17 | if (fr != FR_OK) return fr; 18 | 19 | #if FF_MAX_SS == FF_MIN_SS 20 | clsz = (DWORD)fp->obj.fs->csize * FF_MAX_SS; /* Cluster size */ 21 | #else 22 | clsz = (DWORD)fp->obj.fs->csize * fp->obj.fs->ssize; 23 | #endif 24 | fsz = f_size(fp); 25 | if (fsz > 0) { 26 | clst = fp->obj.sclust - 1; /* A cluster leading the first cluster for first test */ 27 | while (fsz) { 28 | step = (fsz >= clsz) ? clsz : (DWORD)fsz; 29 | fr = f_lseek(fp, f_tell(fp) + step); /* Advances file pointer a cluster */ 30 | if (fr != FR_OK) return fr; 31 | if (clst + 1 != fp->clust) break; /* Is not the cluster next to previous one? */ 32 | clst = fp->clust; fsz -= step; /* Get current cluster for next test */ 33 | } 34 | if (fsz == 0) *cont = 1; /* All done without fail? */ 35 | } 36 | 37 | return FR_OK; 38 | } 39 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/app6.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------*/ 2 | /* Raw Read/Write Throughput Checker */ 3 | /*---------------------------------------------------------------------*/ 4 | 5 | #include 6 | #include 7 | #include "diskio.h" 8 | #include "ff.h" 9 | 10 | 11 | int test_raw_speed ( 12 | BYTE pdrv, /* Physical drive number */ 13 | DWORD lba, /* Start LBA for read/write test */ 14 | DWORD len, /* Number of bytes to read/write (must be multiple of sz_buff) */ 15 | void* buff, /* Read/write buffer */ 16 | UINT sz_buff /* Size of read/write buffer (must be multiple of FF_MAX_SS) */ 17 | ) 18 | { 19 | WORD ss; 20 | DWORD ofs, tmr; 21 | 22 | 23 | #if FF_MIN_SS != FF_MAX_SS 24 | if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) { 25 | printf("\ndisk_ioctl() failed.\n"); 26 | return 0; 27 | } 28 | #else 29 | ss = FF_MAX_SS; 30 | #endif 31 | 32 | printf("Starting raw write test at sector %lu in %u bytes of data chunks...", lba, sz_buff); 33 | tmr = systimer(); 34 | for (ofs = 0; ofs < len / ss; ofs += sz_buff / ss) { 35 | if (disk_write(pdrv, buff, lba + ofs, sz_buff / ss) != RES_OK) { 36 | printf("\ndisk_write() failed.\n"); 37 | return 0; 38 | } 39 | } 40 | if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) { 41 | printf("\ndisk_ioctl() failed.\n"); 42 | return 0; 43 | } 44 | tmr = systimer() - tmr; 45 | printf("\n%lu bytes written and it took %lu timer ticks.\n", len, tmr); 46 | 47 | printf("Starting raw read test at sector %lu in %u bytes of data chunks...", lba, sz_buff); 48 | tmr = systimer(); 49 | for (ofs = 0; ofs < len / ss; ofs += sz_buff / ss) { 50 | if (disk_read(pdrv, buff, lba + ofs, sz_buff / ss) != RES_OK) { 51 | printf("\ndisk_read() failed.\n"); 52 | return 0; 53 | } 54 | } 55 | tmr = systimer() - tmr; 56 | printf("\n%lu bytes read and it took %lu timer ticks.\n", len, tmr); 57 | 58 | printf("Test completed.\n"); 59 | return 1; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/f1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/f1.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/f2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/f2.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/f3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/f3.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/f4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/f4.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/f5.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/f6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/f6.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/f7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/f7.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/funcs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/funcs.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/layers.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/layers1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/layers1.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/layers2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/layers2.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/layers3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/layers3.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/mkfatimg.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/mkfatimg.zip -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/mkfs.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/mkfs.xlsx -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/modules.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/modules.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/rwtest1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/rwtest1.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/rwtest2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/rwtest2.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/rwtest3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/rwtest3.png -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/documents/res/uniconv.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2040/lib/fatfs/documents/res/uniconv.zip -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/source/00readme.txt: -------------------------------------------------------------------------------- 1 | FatFs Module Source Files R0.15 2 | 3 | 4 | FILES 5 | 6 | 00readme.txt This file. 7 | 00history.txt Revision history. 8 | ff.c FatFs module. 9 | ffconf.h Configuration file of FatFs module. 10 | ff.h Common include file for FatFs and application module. 11 | diskio.h Common include file for FatFs and disk I/O module. 12 | diskio.c An example of glue function to attach existing disk I/O module to FatFs. 13 | ffunicode.c Optional Unicode utility functions. 14 | ffsystem.c An example of optional O/S related functions. 15 | 16 | 17 | Low level disk I/O module is not included in this archive because the FatFs 18 | module is only a generic file system layer and it does not depend on any specific 19 | storage device. You need to provide a low level disk I/O module written to 20 | control the storage device that attached to the target system. 21 | 22 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/source/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | 3 | add_library(fatfs INTERFACE) 4 | target_sources(fatfs INTERFACE 5 | ${CMAKE_CURRENT_LIST_DIR}/ff.c 6 | ${CMAKE_CURRENT_LIST_DIR}/ffsystem.c 7 | ${CMAKE_CURRENT_LIST_DIR}/ffunicode.c 8 | ) 9 | target_include_directories(fatfs INTERFACE ${CMAKE_CURRENT_LIST_DIR}) 10 | -------------------------------------------------------------------------------- /platforms/rp2040/lib/fatfs/source/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------/ 2 | / Low level disk interface modlue include file (C)ChaN, 2019 / 3 | /-----------------------------------------------------------------------*/ 4 | 5 | #ifndef _DISKIO_DEFINED 6 | #define _DISKIO_DEFINED 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | /* Status of Disk Functions */ 13 | typedef BYTE DSTATUS; 14 | 15 | /* Results of Disk Functions */ 16 | typedef enum { 17 | RES_OK = 0, /* 0: Successful */ 18 | RES_ERROR, /* 1: R/W Error */ 19 | RES_WRPRT, /* 2: Write Protected */ 20 | RES_NOTRDY, /* 3: Not Ready */ 21 | RES_PARERR /* 4: Invalid Parameter */ 22 | } DRESULT; 23 | 24 | 25 | /*---------------------------------------*/ 26 | /* Prototypes for disk control functions */ 27 | 28 | 29 | DSTATUS disk_initialize (BYTE pdrv); 30 | DSTATUS disk_status (BYTE pdrv); 31 | DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count); 32 | DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count); 33 | DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); 34 | 35 | 36 | /* Disk Status Bits (DSTATUS) */ 37 | 38 | #define STA_NOINIT 0x01 /* Drive not initialized */ 39 | #define STA_NODISK 0x02 /* No medium in the drive */ 40 | #define STA_PROTECT 0x04 /* Write protected */ 41 | 42 | 43 | /* Command code for disk_ioctrl fucntion */ 44 | 45 | /* Generic command (Used by FatFs) */ 46 | #define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */ 47 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */ 48 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */ 49 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */ 50 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */ 51 | 52 | /* Generic command (Not used by FatFs) */ 53 | #define CTRL_POWER 5 /* Get/Set power status */ 54 | #define CTRL_LOCK 6 /* Lock/Unlock media removal */ 55 | #define CTRL_EJECT 7 /* Eject media */ 56 | #define CTRL_FORMAT 8 /* Create physical format on the media */ 57 | 58 | /* MMC/SDC specific ioctl command */ 59 | #define MMC_GET_TYPE 10 /* Get card type */ 60 | #define MMC_GET_CSD 11 /* Get CSD */ 61 | #define MMC_GET_CID 12 /* Get CID */ 62 | #define MMC_GET_OCR 13 /* Get OCR */ 63 | #define MMC_GET_SDSTAT 14 /* Get SD status */ 64 | #define ISDIO_READ 55 /* Read data form SD iSDIO register */ 65 | #define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ 66 | #define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ 67 | 68 | /* ATA/CF specific ioctl command */ 69 | #define ATA_GET_REV 20 /* Get F/W revision */ 70 | #define ATA_GET_MODEL 21 /* Get model name */ 71 | #define ATA_GET_SN 22 /* Get serial number */ 72 | 73 | #ifdef __cplusplus 74 | } 75 | #endif 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /platforms/rp2040/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 | -------------------------------------------------------------------------------- /platforms/rp2040/src/audio.h: -------------------------------------------------------------------------------- 1 | #ifndef AUDIO_H_FILE 2 | #define AUDIO_H_FILE 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #if defined(OLIMEX_NEO6502) || defined(OLIMEX_RP2040PC) 11 | #define _AUDIO_PIN (20) 12 | #else 13 | #define _AUDIO_PIN (8) 14 | #endif 15 | 16 | void audio_init(uint8_t audio_pin, uint16_t sample_freq); 17 | void audio_push_sample(const uint8_t sample); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif // AUDIO_H_FILE 24 | -------------------------------------------------------------------------------- /platforms/rp2040/src/msc_app.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "tusb.h" 3 | #include "ff.h" 4 | #include "diskio.h" 5 | 6 | static FATFS msc_fatfs_volumes[CFG_TUH_DEVICE_MAX]; 7 | static volatile bool msc_volume_busy[CFG_TUH_DEVICE_MAX]; 8 | static scsi_inquiry_resp_t msc_inquiry_resp; 9 | 10 | bool msc_inquiry_complete = false; 11 | 12 | bool inquiry_complete_cb(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { 13 | if (cb_data->csw->status != 0) { 14 | printf("MSC SCSI inquiry failed\r\n"); 15 | return false; 16 | } 17 | 18 | uint32_t block_count = tuh_msc_get_block_count(dev_addr, cb_data->cbw->lun); 19 | uint32_t block_size = tuh_msc_get_block_size(dev_addr, cb_data->cbw->lun); 20 | uint32_t size = block_count / ((1024 * 1024) / block_size); 21 | 22 | printf("MSC %luMB %.8s %.16s rev %.4s\r\n", size, msc_inquiry_resp.vendor_id, msc_inquiry_resp.product_id, 23 | msc_inquiry_resp.product_rev); 24 | 25 | char drive_path[3] = "0:"; 26 | drive_path[0] += dev_addr; 27 | FRESULT result = f_mount(&msc_fatfs_volumes[dev_addr], drive_path, 1); 28 | if (result != FR_OK) { 29 | printf("MSC filesystem mount failed (%d)\r\n", result); 30 | return false; 31 | } 32 | 33 | char s[2]; 34 | if (FR_OK != f_getcwd(s, 2)) { 35 | f_chdrive(drive_path); 36 | f_chdir("/"); 37 | } 38 | 39 | msc_inquiry_complete = true; 40 | 41 | return true; 42 | } 43 | 44 | void tuh_msc_mount_cb(uint8_t dev_addr) { 45 | uint8_t const lun = 0; 46 | printf("MSC mounted, inquiring\r\n"); 47 | tuh_msc_inquiry(dev_addr, lun, &msc_inquiry_resp, inquiry_complete_cb, 0); 48 | } 49 | 50 | void tuh_msc_umount_cb(uint8_t dev_addr) { 51 | char drive_path[3] = "0:"; 52 | drive_path[0] += dev_addr; 53 | f_unmount(drive_path); 54 | } 55 | 56 | static void wait_for_disk_io(BYTE pdrv) { 57 | while (msc_volume_busy[pdrv]) { 58 | tuh_task(); 59 | }; 60 | } 61 | 62 | static bool disk_io_complete(uint8_t dev_addr, tuh_msc_complete_data_t const *cb_data) { 63 | (void)cb_data; 64 | msc_volume_busy[dev_addr] = false; 65 | return true; 66 | } 67 | 68 | DSTATUS disk_status(BYTE pdrv) { 69 | uint8_t dev_addr = pdrv; 70 | return tuh_msc_mounted(dev_addr) ? 0 : STA_NODISK; 71 | } 72 | 73 | DSTATUS disk_initialize(BYTE pdrv) { 74 | (void)(pdrv); 75 | return 0; 76 | } 77 | 78 | DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) { 79 | uint8_t const dev_addr = pdrv; 80 | uint8_t const lun = 0; 81 | msc_volume_busy[pdrv] = true; 82 | tuh_msc_read10(dev_addr, lun, buff, sector, (uint16_t)count, disk_io_complete, 0); 83 | wait_for_disk_io(pdrv); 84 | return RES_OK; 85 | } 86 | 87 | DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count) { 88 | uint8_t const dev_addr = pdrv; 89 | uint8_t const lun = 0; 90 | msc_volume_busy[pdrv] = true; 91 | tuh_msc_write10(dev_addr, lun, buff, sector, (uint16_t)count, disk_io_complete, 0); 92 | wait_for_disk_io(pdrv); 93 | return RES_OK; 94 | } 95 | 96 | DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) { 97 | uint8_t const dev_addr = pdrv; 98 | uint8_t const lun = 0; 99 | switch (cmd) { 100 | case CTRL_SYNC: 101 | return RES_OK; 102 | case GET_SECTOR_COUNT: 103 | *((DWORD *)buff) = (WORD)tuh_msc_get_block_count(dev_addr, lun); 104 | return RES_OK; 105 | case GET_SECTOR_SIZE: 106 | *((WORD *)buff) = (WORD)tuh_msc_get_block_size(dev_addr, lun); 107 | return RES_OK; 108 | case GET_BLOCK_SIZE: 109 | *((DWORD *)buff) = 1; // 1 sector 110 | return RES_OK; 111 | default: 112 | return RES_PARERR; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /platforms/rp2040/src/tusb_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _TUSB_CONFIG_H_ 2 | #define _TUSB_CONFIG_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | //-------------------------------------------------------------------- 9 | // COMMON CONFIGURATION 10 | //-------------------------------------------------------------------- 11 | 12 | // defined by compiler flags for flexibility 13 | #ifndef CFG_TUSB_MCU 14 | #error CFG_TUSB_MCU must be defined 15 | #endif 16 | 17 | #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX 18 | #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) 19 | #else 20 | #define CFG_TUSB_RHPORT0_MODE OPT_MODE_HOST 21 | #endif 22 | 23 | #ifndef CFG_TUSB_OS 24 | #define CFG_TUSB_OS OPT_OS_NONE 25 | #endif 26 | 27 | // CFG_TUSB_DEBUG is defined by compiler in DEBUG build 28 | // #define CFG_TUSB_DEBUG 0 29 | 30 | // USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. 31 | // Tinyusb use follows macros to declare transferring memory so that they can be put 32 | // into those specific section. 33 | // e.g 34 | // - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) 35 | // - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) 36 | 37 | #ifndef CFG_TUSB_MEM_SECTION 38 | #define CFG_TUSB_MEM_SECTION 39 | #endif 40 | 41 | #ifndef CFG_TUSB_MEM_ALIGN 42 | #define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) 43 | #endif 44 | 45 | //-------------------------------------------------------------------- 46 | // CONFIGURATION 47 | //-------------------------------------------------------------------- 48 | 49 | // Size of buffer to hold descriptors and other data used for enumeration 50 | #define CFG_TUH_ENUMERATION_BUFSIZE 256 51 | 52 | #define CFG_TUH_HUB 1 53 | #define CFG_TUH_CDC 0 54 | #define CFG_TUH_HID 4 // Typical keyboard + mouse device can have 3-4 HID interfaces 55 | #define CFG_TUH_MIDI 0 // There will be at most one MIDIStreaming Interface descriptor 56 | #define CFG_TUH_MSC 1 57 | #define CFG_TUH_VENDOR 0 58 | 59 | // Max device support (excluding hub device) 60 | #define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 5 : 1) // Hub typically has 4 ports 61 | 62 | //------------- HID -------------// 63 | #define CFG_TUH_HID_EPIN_BUFSIZE 64 64 | #define CFG_TUH_HID_EPOUT_BUFSIZE 64 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif 69 | 70 | #endif // _TUSB_CONFIG_H_ 71 | -------------------------------------------------------------------------------- /platforms/rp2040/systems/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(apple2) 2 | add_subdirectory(apple2e) 3 | add_subdirectory(oric) 4 | -------------------------------------------------------------------------------- /platforms/rp2040/systems/apple2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Replace TMDS with 10 bit UART (same baud rate): 2 | # add_definitions(-DDVI_SERIAL_DEBUG=1) 3 | # add_definitions(-DRUN_FROM_CRYSTAL) 4 | 5 | add_executable(apple2 6 | ${CMAKE_CURRENT_SOURCE_DIR}/src/apple2.c 7 | ${CMAKE_CURRENT_SOURCE_DIR}/src/utils.S 8 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/hid_app.c 9 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/msc_app.c 10 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/audio.c 11 | ) 12 | 13 | target_compile_options(apple2 PRIVATE -Wall) 14 | 15 | target_compile_definitions(apple2 PRIVATE 16 | # DVI_DEFAULT_SERIAL_CONFIG=pico_sock_cfg 17 | DVI_DEFAULT_SERIAL_CONFIG=olimex_neo6502_cfg 18 | # DVI_DEFAULT_SERIAL_CONFIG=olimex_rp2040pc_cfg 19 | # DVI_DEFAULT_SERIAL_CONFIG=pico_zero_cfg 20 | ) 21 | 22 | target_link_libraries(apple2 23 | pico_stdlib 24 | pico_multicore 25 | pico_util 26 | libdvi 27 | tinyusb_host 28 | fatfs 29 | ) 30 | 31 | # create map/bin/hex file etc. 32 | pico_add_extra_outputs(apple2) 33 | 34 | pico_enable_stdio_usb(apple2 0) 35 | pico_enable_stdio_uart(apple2 1) 36 | -------------------------------------------------------------------------------- /platforms/rp2040/systems/apple2/src/utils.S: -------------------------------------------------------------------------------- 1 | #include "pico/config.h" 2 | #include "hardware/regs/addressmap.h" 3 | #include "hardware/regs/sio.h" 4 | 5 | // Offsets suitable for ldr/str (must be <= 0x7c): 6 | #define ACCUM0_OFFS (SIO_INTERP0_ACCUM0_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 7 | #define ACCUM1_OFFS (SIO_INTERP0_ACCUM1_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 8 | #define POP0_OFFS (SIO_INTERP0_POP_LANE0_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 9 | 10 | .syntax unified 11 | .cpu cortex-m0plus 12 | .thumb 13 | 14 | .macro decl_func_x name 15 | .section .scratch_x.\name, "ax" 16 | .global \name 17 | .type \name,%function 18 | .thumb_func 19 | \name: 20 | .endm 21 | 22 | .macro decl_func_y name 23 | .section .scratch_y.\name, "ax" 24 | .global \name 25 | .type \name,%function 26 | .thumb_func 27 | \name: 28 | .endm 29 | 30 | #define decl_func decl_func_x 31 | 32 | .macro decode_pixel_data rd 33 | ldr \rd, [r2, #POP0_OFFS] 34 | lsls \rd, #8 35 | ldr r7, [r2, #POP0_OFFS] 36 | orrs \rd, r7 37 | ldr r7, [r2, #POP0_OFFS] 38 | lsls r7, #24 39 | orrs \rd, r7 40 | ldr r7, [r2, #POP0_OFFS] 41 | lsls r7, #16 42 | orrs \rd, r7 43 | .endm 44 | 45 | decl_func apple2_render_scanline 46 | push {r3-r7, lr} 47 | 48 | lsls r2, #1 49 | add r2, r1 50 | mov ip, r2 51 | ldr r2, =(SIO_BASE + SIO_INTERP0_ACCUM0_OFFSET) 52 | 53 | .align 2 54 | 1: 55 | ldmia r0!, {r7} 56 | str r7, [r2, #ACCUM0_OFFS] 57 | str r7, [r2, #ACCUM1_OFFS] 58 | decode_pixel_data r3 59 | decode_pixel_data r4 60 | stmia r1!, {r3, r4} 61 | cmp r1, ip 62 | bne 1b 63 | 64 | pop {r3-r7, pc} 65 | 66 | // 67 | decl_func copy_tmdsbuf 68 | push {r2-r7, lr} 69 | 70 | #ifdef OLIMEX_NEO6502 71 | .rept 160 72 | #else 73 | .rept 200 74 | #endif 75 | ldmia r1!, {r2, r3, r4, r5, r6, r7} 76 | stmia r0!, {r2, r3, r4, r5, r6, r7} 77 | .endr 78 | 79 | pop {r2-r7, pc} 80 | -------------------------------------------------------------------------------- /platforms/rp2040/systems/apple2e/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Replace TMDS with 10 bit UART (same baud rate): 2 | # add_definitions(-DDVI_SERIAL_DEBUG=1) 3 | # add_definitions(-DRUN_FROM_CRYSTAL) 4 | 5 | add_executable(apple2e 6 | ${CMAKE_CURRENT_SOURCE_DIR}/src/apple2e.c 7 | ${CMAKE_CURRENT_SOURCE_DIR}/src/utils.S 8 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/hid_app.c 9 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/msc_app.c 10 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/audio.c 11 | ) 12 | 13 | target_compile_options(apple2e PRIVATE -Wall) 14 | 15 | target_compile_definitions(apple2e PRIVATE 16 | # DVI_DEFAULT_SERIAL_CONFIG=pico_sock_cfg 17 | DVI_DEFAULT_SERIAL_CONFIG=olimex_neo6502_cfg 18 | # DVI_DEFAULT_SERIAL_CONFIG=olimex_rp2040pc_cfg 19 | # DVI_DEFAULT_SERIAL_CONFIG=pico_zero_cfg 20 | ) 21 | 22 | target_link_libraries(apple2e 23 | pico_stdlib 24 | pico_multicore 25 | pico_util 26 | libdvi 27 | tinyusb_host 28 | fatfs 29 | ) 30 | 31 | # create map/bin/hex file etc. 32 | pico_add_extra_outputs(apple2e) 33 | 34 | pico_enable_stdio_usb(apple2e 0) 35 | pico_enable_stdio_uart(apple2e 1) 36 | -------------------------------------------------------------------------------- /platforms/rp2040/systems/apple2e/src/utils.S: -------------------------------------------------------------------------------- 1 | #include "pico/config.h" 2 | #include "hardware/regs/addressmap.h" 3 | #include "hardware/regs/sio.h" 4 | 5 | // Offsets suitable for ldr/str (must be <= 0x7c): 6 | #define ACCUM0_OFFS (SIO_INTERP0_ACCUM0_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 7 | #define ACCUM1_OFFS (SIO_INTERP0_ACCUM1_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 8 | #define POP0_OFFS (SIO_INTERP0_POP_LANE0_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 9 | 10 | .syntax unified 11 | .cpu cortex-m0plus 12 | .thumb 13 | 14 | .macro decl_func_x name 15 | .section .scratch_x.\name, "ax" 16 | .global \name 17 | .type \name,%function 18 | .thumb_func 19 | \name: 20 | .endm 21 | 22 | .macro decl_func_y name 23 | .section .scratch_y.\name, "ax" 24 | .global \name 25 | .type \name,%function 26 | .thumb_func 27 | \name: 28 | .endm 29 | 30 | #define decl_func decl_func_x 31 | 32 | .macro decode_pixel_data rd 33 | ldr \rd, [r2, #POP0_OFFS] 34 | lsls \rd, #8 35 | ldr r7, [r2, #POP0_OFFS] 36 | orrs \rd, r7 37 | ldr r7, [r2, #POP0_OFFS] 38 | lsls r7, #24 39 | orrs \rd, r7 40 | ldr r7, [r2, #POP0_OFFS] 41 | lsls r7, #16 42 | orrs \rd, r7 43 | .endm 44 | 45 | decl_func apple2e_render_scanline 46 | push {r3-r7, lr} 47 | 48 | lsls r2, #1 49 | add r2, r1 50 | mov ip, r2 51 | ldr r2, =(SIO_BASE + SIO_INTERP0_ACCUM0_OFFSET) 52 | 53 | .align 2 54 | 1: 55 | ldmia r0!, {r7} 56 | str r7, [r2, #ACCUM0_OFFS] 57 | str r7, [r2, #ACCUM1_OFFS] 58 | decode_pixel_data r3 59 | decode_pixel_data r4 60 | stmia r1!, {r3, r4} 61 | cmp r1, ip 62 | bne 1b 63 | 64 | pop {r3-r7, pc} 65 | 66 | // 67 | decl_func copy_tmdsbuf 68 | push {r2-r7, lr} 69 | 70 | #ifdef OLIMEX_NEO6502 71 | .rept 200 72 | #else 73 | .rept 200 74 | #endif 75 | ldmia r1!, {r2, r3, r4, r5, r6, r7} 76 | stmia r0!, {r2, r3, r4, r5, r6, r7} 77 | .endr 78 | 79 | pop {r2-r7, pc} 80 | -------------------------------------------------------------------------------- /platforms/rp2040/systems/oric/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Replace TMDS with 10 bit UART (same baud rate): 2 | # add_definitions(-DDVI_SERIAL_DEBUG=1) 3 | # add_definitions(-DRUN_FROM_CRYSTAL) 4 | 5 | add_executable(oric 6 | ${CMAKE_CURRENT_SOURCE_DIR}/src/oric.c 7 | ${CMAKE_CURRENT_SOURCE_DIR}/src/utils.S 8 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/hid_app.c 9 | ${CMAKE_CURRENT_SOURCE_DIR}/../../src/audio.c 10 | ) 11 | 12 | target_compile_options(oric PRIVATE -Wall) 13 | 14 | target_compile_definitions(oric PRIVATE 15 | # DVI_DEFAULT_SERIAL_CONFIG=pico_sock_cfg 16 | DVI_DEFAULT_SERIAL_CONFIG=olimex_neo6502_cfg 17 | # DVI_DEFAULT_SERIAL_CONFIG=olimex_rp2040pc_cfg 18 | # DVI_DEFAULT_SERIAL_CONFIG=pico_zero_cfg 19 | ) 20 | 21 | target_link_libraries(oric 22 | pico_stdlib 23 | pico_multicore 24 | pico_util 25 | libdvi 26 | tinyusb_host 27 | ) 28 | 29 | # create map/bin/hex file etc. 30 | pico_add_extra_outputs(oric) 31 | 32 | pico_enable_stdio_usb(oric 0) 33 | pico_enable_stdio_uart(oric 1) 34 | -------------------------------------------------------------------------------- /platforms/rp2040/systems/oric/src/utils.S: -------------------------------------------------------------------------------- 1 | #include "pico/config.h" 2 | #include "hardware/regs/addressmap.h" 3 | #include "hardware/regs/sio.h" 4 | 5 | // Offsets suitable for ldr/str (must be <= 0x7c): 6 | #define ACCUM0_OFFS (SIO_INTERP0_ACCUM0_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 7 | #define ACCUM1_OFFS (SIO_INTERP0_ACCUM1_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 8 | #define POP0_OFFS (SIO_INTERP0_POP_LANE0_OFFSET - SIO_INTERP0_ACCUM0_OFFSET) 9 | 10 | .syntax unified 11 | .cpu cortex-m0plus 12 | .thumb 13 | 14 | .macro decl_func_x name 15 | .section .scratch_x.\name, "ax" 16 | .global \name 17 | .type \name,%function 18 | .thumb_func 19 | \name: 20 | .endm 21 | 22 | .macro decl_func_y name 23 | .section .scratch_y.\name, "ax" 24 | .global \name 25 | .type \name,%function 26 | .thumb_func 27 | \name: 28 | .endm 29 | 30 | #define decl_func decl_func_x 31 | 32 | // 33 | .macro decode_pixel_data_3x rd1, rd2, rd3 34 | ldr r7, [r2, #POP0_OFFS] 35 | mov \rd2, r7 36 | lsls r7, #8 37 | orrs \rd2, r7 38 | lsls r7, #16 39 | mov \rd1, r7 40 | ldr r7, [r2, #POP0_OFFS] 41 | orrs \rd1, r7 42 | lsls r7, #8 43 | orrs \rd1, r7 44 | lsls r7, #8 45 | orrs \rd1, r7 46 | ldr r7, [r2, #POP0_OFFS] 47 | lsls r7, #8 48 | mov \rd3, r7 49 | lsls r7, #8 50 | orrs \rd3, r7 51 | lsls r7, #8 52 | orrs \rd3, r7 53 | ldr r7, [r2, #POP0_OFFS] 54 | orrs \rd3, r7 55 | lsls r7, #16 56 | orrs \rd2, r7 57 | lsls r7, #8 58 | orrs \rd2, r7 59 | .endm 60 | 61 | decl_func oric_render_scanline_3x 62 | push {r3-r7, lr} 63 | 64 | lsls r2, #1 65 | mov r3, r2 66 | lsls r2, #1 67 | add r2, r3 68 | add r2, r1 69 | mov ip, r2 70 | ldr r2, =(SIO_BASE + SIO_INTERP0_ACCUM0_OFFSET) 71 | 72 | .align 2 73 | 1: 74 | ldmia r0!, {r7} 75 | str r7, [r2, #ACCUM0_OFFS] 76 | str r7, [r2, #ACCUM1_OFFS] 77 | decode_pixel_data_3x r3, r4, r5 78 | stmia r1!, {r3, r4, r5} 79 | decode_pixel_data_3x r3, r4, r5 80 | stmia r1!, {r3, r4, r5} 81 | cmp r1, ip 82 | bne 1b 83 | 84 | pop {r3-r7, pc} 85 | 86 | // 87 | .macro decode_pixel_data_2x rd 88 | ldr r7, [r2, #POP0_OFFS] 89 | lsls r7, #16 90 | mov \rd, r7 91 | lsls r7, #8 92 | orrs \rd, r7 93 | ldr r7, [r2, #POP0_OFFS] 94 | orrs \rd, r7 95 | lsls r7, #8 96 | orrs \rd, r7 97 | .endm 98 | 99 | decl_func oric_render_scanline_2x 100 | push {r3-r7, lr} 101 | 102 | lsls r2, #2 103 | add r2, r1 104 | mov ip, r2 105 | ldr r2, =(SIO_BASE + SIO_INTERP0_ACCUM0_OFFSET) 106 | 107 | .align 2 108 | 1: 109 | ldmia r0!, {r7} 110 | str r7, [r2, #ACCUM0_OFFS] 111 | str r7, [r2, #ACCUM1_OFFS] 112 | decode_pixel_data_2x r3 113 | decode_pixel_data_2x r4 114 | decode_pixel_data_2x r5 115 | decode_pixel_data_2x r6 116 | stmia r1!, {r3, r4, r5, r6} 117 | cmp r1, ip 118 | bne 1b 119 | 120 | pop {r3-r7, pc} 121 | 122 | // 123 | decl_func copy_tmdsbuf 124 | push {r2-r7, lr} 125 | 126 | #ifdef OLIMEX_NEO6502 127 | .rept 200 128 | #else 129 | .rept 240 130 | #endif 131 | ldmia r1!, {r2, r3, r4, r5, r6, r7} 132 | stmia r0!, {r2, r3, r4, r5, r6, r7} 133 | .endr 134 | 135 | pop {r2-r7, pc} 136 | -------------------------------------------------------------------------------- /platforms/rp2350/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vsladkov/reload-emulator/d24a7eaf53524332dc56a25d3e4b3adcb700e0d8/platforms/rp2350/.keep -------------------------------------------------------------------------------- /src/chips/beeper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // beeper.h 4 | // 5 | // Simple square-wave beeper 6 | // 7 | // ## zlib/libpng license 8 | // 9 | // Copyright (c) 2018 Andre Weissflog 10 | // This software is provided 'as-is', without any express or implied warranty. 11 | // In no event will the authors be held liable for any damages arising from the 12 | // use of this software. 13 | // Permission is granted to anyone to use this software for any purpose, 14 | // including commercial applications, and to alter it and redistribute it 15 | // freely, subject to the following restrictions: 16 | // 1. The origin of this software must not be misrepresented; you must not 17 | // claim that you wrote the original software. If you use this software in a 18 | // product, an acknowledgment in the product documentation would be 19 | // appreciated but is not required. 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | 25 | #include 26 | #include 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | // Error-accumulation precision boost 33 | #define BEEPER_FIXEDPOINT_SCALE (16) 34 | // DC adjust buffer size 35 | #define BEEPER_DCADJ_BUFLEN (512) 36 | 37 | // Initialization parameters 38 | typedef struct { 39 | int tick_hz; 40 | int sound_hz; 41 | float base_volume; 42 | } beeper_desc_t; 43 | 44 | // Beeper state 45 | typedef struct { 46 | int state; 47 | int period; 48 | int counter; 49 | float base_volume; 50 | float volume; 51 | float sample; 52 | float dcadj_sum; 53 | uint32_t dcadj_pos; 54 | float dcadj_buf[BEEPER_DCADJ_BUFLEN]; 55 | } beeper_t; 56 | 57 | // Initialize beeper instance 58 | void beeper_init(beeper_t* beeper, const beeper_desc_t* desc); 59 | // Reset the beeper instance 60 | void beeper_reset(beeper_t* beeper); 61 | // Set current on/off state 62 | static inline void beeper_set(beeper_t* beeper, bool state) { beeper->state = state ? 1 : 0; } 63 | // Toggle current state (on->off or off->on) 64 | static inline void beeper_toggle(beeper_t* beeper) { beeper->state = !beeper->state; } 65 | // Set current volume 0.0 to 1.0 66 | static inline void beeper_set_volume(beeper_t* beeper, float vol) { beeper->volume = vol; } 67 | // Tick the beeper, return true if a new sample is ready 68 | bool beeper_tick(beeper_t* beeper); 69 | 70 | #ifdef __cplusplus 71 | } // extern "C" 72 | #endif 73 | /*-- IMPLEMENTATION ----------------------------------------------------------*/ 74 | #ifdef CHIPS_IMPL 75 | #include 76 | #ifndef CHIPS_ASSERT 77 | #include 78 | #define CHIPS_ASSERT(c) assert(c) 79 | #endif 80 | 81 | void beeper_init(beeper_t* b, const beeper_desc_t* desc) { 82 | CHIPS_ASSERT(b && desc); 83 | CHIPS_ASSERT((desc->tick_hz > 0) && (desc->sound_hz > 0)); 84 | *b = (beeper_t){ 85 | .period = (desc->tick_hz * BEEPER_FIXEDPOINT_SCALE) / desc->sound_hz, 86 | .counter = b->period, 87 | .base_volume = desc->base_volume, 88 | .volume = 1.0f, 89 | }; 90 | } 91 | 92 | void beeper_reset(beeper_t* b) { 93 | CHIPS_ASSERT(b); 94 | b->state = 0; 95 | b->counter = b->period; 96 | b->sample = 0; 97 | } 98 | 99 | // DC adjustment filter from StSound, this moves an "offcenter" 100 | // signal back to the zero-line (e.g. the volume-level output 101 | // from the chip simulation which is >0.0 gets converted to 102 | // a +/- sample value) 103 | 104 | static float _beeper_dcadjust(beeper_t* bp, float s) { 105 | bp->dcadj_sum -= bp->dcadj_buf[bp->dcadj_pos]; 106 | bp->dcadj_sum += s; 107 | bp->dcadj_buf[bp->dcadj_pos] = s; 108 | bp->dcadj_pos = (bp->dcadj_pos + 1) & (BEEPER_DCADJ_BUFLEN - 1); 109 | return s - (bp->dcadj_sum / BEEPER_DCADJ_BUFLEN); 110 | } 111 | 112 | bool beeper_tick(beeper_t* bp) { 113 | // Generate a new sample? 114 | bp->counter -= BEEPER_FIXEDPOINT_SCALE; 115 | if (bp->counter <= 0) { 116 | bp->counter += bp->period; 117 | // bp->sample = _beeper_dcadjust(bp, (float)bp->state * bp->volume * bp->base_volume); 118 | bp->sample = (float)bp->state * bp->volume * bp->base_volume; 119 | return true; 120 | } 121 | return false; 122 | } 123 | 124 | #endif // CHIPS_IMPL 125 | -------------------------------------------------------------------------------- /src/chips/chips_common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // chips_common.h 4 | // 5 | // Common data types for chips system headers. 6 | // 7 | // ## zlib/libpng license 8 | // 9 | // Copyright (c) 2018 Andre Weissflog 10 | // This software is provided 'as-is', without any express or implied warranty. 11 | // In no event will the authors be held liable for any damages arising from the 12 | // use of this software. 13 | // Permission is granted to anyone to use this software for any purpose, 14 | // including commercial applications, and to alter it and redistribute it 15 | // freely, subject to the following restrictions: 16 | // 1. The origin of this software must not be misrepresented; you must not 17 | // claim that you wrote the original software. If you use this software in a 18 | // product, an acknowledgment in the product documentation would be 19 | // appreciated but is not required. 20 | // 2. Altered source versions must be plainly marked as such, and must not 21 | // be misrepresented as being the original software. 22 | // 3. This notice may not be removed or altered from any source 23 | // distribution. 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #define CHIPS_DEFAULT(val, def) (((val) != 0) ? (val) : (def)) 34 | 35 | #define CHIPS_ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 36 | 37 | typedef struct { 38 | void* ptr; 39 | size_t size; 40 | } chips_range_t; 41 | 42 | typedef struct { 43 | int width, height; 44 | } chips_dim_t; 45 | 46 | typedef struct { 47 | int x, y, width, height; 48 | } chips_rect_t; 49 | 50 | typedef struct { 51 | struct { 52 | chips_dim_t dim; // Framebuffer dimensions in pixels 53 | chips_range_t buffer; 54 | size_t bytes_per_pixel; // 1 or 4 55 | } frame; 56 | chips_rect_t screen; 57 | chips_range_t palette; 58 | bool portrait; 59 | } chips_display_info_t; 60 | 61 | typedef struct { 62 | void (*func)(const uint8_t sample, void* user_data); 63 | void* user_data; 64 | } chips_audio_callback_t; 65 | 66 | typedef void (*chips_debug_func_t)(void* user_data, uint64_t pins); 67 | typedef struct { 68 | struct { 69 | chips_debug_func_t func; 70 | void* user_data; 71 | } callback; 72 | bool* stopped; 73 | } chips_debug_t; 74 | 75 | typedef struct { 76 | chips_audio_callback_t callback; 77 | int sample_rate; 78 | float volume; 79 | } chips_audio_desc_t; 80 | 81 | // Prepare chips_audio_t snapshot for saving 82 | void chips_audio_callback_snapshot_onsave(chips_audio_callback_t* snapshot); 83 | // Fixup chips_audio_t snapshot after loading 84 | void chips_audio_callback_snapshot_onload(chips_audio_callback_t* snapshot, chips_audio_callback_t* sys); 85 | // Prepare chips_debut_t snapshot for saving 86 | void chips_debug_snapshot_onsave(chips_debug_t* snapshot); 87 | // Fixup chips_debug_t snapshot after loading 88 | void chips_debug_snapshot_onload(chips_debug_t* snapshot, chips_debug_t* sys); 89 | 90 | #ifdef __cplusplus 91 | } // extern "C" 92 | #endif 93 | 94 | /*--- IMPLEMENTATION ---------------------------------------------------------*/ 95 | #ifdef CHIPS_IMPL 96 | 97 | void chips_audio_callback_snapshot_onsave(chips_audio_callback_t* snapshot) { 98 | snapshot->func = 0; 99 | snapshot->user_data = 0; 100 | } 101 | 102 | void chips_audio_callback_snapshot_onload(chips_audio_callback_t* snapshot, chips_audio_callback_t* sys) { 103 | snapshot->func = sys->func; 104 | snapshot->user_data = sys->user_data; 105 | } 106 | 107 | void chips_debug_snapshot_onsave(chips_debug_t* snapshot) { 108 | snapshot->callback.func = 0; 109 | snapshot->callback.user_data = 0; 110 | snapshot->stopped = 0; 111 | } 112 | 113 | void chips_debug_snapshot_onload(chips_debug_t* snapshot, chips_debug_t* sys) { 114 | snapshot->callback.func = sys->callback.func; 115 | snapshot->callback.user_data = sys->callback.user_data; 116 | snapshot->stopped = sys->stopped; 117 | } 118 | 119 | #endif // CHIPS_IMPL 120 | -------------------------------------------------------------------------------- /src/chips/clk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // clk.h 4 | // 5 | // Emulator clock helpers. 6 | // 7 | // Do this: 8 | // ~~~C 9 | // #define CHIPS_IMPL 10 | // ~~~ 11 | // before you include this file in *one* C file to create the 12 | // implementation. 13 | // 14 | // Optionally provide the following macros with your own implementation 15 | // 16 | // ~~~C 17 | // CHIPS_ASSERT(c) 18 | // ~~~ 19 | // your own assert macro (default: assert(c)) 20 | // 21 | // ## Functions 22 | // 23 | // ~~~C 24 | // uint32_t clk_us_to_ticks(uint64_t freq_hz, uint32_t micro_seconds) 25 | // ~~~ 26 | // Convert micro-seconds to system ticks. 27 | // 28 | // ## zlib/libpng license 29 | // 30 | // Copyright (c) 2018 Andre Weissflog 31 | // This software is provided 'as-is', without any express or implied warranty. 32 | // In no event will the authors be held liable for any damages arising from the 33 | // use of this software. 34 | // Permission is granted to anyone to use this software for any purpose, 35 | // including commercial applications, and to alter it and redistribute it 36 | // freely, subject to the following restrictions: 37 | // 1. The origin of this software must not be misrepresented; you must not 38 | // claim that you wrote the original software. If you use this software in a 39 | // product, an acknowledgment in the product documentation would be 40 | // appreciated but is not required. 41 | // 2. Altered source versions must be plainly marked as such, and must not 42 | // be misrepresented as being the original software. 43 | // 3. This notice may not be removed or altered from any source 44 | // distribution. 45 | 46 | #include 47 | 48 | #ifdef __cplusplus 49 | extern "C" { 50 | #endif 51 | 52 | // Helper func to convert micro_seconds into ticks 53 | uint32_t clk_us_to_ticks(uint64_t freq_hz, uint32_t micro_seconds); 54 | 55 | #ifdef __cplusplus 56 | } // extern "C" 57 | #endif 58 | 59 | /*-- IMPLEMENTATION ----------------------------------------------------------*/ 60 | #ifdef CHIPS_IMPL 61 | #ifndef CHIPS_ASSERT 62 | #include 63 | #define CHIPS_ASSERT(c) assert(c) 64 | #endif 65 | 66 | uint32_t clk_us_to_ticks(uint64_t freq_hz, uint32_t micro_seconds) { 67 | return (uint32_t)((freq_hz * micro_seconds) / 1000000); 68 | } 69 | #endif // CHIPS_IMPL 70 | -------------------------------------------------------------------------------- /src/devices/apple2_fdc_rom.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // clang-format off 4 | uint8_t __not_in_flash() apple2_fdc_rom[] = { 5 | 0xa2, 0x20, 0xa0, 0x0, 0xa2, 0x3, 0x86, 0x3c, 0x8a, 0xa, 0x24, 0x3c, 0xf0, 0x10, 0x5, 0x3c, 6 | 0x49, 0xff, 0x29, 0x7e, 0xb0, 0x8, 0x4a, 0xd0, 0xfb, 0x98, 0x9d, 0x56, 0x3, 0xc8, 0xe8, 0x10, 7 | 0xe5, 0x20, 0x58, 0xff, 0xba, 0xbd, 0x0, 0x1, 0xa, 0xa, 0xa, 0xa, 0x85, 0x2b, 0xaa, 0xbd, 8 | 0x8e, 0xc0, 0xbd, 0x8c, 0xc0, 0xbd, 0x8a, 0xc0, 0xbd, 0x89, 0xc0, 0xa0, 0x50, 0xbd, 0x80, 0xc0, 9 | 0x98, 0x29, 0x3, 0xa, 0x5, 0x2b, 0xaa, 0xbd, 0x81, 0xc0, 0xa9, 0x56, 0x20, 0xa8, 0xfc, 0x88, 10 | 0x10, 0xeb, 0x85, 0x26, 0x85, 0x3d, 0x85, 0x41, 0xa9, 0x8, 0x85, 0x27, 0x18, 0x8, 0xbd, 0x8c, 11 | 0xc0, 0x10, 0xfb, 0x49, 0xd5, 0xd0, 0xf7, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, 0xd0, 0xf3, 12 | 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0x96, 0xf0, 0x9, 0x28, 0x90, 0xdf, 0x49, 0xad, 0xf0, 13 | 0x25, 0xd0, 0xd9, 0xa0, 0x3, 0x85, 0x40, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x2a, 0x85, 0x3c, 0xbd, 14 | 0x8c, 0xc0, 0x10, 0xfb, 0x25, 0x3c, 0x88, 0xd0, 0xec, 0x28, 0xc5, 0x3d, 0xd0, 0xbe, 0xa5, 0x40, 15 | 0xc5, 0x41, 0xd0, 0xb8, 0xb0, 0xb7, 0xa0, 0x56, 0x84, 0x3c, 0xbc, 0x8c, 0xc0, 0x10, 0xfb, 0x59, 16 | 0xd6, 0x2, 0xa4, 0x3c, 0x88, 0x99, 0x0, 0x3, 0xd0, 0xee, 0x84, 0x3c, 0xbc, 0x8c, 0xc0, 0x10, 17 | 0xfb, 0x59, 0xd6, 0x2, 0xa4, 0x3c, 0x91, 0x26, 0xc8, 0xd0, 0xef, 0xbc, 0x8c, 0xc0, 0x10, 0xfb, 18 | 0x59, 0xd6, 0x2, 0xd0, 0x87, 0xa0, 0x0, 0xa2, 0x56, 0xca, 0x30, 0xfb, 0xb1, 0x26, 0x5e, 0x0, 19 | 0x3, 0x2a, 0x5e, 0x0, 0x3, 0x2a, 0x91, 0x26, 0xc8, 0xd0, 0xee, 0xe6, 0x27, 0xe6, 0x3d, 0xa5, 20 | 0x3d, 0xcd, 0x0, 0x8, 0xa6, 0x2b, 0x90, 0xdb, 0x4c, 0x1, 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 21 | }; 22 | // clang-format on 23 | -------------------------------------------------------------------------------- /src/devices/oric_fdc_rom.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // clang-format off 4 | uint8_t __not_in_flash() oric_fdc_rom[] = { 5 | 0x30, 0x33, 0x30, 0x30, 0x2e, 0x2e, 0x30, 0x33, 0x30, 0x46, 0x20, 0x2d, 0x20, 0x56, 0x49, 0x41, 6 | 0x30, 0x33, 0x31, 0x30, 0x2e, 0x2e, 0x30, 0x33, 0x31, 0x46, 0x20, 0x2d, 0x20, 0x46, 0x44, 0x43, 7 | 0x78, 0xa2, 0x5, 0xbd, 0x2f, 0x3, 0x9d, 0xea, 0x2, 0xca, 0x10, 0xf7, 0x4c, 0xea, 0x2, 0x8d, 8 | 0x82, 0x3, 0x4c, 0x20, 0x3, 0x42, 0x4f, 0x42, 0x59, 0xff, 0xff, 0x8d, 0x81, 0x3, 0x20, 0x3, 9 | 0xd4, 0x8d, 0x80, 0x3, 0x60, 0x8d, 0x81, 0x3, 0x20, 0x6, 0xd4, 0x8d, 0x80, 0x3, 0x60, 0x8d, 10 | 0x80, 0x3, 0x20, 0x5f, 0xc5, 0x8d, 0x81, 0x3, 0x60, 0x8d, 0x80, 0x3, 0x20, 0xc5, 0xe0, 0x8d, 11 | 0x81, 0x3, 0x60, 0x8d, 0x80, 0x3, 0x4c, 0xbd, 0xc4, 0x78, 0x8d, 0x81, 0x3, 0x20, 0x0, 0xd4, 12 | 0x8d, 0x80, 0x3, 0x58, 0x4c, 0x3, 0xc0, 0x78, 0x8d, 0x81, 0x3, 0x4c, 0x0, 0xc0, 0x8d, 0x80, 13 | 0x3, 0x20, 0x92, 0xc5, 0x8d, 0x81, 0x3, 0x60, 0x8d, 0x80, 0x3, 0x20, 0xfb, 0xcc, 0x8d, 0x81, 14 | 0x3, 0x60, 0x8d, 0x80, 0x3, 0x20, 0xa0, 0x3, 0x8d, 0x81, 0x3, 0x40, 0x20, 0xa0, 0x3, 0x40, 15 | 0x8, 0x48, 0xa9, 0x3, 0x48, 0xa9, 0xac, 0x48, 0x8, 0x4c, 0x22, 0xee, 0x68, 0x28, 0x60, 0x8d, 16 | 0x81, 0x3, 0x20, 0x9, 0xd4, 0x8d, 0x80, 0x3, 0x60, 0x8d, 0x81, 0x3, 0x4c, 0xc, 0xd4, 0xff, 17 | 0xff, 0x8d, 0x81, 0x3, 0x20, 0xf, 0xd4, 0x8d, 0x80, 0x3, 0x60, 0x8d, 0x81, 0x3, 0x20, 0x12, 18 | 0xd4, 0x8d, 0x80, 0x3, 0x60, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 19 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 20 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 21 | 0x30, 0x33, 0x30, 0x30, 0x2e, 0x2e, 0x30, 0x33, 0x30, 0x46, 0x20, 0x2d, 0x20, 0x56, 0x49, 0x41, 22 | 0x30, 0x33, 0x31, 0x30, 0x2e, 0x2e, 0x30, 0x33, 0x31, 0x46, 0x20, 0x2d, 0x20, 0x46, 0x44, 0x43, 23 | 0x78, 0xd8, 0xa0, 0x0, 0xa2, 0x3, 0x86, 0x78, 0x8a, 0xa, 0x24, 0x78, 0xf0, 0x10, 0x5, 0x78, 24 | 0x49, 0xff, 0x29, 0x7e, 0xb0, 0x8, 0x4a, 0xd0, 0xfb, 0x98, 0x9d, 0x56, 0xb4, 0xc8, 0xe8, 0x10, 25 | 0xe5, 0x2c, 0x1e, 0x3, 0x2c, 0x1c, 0x3, 0x2c, 0x1a, 0x3, 0x2c, 0x19, 0x3, 0xa2, 0x0, 0xa0, 26 | 0x48, 0xdd, 0x10, 0x3, 0x98, 0x29, 0x3, 0xa, 0xaa, 0xdd, 0x11, 0x3, 0xa2, 0x8, 0xd6, 0x76, 27 | 0xd0, 0xfc, 0xca, 0x10, 0xf9, 0xaa, 0x88, 0x10, 0xe8, 0xa9, 0xb8, 0x85, 0x77, 0x18, 0x8, 0xad, 28 | 0x1c, 0x3, 0x10, 0xfb, 0x49, 0xd5, 0xd0, 0xf7, 0xad, 0x1c, 0x3, 0x10, 0xfb, 0xc9, 0xaa, 0xd0, 29 | 0xf3, 0xea, 0xad, 0x1c, 0x3, 0x10, 0xfb, 0xc9, 0x96, 0xf0, 0x9, 0x28, 0x90, 0xdf, 0x49, 0xad, 30 | 0xf0, 0x25, 0xd0, 0xd9, 0xa0, 0x3, 0x85, 0x7c, 0xad, 0x1c, 0x3, 0x10, 0xfb, 0x2a, 0x85, 0x78, 31 | 0xad, 0x1c, 0x3, 0x10, 0xfb, 0x25, 0x78, 0x88, 0xd0, 0xec, 0x28, 0xc5, 0x79, 0xd0, 0xbe, 0xa5, 32 | 0x7c, 0xc5, 0x7d, 0xd0, 0xb8, 0xb0, 0xb7, 0xa0, 0x56, 0x84, 0x78, 0xac, 0x1c, 0x3, 0x10, 0xfb, 33 | 0x59, 0xd6, 0xb3, 0xa4, 0x78, 0x88, 0x99, 0x0, 0xb4, 0xd0, 0xee, 0x84, 0x78, 0xac, 0x1c, 0x3, 34 | 0x10, 0xfb, 0x59, 0xd6, 0xb3, 0xa4, 0x78, 0x91, 0x76, 0xc8, 0xd0, 0xef, 0xac, 0x1c, 0x3, 0x10, 35 | 0xfb, 0x59, 0xd6, 0xb3, 0xd0, 0x87, 0xa0, 0x0, 0xa2, 0x56, 0xca, 0x30, 0xfb, 0xb1, 0x76, 0x5e, 36 | 0x0, 0xb4, 0x2a, 0x5e, 0x0, 0xb4, 0x2a, 0x91, 0x76, 0xc8, 0xd0, 0xee, 0x4c, 0x0, 0xb8, 0x0, 37 | }; 38 | // clang-format off 39 | -------------------------------------------------------------------------------- /src/devices/prodos_hdc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | // ProDOS HDC softswitches 13 | #define PRODOS_HDC_RC_A (0x00) // return code register A 14 | #define PRODOS_HDC_RC_X (0x01) // return code register X 15 | #define PRODOS_HDC_RC_Y (0x02) // return code register Y 16 | #define PRODOS_HDC_PARA (0x07) // paravirtualization trigger 17 | 18 | #define PRODOS_HDC_MAGIC (0x65) 19 | #define PRODOS_HDC_MAX_DRIVES 2 20 | 21 | // ProDOS disk driver parameters 22 | #define PRODOS_DRV_COMMAND (0x0042) 23 | #define PRODOS_DRV_UNIT (0x0043) 24 | #define PRODOS_DRV_BUFFER (0x0044) 25 | #define PRODOS_DRV_BLOCK (0x0046) 26 | 27 | // ProDOS disk driver commands 28 | #define PRODOS_CMD_STATUS (0x00) 29 | #define PRODOS_CMD_READ (0x01) 30 | #define PRODOS_CMD_WRITE (0x02) 31 | #define PRODOS_CMD_FORMAT (0x04) 32 | 33 | // ProDOS hard disk controller state 34 | typedef struct { 35 | bool valid; 36 | uint8_t return_code[3]; 37 | prodos_hdd_t hdd[PRODOS_HDC_MAX_DRIVES]; 38 | } prodos_hdc_t; 39 | 40 | // ProDOS hard disk controller interface 41 | 42 | // Initialize a new hard disk controller 43 | void prodos_hdc_init(prodos_hdc_t* sys); 44 | 45 | // Discard the hard disk controller 46 | void prodos_hdc_discard(prodos_hdc_t* sys); 47 | 48 | // Reset the hard disk controller 49 | void prodos_hdc_reset(prodos_hdc_t* sys); 50 | 51 | uint8_t prodos_hdc_read_byte(prodos_hdc_t* sys, uint8_t addr); 52 | 53 | void prodos_hdc_write_byte(prodos_hdc_t* sys, uint8_t addr, uint8_t byte, mem_t* mem); 54 | 55 | // Prepare a new hard disk controller snapshot for saving 56 | void prodos_hdc_snapshot_onsave(prodos_hdc_t* snapshot); 57 | 58 | // Fix up the hard disk controller snapshot after loading 59 | void prodos_hdc_snapshot_onload(prodos_hdc_t* snapshot, prodos_hdc_t* sys); 60 | 61 | #ifdef __cplusplus 62 | } // extern "C" 63 | #endif 64 | 65 | /*-- IMPLEMENTATION ----------------------------------------------------------*/ 66 | #ifdef CHIPS_IMPL 67 | #include 68 | #ifndef CHIPS_ASSERT 69 | #include 70 | #define CHIPS_ASSERT(c) assert(c) 71 | #endif 72 | 73 | void prodos_hdc_init(prodos_hdc_t* sys) { 74 | CHIPS_ASSERT(sys && !sys->valid); 75 | memset(sys, 0, sizeof(prodos_hdc_t)); 76 | sys->valid = true; 77 | prodos_hdd_init(&sys->hdd[0]); 78 | } 79 | 80 | void prodos_hdc_discard(prodos_hdc_t* sys) { 81 | CHIPS_ASSERT(sys && sys->valid); 82 | sys->valid = false; 83 | prodos_hdd_discard(&sys->hdd[0]); 84 | } 85 | 86 | void prodos_hdc_reset(prodos_hdc_t* sys) { 87 | CHIPS_ASSERT(sys && sys->valid); 88 | prodos_hdd_reset(&sys->hdd[0]); 89 | } 90 | 91 | uint8_t prodos_hdc_read_byte(prodos_hdc_t* sys, uint8_t addr) { 92 | if (addr > PRODOS_HDC_RC_Y) { 93 | return 0; 94 | } 95 | return sys->return_code[addr]; 96 | } 97 | 98 | void prodos_hdc_write_byte(prodos_hdc_t* sys, uint8_t addr, uint8_t byte, mem_t* mem) { 99 | if (addr != PRODOS_HDC_PARA || byte != PRODOS_HDC_MAGIC) { 100 | return; 101 | } 102 | 103 | prodos_hdd_t* hdd = &sys->hdd[0]; 104 | 105 | if (mem_rd(mem, PRODOS_DRV_UNIT) != 0x70 || !prodos_hdd_is_disk_inserted(hdd)) { 106 | sys->return_code[PRODOS_HDC_RC_A] = PRODOS_HDD_ERR_NODEV; 107 | return; 108 | } 109 | 110 | uint32_t blocks = prodos_hdd_get_blocks(hdd); 111 | 112 | uint16_t buffer = mem_rd16(mem, PRODOS_DRV_BUFFER); 113 | uint16_t block = mem_rd16(mem, PRODOS_DRV_BLOCK); 114 | 115 | switch (mem_rd(mem, PRODOS_DRV_COMMAND)) { 116 | case PRODOS_CMD_STATUS: 117 | sys->return_code[PRODOS_HDC_RC_A] = PRODOS_HDD_ERR_OK; 118 | sys->return_code[PRODOS_HDC_RC_X] = blocks >> 0 & 0xFF; 119 | sys->return_code[PRODOS_HDC_RC_Y] = blocks >> 8 & 0xFF; 120 | return; 121 | case PRODOS_CMD_READ: 122 | sys->return_code[PRODOS_HDC_RC_A] = prodos_hdd_read_block(hdd, buffer, block, mem); 123 | return; 124 | case PRODOS_CMD_WRITE: 125 | sys->return_code[PRODOS_HDC_RC_A] = prodos_hdd_write_block(hdd, buffer, block, mem); 126 | return; 127 | } 128 | 129 | sys->return_code[PRODOS_HDC_RC_A] = PRODOS_HDD_ERR_IO; 130 | return; 131 | } 132 | 133 | void prodos_hdc_snapshot_onsave(prodos_hdc_t* snapshot) { CHIPS_ASSERT(snapshot); } 134 | 135 | void prodos_hdc_snapshot_onload(prodos_hdc_t* snapshot, prodos_hdc_t* sys) { CHIPS_ASSERT(snapshot && sys); } 136 | 137 | #endif // CHIPS_IMPL 138 | -------------------------------------------------------------------------------- /src/devices/prodos_hdc_rom.S: -------------------------------------------------------------------------------- 1 | ; cl65 -t none prodos_hdc_rom.S 2 | ; bin2hdr -i prodos_hdc_rom -o prodos_hdc_rom.h -a prodos_hdc_rom 3 | 4 | .feature c_comments 5 | 6 | /* 7 | 8 | MIT License 9 | 10 | Copyright (c) 2023 Oliver Schmidt (https://a2retro.de/) 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | 30 | */ 31 | 32 | SLOT = $07 33 | 34 | MAGIC = $65 35 | 36 | LOC0 := $00 37 | LOC1 := $01 38 | CMD := $42 ; DISK DRIVER COMMAND 39 | UNIT := $43 ; DISK DRIVER UNIT 40 | BUFL := $44 ; DISK DRIVER BUFFER 41 | BUFH := $45 42 | BLOCKL := $46 ; DISK DRIVER BLOCK 43 | BLOCKH := $47 44 | 45 | MSLOT := $07F8 ; BUFFER FOR HI SLOT ADDR (SCN) 46 | 47 | RC_A := $C080 ; RETURN CODE REGISTER A 48 | RC_X := $C081 ; RETURN CODE REGISTER X 49 | RC_Y := $C082 ; RETURN CODE REGISTER Y 50 | PARA := $C087 ; PARAVIRTUALIZATION TRIGGER 51 | 52 | COUT := $FDED ; CHARACTER OUT (THRU CSW) 53 | SETKBD := $FE89 ; SETS KSW TO APPLE KEYBOARD 54 | SETSCR := $FE93 ; SETS CSW TO APPLE SCREEN 55 | SLOOP := $FABA ; CONTINUE SLOT SCAN 56 | SETTXT := $FB39 ; SET TEXT MODE 57 | HOME := $FC58 ; CLEAR SCREEN AND HOME CURSOR 58 | BASIC := $E000 ; BASIC INTERPRETER COLD START 59 | 60 | .ORG $C000+$0100*SLOT 61 | 62 | CPX #$20 ; $Cn01:$20 63 | LDX #$00 ; $Cn03:$00 64 | CPX #$03 ; $Cn05:$03 65 | CPX #$3C ; $Cn07:$3C 66 | 67 | STX BLOCKL 68 | STX BLOCKH 69 | STX BUFL 70 | INX ; 1 MEANS READ 71 | STX CMD 72 | LDX #>$0800 73 | STX BUFH 74 | LDX #$10*SLOT ; DRIVE 1 75 | STX UNIT 76 | JSR DRIVER ; READ BLOCK 0 FROM DRIVE 1 TO $0800 77 | BCS FAILURE 78 | LDX $0800 ; NUMBER OF DISK II SECTORS TO READ 79 | DEX 80 | BNE FAILURE ; ... MUST BE 1 81 | LDX $0801 ; FIRST OPCODE 82 | BEQ FAILURE ; ... MUSTN'T BE BRK 83 | LDX #$10*SLOT ; DRIVE 1 84 | JMP $0801 ; GO FOR IT 85 | 86 | FAILURE:LDX LOC0 ; POTENTIAL AUTOSTART SCAN ROM PTR LO 87 | BNE ERREXIT ; ... MUST POINT TO A SLOT ROM START 88 | LDX LOC1 ; POTENTIAL AUTOSTART SCAN ROM PTR HI 89 | CPX MSLOT 90 | BNE ERREXIT ; ... MUST POINT TO CURRENT SLOT ROM 91 | CPX #>* 92 | BNE ERREXIT ; ... MUST POINT TO THIS SLOT ROM 93 | JMP SLOOP ; LOOKS LIKE AUTOSTART SCAN SO CONTINUE SCAN 94 | 95 | ERREXIT:JSR SETSCR 96 | JSR SETKBD 97 | JSR SETTXT 98 | JSR HOME 99 | LDX #$08 ; 'HDD ERROR' 100 | : LDA ERRTEXT,X 101 | JSR COUT 102 | DEX 103 | BPL :- 104 | JMP BASIC 105 | 106 | ERRTEXT:.BYTE 'R'|$80, 'O'|$80, 'R'|$80, 'R'|$80, 'E'|$80, ' '|$80, 'D'|$80, 'D'|$80, 'H'|$80 107 | 108 | DRIVER: LDA #MAGIC 109 | STA PARA|$10*SLOT 110 | ; ABRACADABRA 111 | LDA RC_A|$10*SLOT 112 | LDX RC_X|$10*SLOT 113 | LDY RC_Y|$10*SLOT 114 | CMP #$01 ; SET CARRY IF A IS NOT 0 115 | RTS 116 | 117 | .RES $0100-4-<* ; THE 4 BYTES BELOW GO TO THE END OF THE SLOT ROM 118 | 119 | .BYTE $00,$00 ; TOTAL BLOCKS 120 | .BYTE $F7 ; STATUS BYTE 121 | .BYTE 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define BYTES_PER_LINE 16 8 | 9 | static void print_usage(const char* argv0) { 10 | fprintf(stderr, 11 | "Usage: %s -i binary_file -o header_file -a array_name\n" 12 | "\t-h show this help\n", 13 | argv0); 14 | exit(1); 15 | } 16 | 17 | static void print_file(FILE* in, FILE* out, const char* array_name) { 18 | uint8_t c; 19 | int bytes = 0; 20 | int eof; 21 | 22 | fprintf(out, "#pragma once\n\n"); 23 | fprintf(out, "// clang-format off\n"); 24 | fprintf(out, "uint8_t __in_flash() %s[] = {", array_name); 25 | 26 | c = fgetc(in); 27 | eof = feof(in); 28 | while (!eof) { 29 | if ((bytes % BYTES_PER_LINE) == 0) { 30 | fprintf(out, "\n\t"); 31 | } 32 | bytes++; 33 | fprintf(out, "0x%02X", c); 34 | 35 | c = fgetc(in); 36 | eof = feof(in); 37 | if (!eof) { 38 | fprintf(out, ", "); 39 | } 40 | } 41 | if (bytes) { 42 | fprintf(out, "\n"); 43 | } 44 | fprintf(out, "};\n"); 45 | fprintf(out, "// clang-format off\n"); 46 | } 47 | 48 | static void convert_bin_to_hdr(const char* infile, const char* outfile, const char* array_name) { 49 | FILE *in, *out; 50 | 51 | in = fopen(infile, "rb"); 52 | if (in) { 53 | out = fopen(outfile, "w"); 54 | if (out) { 55 | print_file(in, out, array_name); 56 | fclose(out); 57 | } else { 58 | fprintf(stderr, "Failed to open file for writing: %s", outfile); 59 | } 60 | fclose(in); 61 | } else { 62 | fprintf(stderr, "Failed to open file for reading: %s", infile); 63 | } 64 | } 65 | 66 | int main(int argc, char* const argv[]) { 67 | char *infile = NULL, *outfile = NULL, *array_name = NULL; 68 | int opt; 69 | 70 | while ((opt = getopt(argc, argv, "i:o:a:h")) != -1) { 71 | switch (opt) { 72 | case 'i': 73 | infile = strdup(optarg); 74 | break; 75 | case 'o': 76 | outfile = strdup(optarg); 77 | break; 78 | case 'a': 79 | array_name = strdup(optarg); 80 | break; 81 | case 'h': 82 | default: 83 | print_usage(argv[0]); 84 | return 0; 85 | } 86 | } 87 | 88 | if (!infile || !outfile || !array_name) { 89 | print_usage(argv[0]); 90 | } else { 91 | convert_bin_to_hdr(infile, outfile, array_name); 92 | } 93 | 94 | return 0; 95 | } 96 | --------------------------------------------------------------------------------