disk.bas 5.48 KB
Newer Older
John P. Willis's avatar
John P. Willis committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
'
' disk.bas
'

#include "disk.bi"
#include "storage.bi"
#include "bus.bi"
#include "config.bi"
#include "message.bi"


sub disk_attach()

    dim disk_device as dev_entry

    with disk_device
        .dev_tag = "disk"
        .io_base = 240
        .io_port_count = 10
        .dev_init = @disk_init
        .dev_reset = @disk_reset
        .dev_cycle = @disk_cycle
        .dev_input = @disk_input
        .dev_output = @disk_output
    end with

John P. Willis's avatar
John P. Willis committed
27 28
    disk_io_base = disk_device.io_base
    
John P. Willis's avatar
John P. Willis committed
29 30 31 32
    bus_attach 5, disk_device

end sub

John P. Willis's avatar
John P. Willis committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
sub disk_init()       

    dim i as integer    
    dim disk_header as disk_header_t

    if installed_disk_count > 0 then
        for i = 0 to installed_disk_count - 1
            close #installed_disks(i).file_number
        next i
    end if

    installed_disk_count = val(config_get("disk", "count"))

    redim installed_disks(installed_disk_count) as installed_disk_t        

48 49
    message_print "disk_init():  disk adapter configured at I/O port " & disk_io_base & "h"
    message_print "disk_init():  " & installed_disk_count & " storage devices attached"
John P. Willis's avatar
John P. Willis committed
50

John P. Willis's avatar
John P. Willis committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
    for i = 0 to installed_disk_count - 1
        

        installed_disks(i).host_file = config_get("disk", trim(str(i)))
        installed_disks(i).file_number = freefile()

        open installed_disks(i).host_file for binary as #installed_disks(i).file_number
        get #installed_disks(i).file_number, , disk_header

        with installed_disks(i)
            .track_count = disk_header.track_count
            .sectors_per_track = disk_header.sectors_per_track
        end with


        disk_build_seek_table i

John P. Willis's avatar
John P. Willis committed
68
        message_print "disk_init():  channel #" & trim(str(i)) & ": " & disk_header.track_count & " tracks, " & disk_header.sectors_per_track & " sectors/track (host file " & installed_disks(i).host_file & ")"
John P. Willis's avatar
John P. Willis committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104

    next i

    for i = 0 to installed_disk_count - 1
        disk_seek i, 0
    next i
    
end sub

sub disk_build_seek_table(new_channel as ushort)

    dim f_num as integer
    dim f_header as disk_header_t
    dim f_track as disk_track_t
    dim i as integer
    dim f_pos as integer
    dim t_cnt as ushort

    f_num = installed_disks(new_channel).file_number
    t_cnt = installed_disks(new_channel).track_count

    seek #f_num, 1
    get #f_num, , f_header

    redim preserve disk_seek_table(installed_disk_count, t_cnt) as ushort

    for i = 0 to t_cnt
        f_pos = seek(f_num)

        disk_seek_table(new_channel, i) = f_pos

        get #f_num, , f_track
    
    next i

    seek #f_num, 1
John P. Willis's avatar
John P. Willis committed
105 106 107 108 109 110 111 112 113 114 115

end sub

sub disk_reset()

end sub

function disk_input(port_number as ushort) as ushort

    select case port_number
        case (disk_io_base + 0)
John P. Willis's avatar
John P. Willis committed
116
            return installed_disk_count
John P. Willis's avatar
John P. Willis committed
117
        case (disk_io_base + 1)
John P. Willis's avatar
John P. Willis committed
118
            return installed_disks(channel).track_count
John P. Willis's avatar
John P. Willis committed
119
        case (disk_io_base + 2)
John P. Willis's avatar
John P. Willis committed
120
            return installed_disks(channel).sectors_per_track
John P. Willis's avatar
John P. Willis committed
121 122 123 124 125 126 127 128 129
    end select


end function

sub disk_output(port_number as ushort, value as ushort)

    select case port_number
        case (disk_io_base + 0)
John P. Willis's avatar
John P. Willis committed
130
            channel = value
John P. Willis's avatar
John P. Willis committed
131
        case (disk_io_base + 1)
John P. Willis's avatar
John P. Willis committed
132
            sect_buf_page = value
John P. Willis's avatar
John P. Willis committed
133
        case (disk_io_base + 2)
John P. Willis's avatar
John P. Willis committed
134
            sect_buf_offset = value
John P. Willis's avatar
John P. Willis committed
135
        case (disk_io_base + 3)
John P. Willis's avatar
John P. Willis committed
136
            disk_seek channel, value
John P. Willis's avatar
John P. Willis committed
137
        case (disk_io_base + 4)
John P. Willis's avatar
John P. Willis committed
138
            disk_read value
John P. Willis's avatar
John P. Willis committed
139
        case (disk_io_base + 5)
John P. Willis's avatar
John P. Willis committed
140
            disk_write value
John P. Willis's avatar
John P. Willis committed
141 142 143 144 145 146 147
    end select

end sub

sub disk_cycle(byval userdata as any ptr)

    do
John P. Willis's avatar
John P. Willis committed
148
        sleep 500, 1
John P. Willis's avatar
John P. Willis committed
149 150 151 152

        if bus_get_stop_flag(5) = 1 then exit do
    loop

John P. Willis's avatar
John P. Willis committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
end sub

sub disk_create(file_path as string, track_count as ushort)

    dim file_number as integer    
    dim file_header as disk_header_t
    dim track as disk_track_t
    dim i as integer

    file_number = freefile()

    open file_path for binary as #file_number

    with file_header
        .magic = "XDI"
        .track_count = track_count
        .sectors_per_track = 512    'hardcoded for now
    end with

    put #file_number, , file_header

    for i = 0 to track_count - 1
        put #file_number, , track
    next i    

    close #file_number

end sub

sub disk_seek(new_channel as ushort, new_track as ushort)

    dim f_num as integer
    dim f_pos as integer

    f_num = installed_disks(new_channel).file_number

    seek #f_num, disk_seek_table(new_channel, new_track)

    f_pos = seek(f_num)

    message_print "disk_seek():  channel " & new_channel & ": track " & new_track & " (host file offset " & f_pos &")"

    installed_disks(new_channel).current_track = new_track

end sub

sub disk_read(tgt_sector as ushort)

    dim tmp_track as disk_track_t
    dim tmp_sector as disk_sector_t
    dim f_num as integer

    dim i as integer
    dim c_byte as integer = 0

    f_num = installed_disks(channel).file_number

    get #f_num, ,tmp_track
    
    tmp_sector = tmp_track.sectors(tgt_sector)

    for i = sect_buf_offset to sect_buf_offset + 512
        st_write_byte sect_buf_page, i, tmp_sector.sector(c_byte)
        c_byte += 1
    next i

end sub

sub disk_write(tgt_sector as ushort)

    dim tmp_track as disk_track_t
    dim tmp_sector as disk_sector_t
    dim f_num as integer

    f_num = installed_disks(channel).file_number    

    dim i as integer
    dim c_byte as integer = 0

    for i = sect_buf_offset to sect_buf_offset + 512
        tmp_sector.sector(c_byte) = st_read_byte(sect_buf_page, i)
        c_byte += 1
    next i

    tmp_track.sectors(tgt_sector) = tmp_sector

    put #f_num, , tmp_track

end sub

function disk_get_iobase() as ushort
    return disk_io_base
end function