-
Notifications
You must be signed in to change notification settings - Fork 0
/
wdos.asm
570 lines (511 loc) · 12.9 KB
/
wdos.asm
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
27
28
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
;
; Z80 WeirDOS 0.4
;
; A Disk Operating System for Z80 microcomputers, implementing
; the CP/M 2.2 API and FAT12/FAT16 filesystems.
;
; Revision history:
; 0.1 (March 2015) - Initial write
;
; 0.2 (September 2015) - Rewrite of filesystem functions
;
; 0.3 (January 2021) - Get 0.2 to actually work
; - Implement write functions
; - I left this too long
;
; 0.4 (January 2021) - Split source file into multiple files
; - Use of temporary labels
;
; TODO:
; - Finish remaining unimplemented API calls
; - Implement subdirectories
; - Exact method of implementation undecided
; - Maybe use 'user' areas to access directories in root
; - Fully test FAT16 code
; - Write a shell
;
;
; Coptright (C) 2021 Alexis Kotlowy
;
; This file is part of WeirDOS (aka WDOS)
;
; WeirDOS is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; WeirDOS is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with WeirDOS. If not, see <https://www.gnu.org/licenses/>.
;
maclib Z80
FALSE equ 0
TRUE equ NOT FALSE
MEMTOP equ 64 ; Top of addressable memory (up to 64k)
CMD equ 100h ; Load shell to here
CTRLC equ 3
CTRLS equ 19
CTRLZ equ 26
BS equ 8
TAB equ 9
LF equ 10
CR equ 13
EOF equ CTRLZ
ESCAP equ 27
RUBOUT equ 127
WARM equ 0 ; Warm boot vector
IOBYTE equ 3 ; IOBYTE address
CDISK equ 4 ; Active disk
DOSVEC equ 5 ; DOS vector
; Structure offset equates for DPB
DPB$SIZ equ 51 ; Total size of structure
DPB$OFF equ 11 ; Absolute offset from start of sector
DPB$BYTESPERSEC equ 0 ; (2) Bytes per sector
DPB$SECPERCLUST equ 2 ; (1) Sectors per cluster
DPB$RESERVEDSEC equ 3 ; (2) Reserved sectors
DPB$NUMFATS equ 5 ; (1) Number of FATs
DPB$ROOTENTCNT equ 6 ; (2) Root Directory Entries
DPB$TOTSEC16 equ 8 ; (2) Total sectors 16-bit value
DPB$MEDIATYPE equ 10 ; (1) Media type (0xF8 fixed, 0xF0 removable)
DPB$FATSIZE equ 11 ; (2) Sectors taken by one FAT
DPB$SECPERTRK equ 13 ; (2) Sectors per track
DPB$NUMHEADS equ 15 ; (2) Number of heads
DPB$HIDDSEC equ 17 ; (4) Hidden sectors before partition
DPB$TOTSEC32 equ 21 ; (4) Total sectors 32-bit value
DPB$DRVNUM equ 25 ; (1) Drive number, 80h or 0
;RESERVED 26
DPB$BOOTSIG equ 27 ; (1) Boot sig is 29h
DPB$VOLID equ 28 ; (4) Volume serial number
DPB$VOLLABEL equ 32 ; (11) Volume label (11 characters)
DPB$FILESYSTYPE equ 43 ; (8) File system type 'FAT12 ' etc
; Structure for FCB
;
; 00 F1 F2 F3 F4 F5 F6 F7 F8 T1 T2 T3 EX S1 S2 RC
; FL FL OF 00 CC CC IX IX DD DD CL CL LE LE LE LE
; CR RN RN RN
;
; 00 - user number (zero)
; Fx - File name
; Tx - File type
; EX - Extent number (zero)
; S1 - Last record byte count
; S2 - Extent number (high bits)
; RC - record count
; FL - Flags, file number high 5 bits
; OF - File number, low 8 bits
; CC - Current cluster (internal to OS)
; IX - Cluster index (internal to OS)
; DD - DOS Date
; CL - DOS Cluster
; LE - DOS Length
; CR - Current record
; RN - Random record access
USRFCB equ 05Ch ; Location of User FCB
FCBDSK equ 0 ; Drive letter to access (0=current)
FCBNAM equ 1 ; File name
FCBEXT equ 9 ; File extension
FCBEX equ 12 ; File extent
FCBS1 equ 13 ; Bytes in current record
FCBS2 equ 14 ; Module number (512kB block)
FCBRC equ 15 ; Record Count
FCBFL equ 16 ; Flags and high directory entry
FCBOF equ 18 ; Low directory entry
FCBCUR equ 20 ; Current cluster
FCBIDX equ 22 ; Current cluster index
FCBTIME equ 22 ; DOS Time (shared with index)
FCBDATE equ 24 ; DOS Date
FCBCL equ 26 ; DOS Cluster
FCBLEN equ 28 ; DOS Length
FCBCR equ 32 ; Current Record
FCBRN equ 33 ; Random record to access
; Structure for FAT directory entries
; FN FN FN FN FN FN FN FN EX EX EX AT 00 C0 C1 C1
; CD CD AD AD 00 00 MT MT MD MD CL CL LN LN LN LN
;
; FN - File Name
; EX - File extension
; AT - File attributes
; C0 - Creation time 1/10th seconds
; C1 - Creation time 2 seconds
; CD - Creation date
; AD - Access date
; MT - Modification time
; MD - Modification date
; CL - Start cluster
; LN - File length
DIRNAME equ 0 ; File name
DIREXT equ 9 ; File extension
DIRATTR equ 11 ; Attributes
DIRCL equ 26 ; Start cluster
DIRLEN equ 28 ; File length
; Offset for beginning of partition start sector in MBR
PART0 equ 454 ; Bytes offset for partition begin
phase (MEMTOP-8)*1024
jmp wdos ; Jump vector for compatibility
; Default FCB to load shell
fcb: db 1,'CLI COM'
dw 0,0,0,0,0,0,0,0,0,0,0,0
db 0
; Copied to here to load CLI.COM
fcbi: db 0,' '
dw 0,0,0,0,0,0,0,0,0,0,0,0
db 0
; Main function lookup table
jtab: dw reload ; 0 00h Warm Boot - wdoswarm.asm
dw conina ; 1 01h Console input - wdosterm.asm
dw cout ; 2 02h Console output - "
dw punch ; 3 03h papertape punch - "
dw readera ; 4 04h papertape reader - "
dw list ; 5 05h List output (printer) - bios.asm
dw dcons ; 6 06h Direct console output - wdosterm.asm
dw giobyt ; 7 07h Get I/O byte - "
dw siobyt ; 8 08h Set I/O byte - "
dw print ; 9 09h Print string, '$' terminated - "
dw input ; 10 0Ah console line input - "
dw cstat ; 11 0Bh Console status - "
dw vers ; 12 0Ch Version number - wdos.asm
dw dreset ; 13 0Dh Reset disks - wdosdisk.asm
dw select ; 14 0Eh Select disk - "
dw fopen ; 15 0Fh Open file/directory - wdosfile.asm
dw fclose ; 16 10h Close file/directory - "
dw search ; 17 11h Search for file - "
dw next ; 18 12h Search for next occurance - "
dw delete ; 19 13h Delete file - "
dw readn ; 20 14h Read next record - "
dw writen ; 21 15h Write next record - "
dw create ; 22 16h Create file/directory - "
dw rename ; 23 17h Rename file/directory - "
dw unsupp ; 24 18h Return bitmap of logged in drives
dw cdrive ; 25 19h Return current drive
dw setdma ; 26 1Ah Set DMA address - wdosfile.asm
dw unsupp ; 27 1Bh Return address of allocation map
dw unsupp ; 28 1Ch Set current disk to R/O
dw unsupp ; 29 1Dh Return bitmap of R/O drives
dw unsupp ; 30 1Eh Set file attribs
dw getdpb ; 31 1Fh Retrieve DPB
dw usern ; 32 20h Get/set user number
dw rdrnd ; 33 21h Read Random - wdosfile.asm
dw wrrnd ; 34 22h Write random - "
dw fsize ; 35 23h File size - "
JTOTAL equ ($-jtab)/2+2
ifdef DEBUG
; Extra stack space if debugging
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
endif
dw 0,0,0,0 ; Local stack
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
dw 0,0,0,0
pstack: dw 0 ; Store program's stack pointer
param: dw 0 ; Incoming parameters from DE
rval: dw 0 ; Return value in HL
; 0=Uninitialised, 1=FAT12, 2=FAT16
disk: db 0FFh ; Current disk dpbadr points at (FF is none)
atype: db 0 ; Access type (0=data, 1=FAT)
stale: db 0 ; Data buffer has data written (1=data,2=FAT)
; Data calculated from current disk
dpbadr: dw 0 ; DPB address
bshf: db 0 ; Block shift factor
ashf: db 0 ; Allocation shift factor
pchkd: db 0 ; Indicates we've already checked partitions
fatsec: dw 0 ; First sector of FAT region
rtsect: dw 0 ; First sector of root directory region
datsec: dw 0 ; First sector of data region
poffs: dw 0,0 ; Partition offset (0 for unpartitioned)
volsiz: dw 0,0 ; Total volume size
ctotal: dw 0 ; Total number of clusters in volume
; Data for current location in FAT chain
recrd: dw 0 ; Current record (internal use)
index: dw 0 ; Current index of cluster (compared to FCB)
; Data for disk operations
dsect: dw -1,-1 ; Data sector loaded
fsect: dw -1,-1 ; FAT sector loaded
datadr: dw 0 ; Data buffer address
fatadr: dw 0 ; FAT buffer address
fatmsk: dw 0 ; Mask to clear odd/even FAT12 entries
; Disk bitmaps
logdsk: dw 0 ; Currently logged in disks bitmap MSB=A:
rodsk: dw 0 ; Current disks marked read-only MSB=A:
fatype: dw 0 ; FAT12/16 flag per disk 0=FAT12
curfat: db 0 ; FAT12/16 Flag for current disk
; Directory search data
erasf: db 0 ; Non-zero stops search on erased file
curdir: dw 0 ; Current offset within loaded sector
diridx: dw 0 ; Current directory index (0,1,2...)
dirmax: dw 0 ; Maximum number of root entries
dirsec: dw 0,0 ; Current directory sector
dmaadr: dw 80h ; DMA address
wdos: sded param ; Store parameter pointer
ifdef DEBUG
ifdef PRINTALL
call prreg
endif
endif
lxi h, 0
shld rval ; Default return value
sspd pstack ; Keep user SP
lxi sp, pstack ; Set new one
pushix ; Keep IX/IY
pushiy
lixd param ; Point IX to parameters
lxi h, osret ; Return to here
push h
; Check for allowable function calls
mov a, c
cpi JTOTAL
jnc unsupp ; Return if unknown (via unsupp)
; Get address of function call
mov l, c ; H,L = 0,C (function)
mvi h, 0
dad h ; *2 for 2 bytes per entry
lxi d, jtab
dad d
mov e, m ; DE = address of code
inx h
mov d, m
lhld param ; Param to DE if needed
xchg
pchl ; Jump to routine
; Restore program stack pointer and return via it
osret: popiy ; Restore IX/IY
popix
ifdef DEBUG
ifdef PRINTALL
lhld rval ; Return value
mov a, l
mov b, h
call prreg
call dbcrlf
endif
endif
lspd pstack
lhld rval ; Return value
mov a, l
mov b, h
ret
unsupp:
ifdef DEBUG
push b
mvi c, '!'
call bugout
pop b
call prreg
; halt
endif
lxi h, 00FFh ; Always error
shld rval
ret
; Return the current user number (always 0)
; Ignores any attempt to set the user
usern: lxi h, 0
shld rval
ret
; DOS encountered an error. Print message and wait
; for a key.
doserr: push d ; Keep error message to print
call crlf
lda disk ; Current disk in use
cpi 0FFh ; Invalid?
jrnz .1
mvi a, '?' ; Unknown disk???
jr .2
.1: adi 'A' ; Make it a character
.2: sta diskm ; Store to message
lxi d, errm ; Print it
call print
pop d ; Restore error message
call print
call conin ; Wait for a key
push psw ; Newline
call crlf
pop psw
cpi CTRLC
jz WARM ; Warm boot
; Else return with an error
ori 0FFh ; Return with error
sta rval
ret ; If not ctrl-c, ignore error
;
; Function 0Ch (12)
;
; Return version
;
vers: xra a
mov b, a
mvi a, 022h
sta rval
ret
;
; Clear data at DE for B bytes
;
clrde: xra a
fill: stax d ; Also used to fill address with data
inx d
djnz fill
ret
clrhl: xra a
.1: mov m, a
inx h
djnz .1
ret
;
; External assembler files included here
;
include wdoswarm.asm
include wdosterm.asm
include wdosfile.asm
include wdosfat.asm
include wdosdisk.asm
;
;
; Debug
;
;
ifdef DEBUG
dmpdma: push h
push d
push b
push psw
lhld dmaadr
mvi c, 8
.l1: mvi b, 16
.l: mov a, m
inx h
push b
call phex
call dbsp
pop b
djnz .l
push b
call dbcrlf
pop b
dcr c
jrnz .l1
call dbcrlf
pop psw
pop b
pop d
pop h
ret
prfcb: push h
push d
push b
push psw
lhld param
inx h
mvi b, 11
.prl: mov c, m
inx h
call bugout
djnz .prl
call dbsp
mvi b, (21h - 0Ch)
.prl1: mov a, m ; EX
inx h
call phex
call dbsp
djnz .prl1
call dbcrlf
pop psw
pop b
pop d
pop h
ret
prreg: push h
push d
push b
push psw
lxi h,1
dad sp
mvi b, 8 ; Print stack
.1: mov a, m
call phex
mov a, b ; Print a space every other digit
ani 1
jz .2
call dbsp
lxi d, 4
dad d
.2: dcx h
djnz .1
call dbcrlf
pop psw
pop b
pop d
pop h
ret
phex: push psw ; Will use A twice
rar ; Shift upper to lower nibble
rar
rar
rar
call phex1 ; Print it
pop psw ; Restore original Acc
phex1: ani 00Fh ; Mask off high nibble
adi 090h ; Decimal adjust for ASCII
daa
aci 040h
daa
mov c, a ; Print it
jmp bugout
; Debug CRLF
dbcrlf: mvi c, CR
call bugout
mvi c, LF
jmp bugout
dbsp: mvi c, ' '
jmp bugout
endif
; Messages
;
; Message followed by a 0 is non-fatal
; Message followed by a 1 is fatal, Ctrl+C
; must be pressed.
errm: db 'Error on '
diskm: db ' : $' ; Filled by doserr
nfmsg: db 'Unable to load shell$'
datam: db 'data error$'
selm: db 'no drive$'
filem: db 'file '
ronlym: db 'read only$'
fmtm: db 'format$'
; Stack to load shell
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
stack equ $
if BIN
rept (MEMTOP-4)*1024-$
db 0
endm
else
org (MEMTOP-4)*1024
endif
;
; BIOS locations
;
bios: equ (MEMTOP-4)*1024
wboot: equ bios+3
const: equ bios+6
conin: equ bios+9
conout: equ bios+12
list: equ bios+15
punch: equ bios+18
reader: equ bios+21
seldsk: equ bios+24
seek: equ bios+27
read: equ bios+30
write: equ bios+33
listst: equ bios+36
ifdef DEBUG
bugout: equ bios+39
endif
end