Add a more-or-less working NC200 bootable file system image and auto.prg.
authorDavid Given <dg@cowlark.com>
Sat, 9 Dec 2017 16:02:36 +0000 (17:02 +0100)
committerDavid Given <dg@cowlark.com>
Sat, 9 Dec 2017 16:02:36 +0000 (17:02 +0100)
Kernel/platform-nc200/Makefile [new file with mode: 0644]
Kernel/platform-nc200/autoprg.s [new file with mode: 0644]
Kernel/platform-nc200/bootblock.s [new file with mode: 0644]

diff --git a/Kernel/platform-nc200/Makefile b/Kernel/platform-nc200/Makefile
new file mode 100644 (file)
index 0000000..b178d2b
--- /dev/null
@@ -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 (file)
index 0000000..4637848
--- /dev/null
@@ -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 (file)
index 0000000..a4ff529
--- /dev/null
@@ -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