From 2abdb84acc586e494ba1486af8f78d297b6e4dc6 Mon Sep 17 00:00:00 2001 From: hkz Date: Mon, 1 Sep 2025 16:40:51 +0200 Subject: [PATCH] Base version of the floppicator --- Makefile | 4 +- linker-files/linker.scm | 4 +- src/graphics.c | 25 +++++++ src/graphics.h | 2 + src/main.c | 157 +++++++++++++++++++++++++++++++++++++--- src/mem_map.h | 5 +- src/utility.c | 4 +- src/utility.h | 2 +- 8 files changed, 181 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 721d57b..54420ba 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,8 @@ PRG=master # Libraries LIBS=clib-6502.a -ASM_SRCS = tk2k_startup.s preserve_zero_pages.s disk2.s -C_SRCS = main.c graphics.c utility.c line_data.c +ASM_SRCS = tk2k_startup.s preserve_zero_pages.s disk2.s sound.s +C_SRCS = main.c graphics.c utility.c line_data.c input.c # Object files OBJS = $(ASM_SRCS:%.s=%.o) $(C_SRCS:%.c=%.o) diff --git a/linker-files/linker.scm b/linker-files/linker.scm index 8ad7016..9809693 100644 --- a/linker-files/linker.scm +++ b/linker-files/linker.scm @@ -3,9 +3,9 @@ (section registers zpage zzpage)) (memory firstPage (address (#x100 . #x1ff)) (section stack)) (memory reserved (address (#x200 . #x7ff)) (type ram)) - (memory program (address (#x800 . #x15ff)) (type ram) + (memory program (address (#x800 . #x187f)) (type ram) (section (programStart #x800) (dii_critical_wr_code #x803) (dii_critical_rd_code #x90b) startup code switch idata cdata data_init_table)) - (memory dataMem (address (#x1600 . #x1fff)) (type ram) (section cstack zdata data heap zpsave)) + (memory dataMem (address (#x1880 . #x1fff)) (type ram) (section cstack zdata data heap zpsave)) (memory displayPage1 (address (#x2000 . #x3fff)) (type ram)) (memory upperMem (address (#x4000 . #xbbff)) (type ram)) (memory diskBuffer (address (#xbc00 . #xbeff)) (type ram)) ;;; This memory will be used by the disk II routines as buffer diff --git a/src/graphics.c b/src/graphics.c index 8b58fa2..eb4ece0 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -67,3 +67,28 @@ void draw_chars(uint8_t x, uint8_t y, uint8_t invert, uint8_t *buf, uint8_t len } } } + +void draw_char(uint8_t x, uint8_t y, uint8_t invert, uint8_t ch) { + for(uint8_t row = 0; row < CHAR_HEIGHT && (row + y) < SCREEN_HEIGHT; row++) { + uint16_t offset = line_offset_map[row + y]; + + front_buf[offset + x] = invert ? (~CHARSET[(ch * CHAR_HEIGHT) + row]) & 0x7F : CHARSET[(ch * CHAR_HEIGHT) + row]; + } +} + +uint8_t convert_string(uint8_t *buf, uint8_t buf_len, char *str) { + uint8_t size = 0; + + while(*str && size < buf_len) { // Yeah yeah. Unsafe. + char ch = *str; + if(ch >= 64 && ch <= 95) buf[size] = ch - 64; + else if (ch >= 97 && ch <= 122) buf[size] = ch - 96; // Uppercase conversion + else if (ch >= 32 && ch <= 63) buf[size] = ch; // As is + else buf[size] = 0x20; // For everything else, insert a space. + + str++; + size++; + } + + return size; +} diff --git a/src/graphics.h b/src/graphics.h index 3b95b54..0aade5c 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -13,6 +13,8 @@ void initialize_display_buffer(void); void clear_display_buffer(void); void draw_number(uint16_t n, uint8_t len, uint8_t x, uint8_t y); void clear_box(uint8_t w, uint8_t h, uint8_t off_x, uint8_t off_y); +void draw_char(uint8_t x, uint8_t y, uint8_t invert, uint8_t ch); void draw_chars(uint8_t x, uint8_t y, uint8_t invert, uint8_t *buf, uint8_t len); +uint8_t convert_string(uint8_t *buf, uint8_t buf_len, char *str); #endif /* _GRAPHICS_HEADER_ */ diff --git a/src/main.c b/src/main.c index 68f42c9..487d472 100644 --- a/src/main.c +++ b/src/main.c @@ -9,7 +9,10 @@ #include "mem_map.h" #include "mem_registers.h" #include "graphics.h" +#include "sound.h" #include "disk2.h" +#include "input.h" +#include "charset.h" // External initialization requirements #pragma require __preserve_zp @@ -17,7 +20,20 @@ #define DEFAULT_DRIVE_CONTROLLER_OFFSET 0x10 +#define TOT_FLOPPY_TRACKS 35 +#define SECTORS_PER_TRACK 16 +#define SECTOR_SIZE 256 +#define TRACKS_AT_ONCE 7 +#define TRACK_PARTS (TOT_FLOPPY_TRACKS / TRACKS_AT_ONCE) + +static uint8_t *track_buffer = (uint8_t*)TRACK_BUFFER_START; +static uint8_t *crc_buffer = (uint8_t*)CRC_BUFFER_START; + +static uint8_t str_conv_buffer[SCREEN_CHAR_WIDTH]; + static void init(void); +static void draw_sector_map(void); +static void reseat_floppy_heads(void); // Low level initialization static void init(void) { @@ -34,27 +50,144 @@ static void init(void) { clear_display_buffer(); } +#define MAP_TOP_OFFSET 2 +static void draw_sector_map(void) { + uint8_t str_len; + + str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "00000000000000001111111111111111222"); + draw_chars(1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 0), 1, str_conv_buffer, str_len); + str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "0123456789ABCDEF0123456789ABCDEF012"); + draw_chars(1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 1), 1, str_conv_buffer, str_len); + + for(uint8_t row = 0; row < 0x10; row++) { + draw_char(0, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + row), 1, str_conv_buffer[row]); + } + + str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "..................................."); + for(uint8_t row = 0; row < 0x10; row++) { + draw_chars(1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + row), 0, str_conv_buffer, str_len); + } +} + +static void reseat_floppy_heads(void) { + dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 0); + dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, 96, 0); + dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET); + + dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 1); + dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, 96, 0); + dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET); +} + __task int main(void) { - uint8_t cur_trk_1, cur_trk_2 = 0; - uint8_t keep_going = 1; + uint8_t trk_pos_1 = 0, trk_pos_2 = 0; + uint16_t errors = 0; + uint8_t *temp_crc_buf; __disable_interrupts(); init(); + + uint8_t str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "THE FLOPPICATOR"); + draw_chars(12, 32, 0, str_conv_buffer, str_len); + + str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "PRESS ANY KEY TO CONTINUE"); + draw_chars(7, 176, 1, str_conv_buffer, str_len); + + while(!read_any_key()); + snd_mod_button(); + + clear_display_buffer(); + + draw_sector_map(); + + str_len = convert_string(str_conv_buffer, SCREEN_CHAR_WIDTH, "ERRORS: 000"); + draw_chars(0, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19), 0, str_conv_buffer, str_len); + + reseat_floppy_heads(); + + temp_crc_buf = crc_buffer; + for(uint8_t part = 0; part < TRACK_PARTS; part++) { + uint8_t start_track = part * TRACKS_AT_ONCE; + dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 0); + + for(uint8_t cur_trk = 0; cur_trk < TRACKS_AT_ONCE; cur_trk++) { + dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_1 << 1, (start_track + cur_trk) << 1); + trk_pos_1 = (start_track + cur_trk); + + for(uint8_t sec = 0; sec < SECTORS_PER_TRACK; sec++) { + uint8_t read_res = dii_read_sector(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_1, sec, track_buffer + (cur_trk * SECTORS_PER_TRACK * SECTOR_SIZE) + (sec * SECTOR_SIZE), 0); + *(temp_crc_buf++) = calculate_crc8(track_buffer + (cur_trk * SECTORS_PER_TRACK * SECTOR_SIZE) + (sec * SECTOR_SIZE), SECTOR_SIZE); + draw_char((start_track + cur_trk) + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), read_res ? 0 : 1, read_res ? 18 : 24); + + if(!read_res) { + errors++; + draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19)); + } + } + } + + dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET); + + dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 1); + + for(uint8_t cur_trk = 0; cur_trk < TRACKS_AT_ONCE; cur_trk++) { + dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2 << 1, (start_track + cur_trk) << 1); + trk_pos_2 = (start_track + cur_trk); + + for(uint8_t sec = 0; sec < SECTORS_PER_TRACK; sec++) { + dii_encode_gcr62_data(track_buffer + (cur_trk * SECTORS_PER_TRACK * SECTOR_SIZE) + (sec * SECTOR_SIZE), (uint8_t*)WRITE_SIXES_BUFFER_DEFAULT_ADDRESS, (uint8_t*)WRITE_TWOS_BUFFER_DEFAULT_ADDRESS); + uint8_t write_res = dii_write_sector(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2, sec); + draw_char((start_track + cur_trk) + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), write_res ? 1 : 0, write_res ? 24 : 23); + + if(write_res) { + errors++; + draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19)); + } + } + } + + dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET); + } + + + if(!errors) { // No errors up to now, check what we have written + dii_power_on(DEFAULT_DRIVE_CONTROLLER_OFFSET, 1); + + // Now, time to check that we wrote things that make sense... + temp_crc_buf = crc_buffer; + for(uint8_t cur_trk = 0; cur_trk < TOT_FLOPPY_TRACKS; cur_trk++) { + dii_head_reposition(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2 << 1, cur_trk << 1); + trk_pos_2 = cur_trk; + + for(uint8_t sec = 0; sec < SECTORS_PER_TRACK; sec++) { + uint8_t read_res = dii_read_sector(DEFAULT_DRIVE_CONTROLLER_OFFSET, trk_pos_2, sec, track_buffer, 0); + draw_char(cur_trk + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), 0, read_res ? 102 : 24); + uint8_t crc_check = (calculate_crc8(track_buffer, SECTOR_SIZE) == *(temp_crc_buf++)); + draw_char(cur_trk + 1, CHAR_HEIGHT * (MAP_TOP_OFFSET + 2 + sec), crc_check ? 0 : 1, crc_check ? 22 : 24); + + if(!read_res) { + errors++; + draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19)); + } + + if(!crc_check) { + errors++; + draw_number(errors, 3, 8, CHAR_HEIGHT * (MAP_TOP_OFFSET + 19)); + } + } + } + + dii_power_off(DEFAULT_DRIVE_CONTROLLER_OFFSET); + } + __enable_interrupts(); - uint8_t chars[] = {1, 2, 3, 32, 4}; + if(errors) snd_sad_scale(); + else snd_festive(); - draw_chars(0, 0, 1, chars, 5); - draw_chars(1, 8, 0, chars, 5); - draw_chars(2, 16, 1, chars, 5); - - do { - - } while(keep_going); - - __asm volatile(" brk\n":::); + while(1); return 0; } diff --git a/src/mem_map.h b/src/mem_map.h index 1f3aaac..505edb3 100644 --- a/src/mem_map.h +++ b/src/mem_map.h @@ -7,8 +7,7 @@ #define ROMRAM_BANK 0xC100 -#define SHARED_PAGE 0x9B00 -#define STATE_PAGE 0x9A00 -#define MODULE_PAGE 0x4000 +#define TRACK_BUFFER_START 0x4000 +#define CRC_BUFFER_START 0xB000 #endif /* _MEMORY_MAP_HEADER_ */ diff --git a/src/utility.c b/src/utility.c index e019be9..1e82ff3 100644 --- a/src/utility.c +++ b/src/utility.c @@ -45,10 +45,10 @@ uint16_t lfsr_update(void) { } #define CRC8RDALLAS_POLY 0x31 -uint8_t calculate_crc8(uint8_t* data, uint8_t len) { +uint8_t calculate_crc8(uint8_t* data, uint16_t len) { uint8_t crc = 0; - for(uint8_t data_idx = 0; data_idx < len; data_idx++) { + for(uint16_t data_idx = 0; data_idx < len; data_idx++) { uint8_t carry; uint8_t d = data[data_idx]; diff --git a/src/utility.h b/src/utility.h index d30bb0a..4bbf7ed 100644 --- a/src/utility.h +++ b/src/utility.h @@ -29,6 +29,6 @@ uint8_t bit_reverse(uint8_t b); uint8_t bit_count(uint8_t b); void lfsr_init(uint16_t reg); uint16_t lfsr_update(void); -uint8_t calculate_crc8(uint8_t* data, uint8_t len); +uint8_t calculate_crc8(uint8_t* data, uint16_t len); #endif /* _UTILITY_HEADER_ */