;VOLUMES - Utility for displaying logical drive information
;          on my 8080 computer.
;
;Version 1.0
;08-19-2024
;Jerry Davis
;
   CPU 8080 ;Specify architecture
   PAGE 0   ;Turn off page breaks in listings
;
;
;BIOS Routines
;
wboot   equ   0f403h   ;warm start
const   equ   0f406h   ;console status
conin   equ   0f409h   ;console character in
conout  equ   0f40ch   ;console character out
seldsk  equ   0f41bh   ;select disk
settrk  equ   0f41eh   ;set track number
setsec  equ   0f421h   ;set sector number
setdma  equ   0f424h   ;set dma address
read    equ   0f427h   ;read disk
write   equ   0f42ah   ;write disk
;
;
;BIOS Variables
;
volumes  equ 15         ;number of volumes in the system
;
;
   org 100h
;
;
start:
   lxi d, msg_start    ;point to start message
   call print          ;print it
   call print_vols     ;print the list of volumes
   ret                 ;return to CCP
;
;
;Print the list of volumes
;
print_vols:
   call getvols        ;get volume labels
   lda volerr          ;check for volume label error
   cpi 0               ;Success?
   jz pvol000          ;move on if no error
   mvi c, bclose       ;bdos close function call
   lxi d, volfcb       ;point to volume FCB
   call bdos           ;close the file
   lxi d, msg_volerr   ;point to volume label error
   call print          ;print it
   jmp pvolexit        ;exit to CCP
pvol000:
   lxi d, msg_crlf     ;point to new line
   call print          ;print it
   lxi d, msg_header   ;point to volume list header
   call print          ;print it
pvol001:
   call volline        ;print drive A map and label
   lda count           ;get drive counter
   cpi volumes-1       ;done?
   jz pvolexit         ;exit if done
   inr a               ;increment counter
   sta count           ;save it
   jmp pvol001         ;do again
pvolexit:
   lxi d, msg_crlf     ;point to new line
   call print          ;print it
   ret                 ;exit to CCP
;
;
volline:
   mvi c, 2            ;print 2 spaces
   call print_spc
   lda count           ;get drive counter
   mov c, a            ;put it in C
   call print_dec      ;print it
   lxi d, msg_volsize  ;point to volume size
   call print          ;print it
   lda count           ;point to volume number
   push h              ;Save HL on the stack
   call getlabel       ;get the volume label in DE
   pop h               ;get HL from the stack
   call print          ;print it
   lxi d, msg_crlf     ;point to new line
   call print          ;print it
   ret
;
;
getlabel:
   lxi h, labels       ;point to labels list
   lxi b, 16           ;label increment
gl001:
   cpi 0               ;done?
   jz glexit           ;if so then exit
   dad b               ;move pointer to next label
   dcr a               ;decrement vdrive counter
   jmp gl001           ;next label
glexit:
   xchg                ;put HL in DE
   ret                 ;exit
;
;
;Print one or two digit decimal number from 4 bit hex
;Modifies: a, c
;
print_dec:
    mov a, c         ;move C into A
    ani 00fh         ;mask off high bits
    adi 0            ;for decimal adjust
    daa              ;decimal adjust A
    push psw         ;save A on the stack
	mov c, a         ;save it in C
	ani 0f0h         ;mask off low bits
    rrc              ;shift to low bits
	rrc
	rrc
	rrc
    adi '0'          ;convert to ASCII
	mov c, a         ;save it in C
    call conout      ;print it
pd001:
    pop psw          ;restore A from the stack
	ani 00fh         ;mask off high bits
	adi '0'          ;convert to ASCII
	mov c, a         ;put it in C
    call conout      ;print it
    ret
;
;
;Print number space characters in C
;
print_spc:           ;print space characters on the console
    mov b, c         ;save count in B
pspc001:
    mvi c, ' '       ;space character
	call conout      ;print it
    dcr b            ;decrement B
    jnz pspc001      ;do over
pspcend:
	ret              ;and exit
;
;
;Print a null terminated string
;
print:               ;print a message on the console
	ldax d           ;get char pointed to by D into A
	cpi 0            ;end of string?
	jz pend          ;exit if end of string
	mov c, a         ;move char into C for console out
	call conout      ;print it
	inx d            ;point to next character
	jmp print         ;repeat
pend:
	ret              ;and exit
;
;
;Open the volumes file 'volumes.dat' and read in the volume
;labels for each virtual disk.
;Returns 0ffh or non-zero on fail, 0 on success.
;
bopen  equ 15  ;BDOS open function
bclose equ 16  ;BDOS close function
bread  equ 20  ;BDOS sequential read function
bsdma  equ 26  ;BDOS set DMA 
bdos   equ 5   ;BDOS jump address
;
getvols:
   mvi c, bopen            ;bdos open function call
   lxi d, volfcb           ;point to volume FCB
   call bdos               ;open the file
   cpi 0ffh                ;file error?
   jz gverror              ;signal error and exit
   mvi c, bsdma            ;bdos set dma function call
   lxi d, labels           ;point to volumes buffer
   call bdos               ;set dma for volume list
   mvi c, bread            ;bdos read function call
   lxi d, volfcb           ;point to volume fcb
   call bdos               ;read one record
   cpi 0                   ;any errors?
   jnz gverror             ;signal error and exit
   mvi c, bsdma            ;bdos set dma function call
   lxi d, labels+128       ;point to volumes buffer
   call bdos               ;set dma for volume list
   mvi c, bread            ;bdos read function call
   lxi d, volfcb           ;point to volume fcb
   call bdos               ;read one record
   cpi 0                   ;any errors?
   jnz gverror             ;signal error and exit
   mvi c, bclose           ;bdos close function call
   lxi d, volfcb           ;point to volume FCB
   call bdos               ;close the file
   cpi 0                   ;any errors?
   jnz gverror             ;signal error and exit
   ret                     ;done
;
;
gverror:
   mvi a, 1                ;signal volume label read error
   sta volerr              ;save it
   ret
;
;
msg_start:
   dw 0d0ah
   db 'VOLUMES v1.0 - List virtual disks'
   dw 0d0ah
   db 0
;
;
msg_volerr:
   db '*** Error reading volume labels!'
   dw 0d0ah
   db 0
;
;
msg_header:
   db 'Volume  Size  Label', 0dh, 0ah
   db '------  ----  ---------------', 0dh, 0ah
   db 0
;
msg_volsize:
   db '     8MB  '
   db 0
;
msg_crlf:
   dw 0d0ah
   db 0
;
count  db 0                  ;physical drives to display
;
volerr: db 0                 ;volume error flag
;
volfcb:
fcbdisk: db 1                ;always use drive A
fcbname: db 'VOLUMES', 20h   ;volume labels file name
fcbtype: db 'DAT'            ;volume labels file type
fcbextn: db 0                ;volume labels extent
fcbresv: db 0,0              ;reserved
fcbrecs: db 0                ;volume labels records used
fcbaloc: dw 0,0,0,0,0,0,0,0  ;allocation blocks
fcbsrec: db 0                ;sequential record number
fcbrrec: dw 0                ;random record number
fcbreco: db 0                ;random record overflow
;
labels ds 256                ;storage for volume labels
;
   end