; DSKPRAM.ASM
;
;File was corrupted in FOGCPM Library; corrected 5-90, wb.
;Corrections indicated with <<mod. 5-90>>
;
VER     EQU     11
; 
; DSKPRAM intended use is to determine the the values of the DISK
; PARAMETER BLOCK and the SKEW TRANSLATION TABLE of a system alien
; to AMPRO MULTIDSK program.  DSKPRAM is to be run on the system
; where the disk values are not known.  After the host system 
; parameters are are determined ESET may be used to set up the E: 
; drive on the AMPRO system. 
;
; Putting an NON-AMPRO disk into the AMPRO system and running DSKPRAM
; on that disk will not return useful disk parmeters.  DSKPRAM must
; be run on the 5.25" CP/M system that you want to find the prameters 
; for.
;
; DSKPRAM displays the disk parameter block and the skew translation
; table maintained in the target cp/m 2.2 bios in any selected system
;
; DSKPRAM.ASM is the combination of DPB.ASM and SKEW.ASM by 
; Robert C. Kuhman, Sysop of the Cro's Nest RCP/M.  Both are   
; COPYRIGHT (c) 1984, by Robert C. Kuhman and released to the public
; domain for non-profit purposes only, not to be sold, nor bundled 
; with other software for sale.  Synthesis of the two programs into
; this version was performed by Fred Willink.
;
;****************************************************************
;
; Revisions:
;               Ver 1.0 as of 16 Nov 1984, Fred Willink
;               Ver 1.1        4 Dec 1984, Rick Lehrbaum
;
;****************************************************************
;
BOOT    EQU     0               ;
BDOS    EQU     05H             ;
FCB1    EQU     5CH             ;
;
;  other equates
;
ACROSS  EQU     8
;
; ampro bios disk id save area
;
; ascii equates
;
BELL    EQU     07H             ; bell
TAB     EQU     09H             ; horz tab
LF      EQU     0AH             ; line feed
CR      EQU     0DH             ; carriage return
SPC     EQU     20H             ; space
;
        ORG     100H
;
START:  LXI     H,0
        DAD     SP              ; hl=ccp stack pointer
        LXI     SP,STACK        ; set up local stack
        PUSH    H               ; save the ccp pointer for return
        LXI     H,SIGNON
        CALL    COSTR
TEST:   LDA     FCB1+1
        CPI     '/'
        JZ      HELP            ; help
        CPI     '?'
        JZ      HELP
        CALL    DPB
        CALL    SKEW
        JMP     EXIT
;
HELP:   LXI     H,HLPMSG        ; point to help message
        CALL    COSTR           ; display help
;
; exit no warm boot
;
EXIT:   POP     H               ; recover ccp"s stack ptr
        SPHL
        RET
;
DPB:    LDA     FCB1            ; drive code given ?
        DCR     A               ; convert a=1 to 0
        JP      DPB2
        CALL    FCN25
DPB2:   MOV     E,A             ; save for select
        ADI     'A'             ; make drive code printable
        STA     DRIVE
        CALL    FCN14
        CALL    FCN31
        PUSH    H               ; save it for dump
;
        LXI     D,SPT           ; make dph values printable
        CALL    CVT2
        LXI     D,BSH
        CALL    CVT1
        LXI     D,BLM
        CALL    CVT1
        LXI     D,EXM
        CALL    CVT1
        LXI     D,DSM
        CALL    CVT2
        LXI     D,DRM
        CALL    CVT2
        LXI     D,AL0
        CALL    CVT1
        LXI     D,AL1
        CALL    CVT1
        LXI     D,CKS
        CALL    CVT2
        LXI     D,OFF
        CALL    CVT2
;
        LXI     H,DSPLAY        ; dph table
        CALL    COSTR           ; print it all
        POP     H
        CALL    HEXADR          ; print bios address of dph
        LXI     H,HEX
        CALL    COSTR
        CALL    COCRLF
        RET
;
SKEW:   LDA     FCB1            ; see if drive was specified
        DCR     A               ; test ff=no
        JP      REC2            ; yes, select drive
        CALL    FCN25           ; no, get current drive
REC2:   MOV     E,A
        MOV     C,A
        CALL    FCN14           ; select drive
        CALL    FCN31           ; get address of dph
        MOV     E,M
        INX     H
        MOV     D,M
        XCHG
        SHLD    NRECS           ; save dph address for records per track
        MVI     A,24            ; offset for seldsk:
        CALL    BIOS            ; hl=dph, set de=xlate table
        MOV     E,M
        INX     H
        MOV     D,M             ; de=dph
        XCHG                    ; dph in hl
        SHLD    DPHADR          ; and save
        MOV     A,L             ; get low byte
        ORA     H               ; or with high
        JNZ     SHOWD           ; if zero no translate done
        LXI     H,NXLATE        ; no translate message
        CALL    COSTR
        RET
;
SHOWD:  LXI     H,TBLMSG        ; for skew table
        CALL    COSTR           ; display
        MVI     A,20            ; number of entries
        STA     POSIT           ; set counter
        LHLD    DPHADR          ; get dph address
        SHLD    LAST            ; save it
        JMP     ENTRY
;
MORE:   LHLD    LAST            ; get last position
        INX     H               ; update and
        SHLD    LAST            ; save it
ENTRY:  MOV     E,M             ; get byte
        MVI     D,0             ; zero d
        MOV     A,E             ; value in a
        CPI     27              ; largest value
        JNC     ZERFIL          ;
        CPI     1               ; start of table
        JZ      WHERE           ; what position
        CPI     0               ;
        JNZ     NOPE            ; none of those
WHERE:  LDA     POSIT           ; see where in table
        CPI     20              ; first position of 20
        JNZ     ZERFIL          ; see if need zeros
NOPE:   XCHG                    ; hl has value
        CALL    DECOUT          ; print decimal value
        LDA     POSIT           ; get count
        CPI     0               ; see if done
        JZ      DONE            ; yes, return
        MVI     A,','           ; insert comma
        CALL    COUT
        CALL    COSPAC          ; insert space
        LDA     POSIT           ; see if done
        CPI     0
        JZ      ZERFIL          ; fill remainder
NOTDON: DCR     A               ; count down
        STA     POSIT           ; and save
        JMP     MORE
;
ZERFIL: LDA     POSIT           ; how many zero's
        CPI     0
        JZ      DONE            ; done if zero
        DCR     A               ; count down
        STA     POSIT           ; and save
        MVI     A,'0'
        CALL    COUT            ; print '0'
        LDA     POSIT
        CPI     0               ; see if through now
        JZ      DONE
        MVI     A,','
        CALL    COUT            ; print ','
        CALL    COSPAC          ; print space
        JMP     ZERFIL
;
DONE:   CALL    COCRLF
        LXI     H,DPH           ; trailer message for address
        CALL    COSTR           ; display
        LHLD    DPHADR
        CALL    HEXADR          ; print address of offset table
        LXI     H,HEX
        CALL    COSTR
        CALL    COCRLF
        RET
;
; convert binary in hl to ascii decimal
;
DECOUT: MVI     B,0             ; leading zero fill
        LXI     D,-100
        CALL    SUBTR           ; hundreds
        LXI     D,-10
        CALL    SUBTR           ; tens
        MOV     A,L
        ADI     '0'             ; ascii bias
        JMP     COUT            ; print and return to caller
;
; subtract powers of 10
;
SUBTR:  MVI     C,'0'-1         ; ascii count
SUBT2:  INR     C
        DAD     D               ; add neg number
        JC      SUBT2
;
; one to many add one back
;
        MOV     A,D             ; complement
        CMA                     ; de
        MOV     D,A
        MOV     A,E
        CMA
        MOV     E,A
        INX     D
        DAD     D
        MOV     A,C             ; get count
;
; check for zero
;
        CPI     '1'             ; less than 1?
        JNC     NZERO           ; no
        MOV     A,B             ; check 0 flag
        ORA     A
        MOV     A,C             ; restore
        RZ                      ; skip leading zero
        JMP     COUT            ; print character
;
; set flag for non-zero character
;
NZERO:  MVI     B,0FFH          ; set to zero
        JMP     COUT            ; print
        RET
;
; select disk, 'e' has drive number
;
FCN14:  PUSH    B
        PUSH    D
        PUSH    H
        MVI     C,14
        CALL    BDOS
        POP     H
        POP     D
        POP     B
        RET
;
; get current disk number, returns current disk in 'a'
;
FCN25:  PUSH    B
        PUSH    D
        PUSH    H
        MVI     C,25            ; no drive given, get current disk
        CALL    BDOS
        POP     H
        POP     D
        POP     B
        RET
;
; get disk parameters, returns 'hl'=dpb address
;
FCN31:  PUSH    B
        PUSH    D
        MVI     C,31            ; hl = dpb for current disk
        CALL    BDOS
        POP     D
        POP     B
        RET
;
CVT2:   PUSH    H               ; display 16 bit integer
        INX     H
        CALL    CVT1
        XTHL
        CALL    CVT1
        POP     H
        RET
;
CVT1:   MOV     A,M             ; display byte at 'hl'
        INX     H
CVT1A:  CALL    HEXBYT          ; a,c=ascii display
        STAX    D
        INX     D
        MOV     A,C
        STAX    D
        INX     D
        RET
;
; Subroutine to print hl as an address in hex
;
HEXADR: MOV     A,H
        CALL    COHEX
        MOV     A,L
        CALL    COHEX
        RET
;
; print the hex byte in 'a'
;
COHEX:  PUSH    PSW             ; save byte
        CALL    HEXLFT          ; get left half
        CALL    COUT            ; and print
        POP     PSW             ; restore byte
        CALL    HEXRHT          ; right half and
        CALL    COUT            ; print
        RET
;
HEXLFT: RAR                     ; make left nibble
        RAR
        RAR
        RAR
;
HEXRHT: ANI     0FH             ; make right nibble
        CPI     0AH
        JC      HEXLR
        ADI     'A'-3AH
;
HEXLR:  ADI     '0'
        RET
;
; suboutrine to return the hex value of 'a',
; least significant half in 'c', most significant in 'a'.
; used when ascii-hex is to be stored.
;
HEXBYT: PUSH    PSW             ; save
        CALL    HEXRHT          ; get right nibble
        MOV     C,A             ; save in c
        POP     PSW             ; restore and get
        CALL    HEXLFT          ; left nibble
        RET
;
; subroutine to write 'a' to console  <<mod. 5-90>>
COUT:   PUSH    B               ; <<mod. 5-90>>
        PUSH    D
        PUSH    H
        ANI     7FH             ; strip bit 7
        MOV     E,A
        MVI     C,2             ; cp/m fcn 2
        CALL    BDOS            ; 
        POP     H
        POP     D
        POP     B
        RET
;
; print cr,lf to the console
;
COCRLF: PUSH    PSW
        MVI     A,CR            ; carriage return
        CALL    COUT            ; print it
        MVI     A,LF            ; line feed
        CALL    COUT            ; and print it
        POP     A
        RET
;
; subroutine to write a space to the console
;
COSPAC: PUSH    PSW
        MVI     A,SPC           ; space
        CALL    COUT            ; and print it
        POP     PSW
        RET
;
; subroutine to write bytes addressed by hl, terminated by last byte with
; 80 bit set.
;
COSTR   MOV     A,M             ; get byte
        CALL    COUT            ; print
        MOV     A,M             ; again and test
        RLC                     ; for bit 7 set
        RC                      ; yes, return
        INX     H               ; next byte
        JMP     COSTR           ; and continue
;
; bios service, offset in 'a'
;
BIOS:   PUSH    B
        PUSH    D
        LHLD    BOOT+1          ; get warm boot address
        ADD     L               ; add offset to wboot
        MOV     L,A             ; to address of service
        PUSH    H               ; save it
        LXI     H,BIORET        ; return address
        XTHL
        PCHL
;
BIORET: POP     D
        POP     B
        RET
;
;  message strings
;
SIGNON: DB      CR,LF
        DB      CR,LF,'DSKPRAM ver. ',VER/10+'0','.',VER MOD 10+'0'
        DB      CR,LF,'Copyright (c) 1984 Robert C. Kuhman'
        DB      CR,LF,LF+80H
;
HEX:    DB      ' hex',cr,lf+80h
;
DSPLAY: 
        DB      'DPB table for drive '
DRIVE:  
DS      1
        DB      ':',CR,LF,LF
        DB      'SPT:  '
SPT:    DS      4
        DB      'H',TAB,'Sectors per track.',cr,lf
        DB      'BSH:  '
BSH:    DS      2
        DB      'H',TAB,'Block shift.',cr,lf
        DB      'BLM:  '
BLM:    DS      2
        DB      'H',TAB,'Block mask.',cr,lf
        DB      'EXM:  '
EXM:    DS      2
        DB      'H',TAB,'Extent mask.',cr,lf
        DB      'DSM:  '
DSM:    DS      4
        DB      'H',TAB,'Disk size-1.',cr,lf
        DB      'DRM:  '
DRM:    DS      4
        DB      'H',TAB,'Directory entries-1.',cr,lf
        DB      'ASV0: '
AL0:    DS      2
        DB      'H',TAB,'Directory group allocation 0.',cr,lf
        DB      'ALV1: '
AL1:    DS      2
        DB      'H',TAB,'Directory group allocation 1.',cr,lf
        DB      'CKS:  '
CKS:    DS      4
        DB      'H',TAB,'Check size.',cr,lf
        DB      'OFF:  '
OFF:    DS      4
        DB      'H',TAB,'Offset (number of reserve tracks).',cr,lf
;
DMPMSG: DB      'DPB address =',SPC+80H
;
NXLATE: DB      BELL,'Diskette needs no translation.',cr,lf+80h
;
TBLMSG: DB      'Skew table decimal values.',cr,lf+80h
;
DPH:    DB      'DPH address =',SPC+80H
; User help
;
HLPMSG: 
DB      CR,LF,'              >>> DSKPRAM.COM - H E L P <<<'
DB      CR,LF
DB      CR,LF,'DSKPRAM displays DPB and skew tables for a floppy drive.'
DB      CR,LF,'Information provided can be used as input for ESET.COM,'
DB      CR,LF,'allowing the AMPRO''s "E:" drive to read and write non-AMPRO'
DB      CR,LF,'diskette formats not included in MULTIDSK.COM.'
DB      CR,LF
DB      CR,LF,'                         SYNTAX'
DB      CR,LF
DB      CR,LF,'A0>DSKPRAM <RET>  --> DPB and SKEW table for default drive'
DB      CR,LF,'A0>DSKPRAM d:     --> Tables for selected drive'
DB      CR,LF,'A0>DSKPRAM ? or / --> Displays this message'
DB      CR,LF
DB      CR,LF,'                          NOTES'
DB      CR,LF
DB      CR,LF,'1. DSKPRAM must be run in the alien system, not the'
DB      CR,LF,'   AMPRO system.  It will not provide useful data when'
DB      CR,LF,'   used in the AMPRO on a non-AMPRO format diskette.'
DB      CR,LF
DB      CR,LF,'2. DSKPRAM does not work in some CP/M 2.2 systems.'
DB      CR,LF+80H
;
NRECS:  DS      2
DPHADR: DS      2
POSIT:  DS      1
LAST:   DS      2
;
        DS      30
STACK:  EQU     $
;
        END
