From b3217e2cff60c921cd79a4ba482a1ed64be352d7 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 9 Dec 2017 17:02:36 +0100 Subject: [PATCH] Add a more-or-less working NC200 bootable file system image and auto.prg. --- Kernel/platform-nc200/Makefile | 24 +++++ Kernel/platform-nc200/autoprg.s | 157 ++++++++++++++++++++++++++++++ Kernel/platform-nc200/bootblock.s | 82 ++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 Kernel/platform-nc200/Makefile create mode 100644 Kernel/platform-nc200/autoprg.s create mode 100644 Kernel/platform-nc200/bootblock.s diff --git a/Kernel/platform-nc200/Makefile b/Kernel/platform-nc200/Makefile new file mode 100644 index 00000000..b178d2b2 --- /dev/null +++ b/Kernel/platform-nc200/Makefile @@ -0,0 +1,24 @@ +bootfloppy.img: bootblock.img autoprg.bin + rm -f bootfloppy.img + cp bootblock.img bootfloppy.img + truncate bootfloppy.img --size 7680 + mcopy -i bootfloppy.img autoprg.bin ::auto.prg + mcopy -i bootfloppy.img big ::bank80.img + mcopy -i bootfloppy.img big ::bank81.img + +bootblock.img: bootblock.s + sdasz80 -fflopzws bootblock.rel bootblock.s + sdldz80 -nwmx -i bootblock.ihx bootblock.rel + srec_cat -disable-sequence-warning \ + bootblock.ihx -intel \ + -output bootblock.img -binary + +autoprg.bin: autoprg.s + sdasz80 -fflopzws autoprg.rel autoprg.s + sdldz80 -nwmx -b _CODE=0xa000 -i autoprg.ihx autoprg.rel + srec_cat -disable-sequence-warning \ + autoprg.ihx -intel -offset -0xa000 \ + -output autoprg.bin -binary + +clean: + rm -f bootblock.img autoprg.bin bootfloppy.img diff --git a/Kernel/platform-nc200/autoprg.s b/Kernel/platform-nc200/autoprg.s new file mode 100644 index 00000000..4637848a --- /dev/null +++ b/Kernel/platform-nc200/autoprg.s @@ -0,0 +1,157 @@ +.globl entry + +; Amstrad kernel entrypoints + +kmreadchar = 0xb9b3 +textout = 0xb81e +txtclearwindow = 0xb824 +txtoutput = 0xb833 + +; Ranger FDD entrypoints + +r_finish = 0xf34b +r_set_dta = 0xf391 +r_find_first = 0xf396 +r_find_next = 0xf3bf +.data.gp = 0xb7e0 +.data.dta = 0xb7f1 +load_sectors_to_4000 = 0xe884 +print_hex_i8 = 0xcb0e +press_any_key = 0xcb50 +advance_to_next_cluster = 0xd8ca +read_sector = 0xdffe +calculate_location_of_cluster = 0xda57 +update_watchdog_timer = 0xcc78 + + ; On entry, the memory map is as follows: + ; + ; 0x0000-0x3fff: Kernel workspace + ; 0x4000-0x7ccc: Dedicated 16kB bank for us + ; 0x8000-0xbfff: Kernel workspace + ; 0xc000-0xffff: Ranger floppy disk routines + ; + ; The only bank we can change while still keeping the Amstral kernel running + ; from is the one at 0x4000. So we need to relocate ourself into the transient + ; data area at 0xa000 to allow this. This is 4kB wide. + +entry: + ld de, #0xa000 + ld hl, #0x4000 + ld bc, #0x1000 + ldir + jp start +start: + call txtclearwindow + ld hl, #.str.hello + call textout + + ld hl, #.str.pattern + ld a, #0xff + call r_find_first +filename_loop: + jp c, failed + + ld hl, (.data.dta) + call textout + ld a, #' ' + call txtoutput + call load_file + + call r_find_next + jr filename_loop + +failed: + cp #0x12 ; ran out of files? + jr z, finished + ; Otherwise it's a hard error. +really_failed: + push af + ld hl, #.str.error + call textout + pop af + call print_hex_i8 + jp press_any_key + +finished: + ld a, (.data.found_a_file) + or a + jr z, no_files + call r_finish + jp press_any_key +no_files: + ld hl, #.str.nofiles + call textout + jp press_any_key + +nl: + ld hl, #.str.nl + jp textout + +load_file: + ld a, #1 + ld (.data.found_a_file), a + + ld hl, #0x4000 + ld (.data.destination), hl + + ld iy, (.data.dta) + ld l, 0x1c(iy) ; start cluster in dirent + ld h, 0x1d(iy) +cluster_loop: + push hl + call calculate_location_of_cluster + ld 0x18(ix), a ; track + ld 0x1a(ix), l ; sector + + ld hl, (.data.destination) + call read_sector + jr c, really_failed + call update_watchdog_timer + + ld a, 0x1a(ix) + inc a + ld 0x1a(ix), a + + ld hl, (.data.destination) + ld de, #0x200 + add hl, de + ld (.data.destination), hl + call read_sector + jr c, really_failed + call update_watchdog_timer + + ld hl, (.data.destination) + ld de, #0x200 + add hl, de + ld (.data.destination), hl + + ld a, #'.' + call txtoutput + + pop hl + call advance_to_next_cluster + jr nc, cluster_loop + jp nl + +.data.found_a_file: + .db 0 +.data.destination: + .dw 0 + +.str.hello: + .ascii "Loading..." +.str.nl: + .ascii "\r\n" + .db 0 + +.str.nofiles: + .ascii "No files to load!" + .db 0 + +.str.pattern: + .ascii "BANK??.IMG" + .db 0 + +.str.error: + .ascii "\r\nError: " + .db 0 \ No newline at end of file diff --git a/Kernel/platform-nc200/bootblock.s b/Kernel/platform-nc200/bootblock.s new file mode 100644 index 00000000..a4ff529a --- /dev/null +++ b/Kernel/platform-nc200/bootblock.s @@ -0,0 +1,82 @@ + .area _BOOT (ABS) + +.macro bios_parameter_block reserved_sectors + .dw 512 ; bytes per sector + .db 2 ; sectors per cluster + .dw reserved_sectors + .db 2 ; FAT count + .dw 0x70 ; number of root directory entries + .dw 108 ; filesystem size, in sectors + .db 0xf9 ; media byte + .dw 3 ; sectors per FAT + .dw 9 ; number of sectors per track + .dw 2 ; number of heads + .dw 0 ; number of hidden sectors +.endm + + .org 0x0003 + .ascii "NCBOOT " + + .org 0x000b + bios_parameter_block 2 + .org 0x020b + bios_parameter_block 0 + + .org 0x1be + + ; Partition 0 + .db 0 ; partition status (not bootable) + .db 0, 2, 0 ; encoded CHS of start + .db 0xda ; partition type + .db 1, 8, 5 ; encoded CHS of end + .dw 1, 0 ; LBA of start + .dw 0x6a, 0 ; LBA of end + + ; partition 1 + .db 0 ; partition status (not bootable) + .db 1, 9, 5 ; encoded CHS of start + .db 0x83 ; partition type + .db 1, 9, 0x4f ; encoded CHS of end + .dw 0x6b, 0 ; LBA of start + .dw 0x534, 0 ; LBA of end + + .org 0x01fe + .db 0x55, 0xaa + +; The FAT entries for two cylinders (four physical tracks). +; That's 18*4 = 72 sectors = 0x12 clusters. But we are offset left +; by one sector, so clusters 0 and 5 span two tracks (and are inaccessible). +; Then the pattern is repeated again for the other two tracks. +.macro four_tracks + .db 0xf7, 0x0f, 0x00 ; clusters 0, 1 + .db 0x00, 0x00, 0x00 ; clusters 2, 3 + .db 0x00, 0x70, 0xff ; clusters 4, 5 + .db 0x00, 0x00, 0x00 ; clusters 6, 7 + .db 0x00, 0x70, 0xff ; clusters 8, 9 + .db 0x00, 0x00, 0x00 ; clusters a, b + .db 0x00, 0x00, 0x00 ; clusters c, d + .db 0xf7, 0x0f, 0x00 ; clusters d, e + .db 0x00, 0x00, 0x00 ; clusters f, 10 +.endm + +.macro fat_definition + .db 0xf9, 0xff, 0xff + .db 0x00, 0x70, 0xff ; clusters 2, 3 + .db 0x00, 0x00, 0x00 ; clusters 4, 5 + .db 0x00, 0x00, 0x00 ; clusters 6, 7 + .db 0xf7, 0x0f, 0x00 ; clusters 8, 9 + .db 0x00, 0x00, 0x00 ; clusters a, b + + four_tracks + four_tracks +.endm + + .org 0x400 + fat_definition + .org 0xa00 + fat_definition + +; Make an empty root directory. + + .org 0x1000 + .db 0 -- 2.34.1