Browse Source

Early partition table support

Adding infrastructure for partition table support.  Backward compatible.  Not ready for end user usage yet.

Bumped version to 3.1.1 to demarcate this change.
patch
Wayne Warthen 6 years ago
parent
commit
ee0fac37f9
  1. 1
      Binary/Clean.cmd
  2. 5
      Doc/ChangeLog.txt
  3. 10
      Source/Apps/Assign.asm
  4. 12
      Source/Apps/Timer.asm
  5. 139
      Source/BPBIOS/diskdefs
  6. 277
      Source/CBIOS/cbios.asm
  7. 12
      Source/CBIOS/util.asm
  8. 442
      Source/CPM3/biosldr.z80
  9. 2
      Source/CPM3/boot.z80
  10. 482
      Source/CPM3/diskio.z80
  11. 4
      Source/CPM3/genbnk.dat
  12. 3
      Source/CPM3/move.z80
  13. 3
      Source/CPM3/optzpm.lib
  14. 2
      Source/CPM3/util.z80
  15. 139
      Source/HBIOS/diskdefs
  16. 548
      Source/HBIOS/romldr.asm
  17. 26
      Source/Images/Build.cmd
  18. 38
      Source/Images/BuildFD.ps1
  19. 53
      Source/Images/BuildHD.ps1
  20. 40
      Source/Images/BuildNew.cmd
  21. 46
      Source/Images/Makefile
  22. 139
      Source/Images/diskdefs
  23. BIN
      Source/Images/hd_prefix.dat
  24. 4
      Source/ver.inc
  25. 4
      Source/ver.lib
  26. 139
      Tools/cpmtools/diskdefs

1
Binary/Clean.cmd

@ -2,6 +2,7 @@
setlocal
if exist *.bin del *.bin
if exist *.dat del *.dat
if exist *.com del *.com
if exist *.img del *.img
if exist *.rom del *.rom

5
Doc/ChangeLog.txt

@ -1,3 +1,8 @@
Version 3.1.1
-------------
- WBW: Version bumped due to pervasive changes
- WBW: Preliminary support for hard disk partition support (backward compatible)
Version 3.1
-----------
- WBW: Refactored ROM Loader

10
Source/Apps/Assign.asm

@ -22,7 +22,8 @@
; 2016-04-08 [WBW] Determine key memory addresses dynamically
; 2019-08-07 [WBW] Fixed DPB selection error
; 2019-11-17 [WBW] Added preliminary CP/M 3 support
; 2019-12-24 [WBW] Fixed location of BIOS save area
; 2019-12-24 [WBW] Fixed location of BIOS save area\
; 2020-04-29 [WBW] Updated for larger DPH (16 -> 20 bytes)
;_______________________________________________________________________________
;
; ToDo:
@ -546,7 +547,8 @@ dph_init2:
ld a,(hl) ; unit to A
push bc ; save loop control
push hl ; save drive map pointer
ld hl,16 ; size of a DPH structure
;ld hl,16 ; size of a DPH structure
ld hl,20 ; size of a DPH structure
call alloc ; allocate space for dph
jp c,instovf ; handle overflow error
push hl ; save DPH location
@ -1866,10 +1868,10 @@ stack .equ $ ; stack top
; Messages
;
indent .db " ",0
msgban1 .db "ASSIGN v1.1a for RomWBW CP/M, 24-Dec-2019",0
msgban1 .db "ASSIGN v1.1b for RomWBW CP/M, 29-Apr-2020",0
msghb .db " (HBIOS Mode)",0
msgub .db " (UBIOS Mode)",0
msgban2 .db "Copyright 2019, Wayne Warthen, GNU GPL v3",0
msgban2 .db "Copyright 2020, Wayne Warthen, GNU GPL v3",0
msguse .db "Usage: ASSIGN D:[=[{D:|<device>[<unitnum>]:[<slicenum>]}]][,...]",13,10
.db " ex. ASSIGN (display all active assignments)",13,10
.db " ASSIGN /? (display version and usage)",13,10

12
Source/Apps/Timer.asm

@ -41,8 +41,11 @@ rmn .equ 1 ; intended CBIOS version - minor
;
bf_sysver .equ $F1 ; BIOS: VER function
bf_sysget .equ $F8 ; HBIOS: SYSGET function
bf_sysset .equ $F9 ; HBIOS: SYSGET function
bf_sysgettimer .equ $D0 ; TIMER subfunction
bf_syssettimer .equ $D0 ; TIMER subfunction
bf_sysgetsecs .equ $D1 ; SECONDS subfunction
bf_syssetsecs .equ $D1 ; SECONDS subfunction
;
;===============================================================================
; Code Section
@ -106,6 +109,15 @@ process00:
jr process00 ; continue looking for options
;
process0:
;
; Test of API function to set seconds value
;ld b,bf_sysset ; HBIOS SYSGET function
;ld c,bf_syssetsecs ; SECONDS subfunction
;ld de,0 ; set seconds value
;ld hl,1000 ; ... to 1000
;rst 08 ; call HBIOS, DE:HL := seconds value
;
; get and print seconds value
call crlf2 ; formatting
;
process1:

139
Source/BPBIOS/diskdefs

@ -297,121 +297,158 @@ diskdef wbw_rom1024
os 2.2
end
# UNA 512KB ROM (128KB reserved, 384KB ROM Disk)
# RomWBW 720K floppy media
diskdef wbw_fd720
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom512
# RomWBW 1.44M floppy media
diskdef wbw_fd144
seclen 512
tracks 12
sectrk 64
tracks 160
sectrk 18
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# UNA 512KB ROM (128KB reserved, 896KB ROM Disk)
# RomWBW 360K floppy media
diskdef wbw_fd360
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom1024
# RomWBW 1.20M floppy media
diskdef wbw_fd120
seclen 512
tracks 28
sectrk 64
tracks 160
sectrk 15
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# RomWBW 8MB Hard Disk, LU 0-3
# RomWBW 8MB Hard Disk, first 4 slices
# Legacy format, 512 dir entries, 8,320 sectors / slice
diskdef wbw_hd0
seclen 512
tracks 65
sectrk 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 1
boottrk 16
os 2.2
end
diskdef wbw_hd1
seclen 512
tracks 130
sectrk 256
tracks 2080
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 66
boottrk 1056
os 2.2
end
diskdef wbw_hd2
seclen 512
tracks 195
sectrk 256
tracks 3120
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 131
boottrk 2096
os 2.2
end
diskdef wbw_hd3
seclen 512
tracks 260
sectrk 256
tracks 4160
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 196
boottrk 3136
os 2.2
end
# RomWBW 720K floppy media
diskdef wbw_fd720
# RomWBW 8MB Hard Disk
# New format, 1024 dir entries, 8,192 sectors / slice
# Pure filesystem image, no prefix
diskdef wbw_hd_new
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
tracks 1024
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 2
os 2.2
end
# RomWBW 1.44M floppy media
diskdef wbw_fd144
# RomWBW 8MB Hard Disk, first 4 slices
# New format, 1024 dir entries, 8,192 sectors / slice
# Assumes 256 sector (16 track) hard disk prefix
diskdef wbw_hd0_new
seclen 512
tracks 160
sectrk 18
blocksize 2048
maxdir 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 18
os 2.2
end
# RomWBW 360K floppy media
diskdef wbw_fd360
diskdef wbw_hd1_new
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
tracks 2064
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 1042
os 2.2
end
# RomWBW 1.20M floppy media
diskdef wbw_fd120
diskdef wbw_hd2_new
seclen 512
tracks 160
sectrk 15
blocksize 2048
maxdir 256
tracks 3112
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 2066
os 2.2
end
diskdef wbw_hd3_new
seclen 512
tracks 4136
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 3114
os 2.2
end

277
Source/CBIOS/cbios.asm

@ -252,9 +252,9 @@ DEVMAP:
; | | |
; +--------------------+ +-> [DPH] +-> [DPH]
; |
; V-----+-------+-------+-------+--------+-----+-----+-----+
; DPH: | XLT | 0000H | 0000H | 0000H | DIRBUF | DPB | CSV | ALV |
; +---16+-----16+-----16+-----16+------16+-+-16+-+-16+-+-16+
; V-----+-------+-------+-------+--------+-----+-----+-----+--------+
; DPH: | XLT | 0000H | 0000H | 0000H | DIRBUF | DPB | CSV | ALV | LBAOFF |
; +---16+-----16+-----16+-----16+------16+-+-16+-+-16+-+-16+------32+
; (ONE DPH PER DRIVE) | | |
; | | +----------+
; | | |
@ -289,6 +289,7 @@ DPBMAP:
.DW DPB_FD360 ; MID_FD360
.DW DPB_FD120 ; MID_FD120
.DW DPB_FD111 ; MID_FD111
.DW DPB_HDNEW ; MID_HDNEW (1024 DIR ENTRIES)
;
DPBCNT .EQU ($ - DPBMAP) / 2
;
@ -1199,6 +1200,7 @@ DSK_GETINF1: ; ERROR RETURN
DSK_SELECT:
LD B,E ; SAVE E IN B FOR NOW
CALL DSK_GETINF ; GET D=UNIT, E=SLICE, HL=DPH ADDRESS
CALL NZ,PANIC ; *DEBUG*
RET NZ ; RETURN IF INVALID DRIVE (A=1, NZ SET, HL=0)
PUSH BC ; WE NEED B LATER, SAVE ON STACK
;
@ -1209,13 +1211,15 @@ DSK_SELECT:
LD (SEKUNIT),A ; SAVE UNIT
LD (SEKDPH),HL ; SAVE DPH ADDRESS
;
; UPDATE OFFSET FOR ACTIVE SLICE
; A TRACK IS ASSUMED TO BE 16 SECTORS
; THE OFFSET REPRESENTS THE NUMBER OF BLOCKS * 256
; TO USE AS THE OFFSET
LD H,65 ; H = TRACKS PER SLICE, E = SLICE NO
CALL MULT8 ; HL := H * E (TOTAL TRACK OFFSET)
LD (SEKOFF),HL ; SAVE NEW TRACK OFFSET
LD A,E ; A := SLICE
LD (SLICE),A ; SAVE IT
; UPDATE LBAOFF FROM DPH
LD HL,(SEKDPH)
LD A,16
CALL ADDHLA
LD DE,SEKLBA
LD BC,4
LDIR
;
; RESTORE DE TO BC (FOR ACCESS TO DRIVE LOGIN BIT)
POP BC ; GET ORIGINAL E INTO B
@ -1234,11 +1238,24 @@ DSK_SELECT:
LD E,1 ; ENABLE MEDIA CHECK/DISCOVERY
RST 08 ; DO IT
LD A,E ; RESULTANT MEDIA ID TO ACCUM
LD (MEDID),A ; SAVE IT
OR A ; SET FLAGS
LD HL,0 ; ASSUME FAILURE
RET Z ; BAIL OUT IF NO MEDIA
;
; A HAS MEDIA ID, SET HL TO CORRESPONDING DPBMAP ENTRY
; CLEAR LBA OFFSET (DWORD)
LD HL,0 ; ZERO
LD (SEKLBA),HL ; CLEAR FIRST WORD
LD (SEKLBA+2),HL ; CLEAR SECOND WORD
;
; CHECK MBR OF PHYSICAL DISK BEING SELECTED
; WILL UPDATE MEDID AND LBAOFF IF VALID CP/M PARTITION EXISTS
CALL DSK_MBR ; UPDATE MEDIA FROM MBR
LD HL,0 ; ASSUME FAILURE
RET NZ ; ABORT ON I/O ERROR
;
; SET HL TO DPBMAP ENTRY CORRESPONDING TO MEDIA ID
LD A,(MEDID) ; GET MEDIA ID
LD HL,DPBMAP ; HL = DPBMAP
RLCA ; DPBMAP ENTRIES ARE 2 BYTES EACH
CALL ADDHLA ; ADD OFFSET TO HL
@ -1249,12 +1266,22 @@ DSK_SELECT:
LD D,(HL) ; DE = ADDRESS OF DESIRED DPB
;
; PLUG DPB INTO THE ACTIVE DPH
LD HL,(SEKDPH)
LD HL,(SEKDPH) ; POINT TO START OF DPH
LD BC,10 ; OFFSET OF DPB IN DPH
ADD HL,BC ; HL := DPH.DPB
LD (HL),E ; SET LSB OF DPB IN DPH
INC HL ; BUMP TO MSB
LD (HL),D ; SET MSB OF DPB IN DPH
;
; ; PLUG LBA OFFSET INTO ACTIVE DPH
LD HL,(SEKDPH) ; POINT TO START OF DPH
LD BC,16 ; OFFSET OF LBA OFFSET IN DPH
ADD HL,BC ; HL := DPH.LBAOFF PTR
EX DE,HL ; DEST IS DPH.LBAOFF PTR
LD HL,SEKLBA ; SOURCE IS LBAOFF
LD BC,4 ; 4 BYTES
LDIR ; DO IT
;
#ENDIF
;
DSK_SELECT2:
@ -1262,6 +1289,131 @@ DSK_SELECT2:
XOR A ; FLAG SUCCESS
RET ; NORMAL RETURN
;
; CHECK MBR OF DISK TO SEE IF IT HAS A PARTITION TABLE.
; IF SO, LOOK FOR A CP/M PARTITION. IF FOUND, GET
; UPDATE THE PARTITION OFFSET (LBAOFF) AND UPDATE
; THE MEDIA ID (MEDID).
;
#IFDEF PLTWBW
;
DSK_MBR:
; CHECK MEDIA TYPE, ONLY HARD DISK IS APPLICABLE
LD A,(MEDID) ; GET MEDIA ID
CP MID_HD ; HARD DISK?
JR Z,DSK_MBR1 ; IF SO, CONTINUE
XOR A ; ELSE, N/A, SIGNAL SUCCESS
RET ; AND RETURN
;
DSK_MBR1:
; FLUSH DSKBUF TO MAKE SURE IT IS SAFE TO USE IT.
CALL BLKFLSH ; MAKE SURE DISK BUFFER IS NOT DIRTY
XOR A ; CLEAR ACCUM
LD (HSTACT),A ; CLEAR HOST BUFFER ACTIVE FLAG
;
; READ SECTOR ZERO (MBR)
LD B,BF_DIOREAD ; READ FUNCTION
LD A,(SEKUNIT) ; GET UNIT
LD C,A ; PUT IN C
LD DE,0 ; LBA SECTOR ZERO
LD HL,0 ; ...
CALL DSK_IO2 ; DO IT
RET NZ ; ABORT ON ERROR
;
; SWITCH TO BIOS BANK TO ACCESS DISK BUFFER
LD A,(HB_CURBNK) ; GET CUR BANK
PUSH AF ; SAVE CUR BANK
LD A,(BNKBIOS) ; BIOS BANK
CALL HB_BNKSEL ; DO IT
;
; CHECK SIGNATURE
LD HL,(DSKBUF) ; DSKBUF ADR
LD DE,$1FE ; OFFSET TO SIGNATURE
ADD HL,DE ; POINT TO SIGNATURE
LD A,(HL) ; GET FIRST BYTE
CP $55 ; CHECK FIRST BYTE
JR NZ,DSK_MBR4 ; NO MATCH, NO PART TABLE
INC HL ; NEXT BYTE
LD A,(HL) ; GET SECOND BYTE
CP $AA ; CHECK SECOND BYTE
JR NZ,DSK_MBR4 ; NO MATCH, NO PART TABLE, ABORT
;
; TRY TO FIND OUR ENTRY IN PART TABLE AND CAPTURE LBA OFFSET
LD B,4 ; FOUR ENTRIES IN PART TABLE
LD HL,(DSKBUF) ; DSKBUF ADR
LD DE,$1BE+4 ; OFFSET OF FIRST ENTRY PART TYPE
ADD HL,DE ; POINT TO IT
DSK_MBR2:
LD A,(HL) ; GET PART TYPE
CP $52 ; CP/M PARTITION?
JR Z,DSK_MBR3 ; COOL, GRAB THE LBA OFFSET
LD DE,16 ; PART TABLE ENTRY SIZE
ADD HL,DE ; BUMP TO NEXT ENTRY PART TYPE
DJNZ DSK_MBR2 ; LOOP THRU TABLE
JR DSK_MBR4 ; TOO BAD, NO CP/M PARTITION
;
DSK_MBR3:
; WE HAVE LOCATED A VALID CP/M PARTITION
; HL POINTS TO PART TYPE FIELD OF PART ENTRY
; UPDATE MEDIA ID
LD A,MID_HDNEW ; NEW MEDIA ID
LD (MEDID),A ; SAVE IT
;
; CAPTURE THE LBA OFFSET
LD DE,4 ; LBA IS 4 BYTES AFTER PART TYPE
ADD HL,DE ; POINT TO IT
LD DE,SEKLBA ; LOC TO STORE LBA OFFSET
LD BC,4 ; 4 BYTES (32 BITS)
LDIR ; COPY IT
;
DSK_MBR4:
; RESTORE BANK
POP AF ; GET PREV BANK
CALL HB_BNKSEL ; SELECT IT
;
DSK_MBR5:
;
; DIFFERENT ALGORITHM FOR NEW HD FORMAT
LD A,(MEDID) ; GET MEDIA ID
CP MID_HDNEW ; NEW FORMAT?
JR Z,DSK_MBR6 ; IF SO, GO THERE
;
; OLD HD FORMAT, 65 TRACKS PER SLICE
LD A,(SLICE) ; GET SLICE
LD E,A ; E = SLICE NO
LD H,65 ; H = TRACKS PER SLICE
CALL MULT8 ; HL := H * E (TOTAL TRACK OFFSET)
LD DE,0 ; CLEAR HI WORD
LD B,8 ; 16 SPT, SHIFT 4 BITS
CALL RL32 ; DO IT
JR DSK_MBR7 ; DONE
;
DSK_MBR6:
; NEW HD FORMAT, MULTIPLY SLICE BY 8MB
LD DE,0 ; CLEAR HIWORD
LD H,0 ; CLEAR HI BYTE OR LOWORD
LD A,(SLICE) ; GET SLICE
LD L,A ; PUT SLICE IN LOW BYTE
LD B,14
CALL RL32 ; MULTIPLY BY 16384 SECTORS (8MB)
;
DSK_MBR7:
; ADD IN LBA OFFSET
LD BC,(SEKLBA) ; LBA OFFSET LOWORD
ADD HL,BC
EX DE,HL
LD BC,(SEKLBA+2) ; LBA OFFSET HIWORD
ADC HL,BC
EX DE,HL
SET 7,D ; SET LBA ACCESS BIT
; RESAVE IT
LD (SEKLBA),HL ; LOWORD
LD (SEKLBA+2),DE ; HIWORD
; SUCCESSFUL FINISH
XOR A ; SUCCESS
RET ; DONE
;
#ENDIF
;
;
;
DSK_STATUS:
@ -1297,7 +1449,7 @@ DSK_WRITE:
;
;
#IFDEF PLTUNA
;
DSK_IO:
PUSH BC
LD DE,(HSTTRK) ; GET TRACK INTO HL
@ -1338,15 +1490,10 @@ DSK_IO1:
RST 08
OR A ; SET FLAGS BASED ON RESULT
RET
#ELSE
DSK_IO:
;
; TRANSLATE CP/M TRACK/SECTOR -> HBIOS TRACK/HEAD/SECTOR
; NEEDS TO HANDLE FLOPPY SEPARATE FROM HARD DISK
#ELSE
;
CHS:
DSK_IO:
LD A,(HSTUNIT) ; GET UNIT
LD C,A ; UNIT -> C
PUSH BC ; SAVE FUNC/UNIT
@ -1356,7 +1503,7 @@ CHS:
LD A,D ; DEVICE TYPE -> A
AND $F0 ; ISOLATE HIGH BITS
CP DIODEV_FD ; FLOPPY?
JR NZ,CHSHD ; IF NOT, DO HD CHS XLAT
JR NZ,LBA_IO ; IF NOT, DO LBA IO
;
; FLOPPY SPECIFIC TRANSLATION ASSUMES FLOPPY IS DOUBLE-SIDED AND
; USES LOW ORDER BIT OF TRACK AS HEAD VALUE
@ -1368,40 +1515,37 @@ CHS:
SRL H ; SHIFT HEAD BIT OUT OF HL
RR L ; ... AND INTO CARRY
RL D ; CARRY BIT (HEAD) INTO D
JR CHS2
;
; HARD DISK SPECIFIC TRANSLATION
; ASSUMES 16 HEADS PER CYLINDER AND 16 SECTORS PER TRACK
JR DSK_IO2 ; DO THE DISK I/O
;
CHSHD:
LD HL,(HSTTRK) ; GET TRACK VALUE
LD A,L ; LSB OF TRACK TO A
AND $0F ; ISOLATE HEAD IN LOW 4 BITS
LD D,A ; STUFF IT IN D
LBA_IO:
LD A,(HSTUNIT) ; GET THE UNIT VALUE
LD C,A ; PUT IT IN C
PUSH BC ; SAVE FUNC/UNIT
; GET TRACK AND SHIFT TO MAKE ROOM FOR 4 BIT SECTOR VALUE
LD HL,(HSTTRK) ; GET TRACK
LD DE,0 ; CLEAR HIWORD
LD B,4 ; X16 (16 SPT ASSUMED)
CALL RL32 ; DO IT
; COMBINE WITH SECTOR
LD A,(HSTSEC) ; GET SECTOR
LD E,A ; STUFF IT IN E
LD A,B ; SAVE B (HBIOS FUNC)
LD B,4 ; PREPARE TO SHIFT OUT 4 BIT HEAD VALUE
CHSHD1:
SRL H ; SHIFT ONE BIT OUT
RR L ; ... OF HL
DJNZ CHSHD1 ; DO ALL 4 BITS
LD B,A ; RESTORE B (HBIOS FUNC)
; FALL THRU TO CHS2
;
; ALL TYPES OF TRANSLATION WIND UP HERE TO
; MAKE THE ACTUAL HBIOS CALL
;
CHS2:
PUSH DE ; SAVE HEAD/SECTOR + COULD MOVE
LD DE,(HSTOFF) ; NOW GET SLICE OFFSET | TO CHSHD,
ADD HL,DE ; ADD IT TO TRACK VALUE | NO SLICES
POP DE ; RECOVER HEAD/SECTOR + FOR FLOPPY
OR L
LD L,A
; ADD IN LBA OFFSET FOR PARTITION AND/OR SLICE
LD BC,(HSTLBA) ; LBA OFFSET LOWORD
ADD HL,BC
EX DE,HL
LD BC,(HSTLBA+2) ; LBA OFFSET HIWORD
ADC HL,BC
EX DE,HL
SET 7,D ; MAKE SURE LBA ACCESS BIT SET
POP BC ; RESTORE FUNC/UNIT
;JR DSK_IO2 ; DO THE DISK I/O (FALL THRU)
;
; MAKE HBIOS CALL
; HBIOS FUNC SHOULD STILL BE IN B
; UNIT SHOULD STILL BE IN C
;
DSK_IO2:
PUSH BC ; SAVE INCOMING FUNCTION, DEVICE/UNIT
LD B,BF_DIOSEEK ; SETUP FOR NEW SEEK CALL
RST 08 ; DO IT
@ -1411,10 +1555,11 @@ CHS2:
LD A,(BNKBIOS) ; GET BIOS BANK
LD D,A ; TRANSFER TO/FROM BIOS BANK
LD E,1 ; TRANSFER ONE SECTOR
;CALL PC_ASTERISK ; *DEBUG*
RST 08 ; DO IT
OR A ; SET FLAGS
RET ; DONE
;
#ENDIF
;
;==================================================================================================
@ -1504,9 +1649,11 @@ STR_SEC .DB " SEC=$"
;STR_READONLY .DB "\r\nCBIOS Err: Read Only Drive$"
;STR_STALE .DB "\r\nCBIOS Err: Stale Drive$"
;
SECADR .DW 0 ; ADDRESS OF SECTOR IN ROM/RAM PAGE
;SECADR .DW 0 ; ADDRESS OF SECTOR IN ROM/RAM PAGE
DEFDRIVE .DB 0 ; DEFAULT DRIVE
CCPBUF .DW 0 ; ADDRESS OF CCP BUF IN BIOS BANK
MEDID .DB 0 ; TEMP STORAGE FOR MEDIA ID
SLICE .DB 0 ; CURRENT SLICE
;
#IFDEF PLTWBW
BNKBIOS .DB 0 ; BIOS BANK ID
@ -1536,6 +1683,7 @@ SEKUNIT .DB 0 ; DISK UNIT
SEKDPH .DW 0 ; ADDRESS OF ACTIVE (SELECTED) DPH
SEKOFF .DW 0 ; TRACK OFFSET IN EFFECT FOR SLICE
SEKACT .DB TRUE ; ALWAYS TRUE!
SEKLBA .FILL 4,0 ; LBA OFFSET
;
; RESULT OF CPM TO PHYSICAL TRANSLATION
;
@ -1547,6 +1695,7 @@ XLTUNIT .DB 0
XLTDPH .DW 0
XLTOFF .DW 0
XLTACT .DB TRUE ; ALWAYS TRUE!
XLTLBA .FILL 4,0 ; LBA OFFSET
;
XLTSIZ .EQU $ - XLT
;
@ -1560,6 +1709,7 @@ HSTUNIT .DB 0 ; DISK UNIT IN BUFFER
HSTDPH .DW 0 ; CURRENT DPH ADDRESS
HSTOFF .DW 0 ; TRACK OFFSET IN EFFECT FOR SLICE
HSTACT .DB 0 ; TRUE = BUFFER HAS VALID DATA
HSTLBA .FILL 4,0 ; LBA OFFSET
;
; SEQUENTIAL WRITE TRACKING FOR (UNA)LLOCATED BLOCK
;
@ -1695,11 +1845,28 @@ DPB_HD:
.DB 31 ; BLM: BLOCK MASK
.DB 1 ; EXM: EXTENT MASK
.DW 2047 ; DSM: TOTAL STORAGE IN BLOCKS - 1 = (8MB / 4K BLS) - 1 = 2047
.DW 511 ; DRM: DIR ENTRIES - 1 = 512 - 1 = 511
.DW 512 - 1 ; DRM: DIR ENTRIES - 1
.DB 11110000B ; AL0: DIR BLK BIT MAP, FIRST BYTE
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
.DW 0 ; CKS: DIRECTORY CHECK VECTOR SIZE = 256 / 4
.DW 16 ; OFF: RESERVED TRACKS = 16 TRKS * (16 TRKS * 16 HEADS * 16 SECS * 512 BYTES) = 128K
.DW 16 ; OFF: RESERVED TRACKS
;
; BLOCKSIZE (BLS) = 4K, DIRECTORY ENTRIES = 1024
;
.DW CKS_HD
.DW ALS_HD
.DB (4096 / 128) ; RECORDS PER BLOCK (BLS / 128)
DPB_HDNEW:
.DW 64 ; SPT: SECTORS PER TRACK
.DB 5 ; BSH: BLOCK SHIFT FACTOR
.DB 31 ; BLM: BLOCK MASK
.DB 1 ; EXM: EXTENT MASK
.DW 2048 - 1 - 4 ; DSM: STORAGE BLOCKS - 1 - RES TRKS
.DW 1024 - 1 ; DRM: DIR ENTRIES - 1
.DB 11111111B ; AL0: DIR BLK BIT MAP, FIRST BYTE
.DB 00000000B ; AL1: DIR BLK BIT MAP, SECOND BYTE
.DW 0 ; CKS: DIRECTORY CHECK VECTOR SIZE = 256 / 4
.DW 2 ; OFF: RESERVED TRACKS
;__________________________________________________________________________________________________
;
; IBM 720KB 3.5" FLOPPY DRIVE, 80 TRKS, 36 SECS/TRK, 512 BYTES/SEC
@ -2650,7 +2817,8 @@ DPH_INIT:
LD H,0 ; ... INTO HL
ADD HL,HL ; MULTIPLY
ADD HL,HL ; ... BY SIZE
ADD HL,HL ; ... OF DPH (16)
CALL ADDHLA ; ...
ADD HL,HL ; ... OF DPH (20)
ADD HL,HL ; ... FOR TOTAL SIZE
CALL ALLOC ; ALLOCATE THE SPACE
CALL C,PANIC ; SHOULD NEVER ERROR
@ -2707,7 +2875,8 @@ DPH_INIT2:
LD (HL),D ; ... DRIVE MAP
INC HL ; AND BUMP TO START OF NEXT ENTRY
; UPDATE DPH ALLOCATION TOP
LD A,16 ; SIZE OF A DPH ENTRY
;LD A,16 ; SIZE OF A DPH ENTRY
LD A,20 ; SIZE OF A DPH ENTRY
EX DE,HL ; HL := DPH POINTER
CALL ADDHLA ; CALC NEW DPHTOP
LD (DPHTOP),HL ; SAVE IT

12
Source/CBIOS/util.asm

@ -430,3 +430,15 @@ PRTHEXBUF1:
INC DE
DJNZ PRTHEXBUF1
RET
;
; LEFT SHIFT DE:HL BY B BITS (B > 0)
;
RL32:
OR A ; CLEAR CARRY
RL L
RL H
RL E
RL D
DJNZ RL32
RET

442
Source/CPM3/biosldr.z80

@ -51,57 +51,67 @@
jp 0 ; reserved for future expansion
jp 0 ; reserved for future expansion
boot:
if cmdline
mbrsec equ dtabuf
boot:
; The main module (cpmldr.asm) does not expect the
; boot call to use much stack. We use our own during
; this routine to avoid issues.
ld (stksav),sp
ld sp,stack
boot1:
ld de,msgunit
call writestr
call cin
push af
call cout
pop af
; Do the real work
call boot0
; Restore original stack and return
ld sp,(stksav)
ret
sub '0'
ld (unit),a
jr c,selerr
boot0:
if cmdline
boot1:
; Get disk unit from user
ld de,msgunit ; disk unit prompt
call writestr ; display on console
call cin ; get a character
push af ; save it
call cout ; echo character
pop af ; restore it
sub '0' ; convert to binary
ld (unit),a ; save it
jr c,selerr ; loop if below 0 entered
ld bc,0F810h ; HBIOS, get disk unit count
call 0FFF0h ; do it, E := disk unit count
ld a,(unit) ; get unit num back
cp e ; compare to entry
jr nc,selerr ; loop if too high
ld de,msgslc
call writestr
call cin
push af
call cout
pop af
sub '0'
ld (slice),a
jr c,selerr
cp 10
jr nc,selerr
jr boot2
; Get disk slice from user
ld de,msgslc ; slice prompt
call writestr ; display on console
call cin ; get a character
push af ; save it
call cout ; echo it
pop af ; restore it
sub '0' ; convert to binary
ld (slice),a ; save it
jr c,selerr ; loop if below 0 entered
cp 10 ; check for over 9
jr nc,selerr ; loop if over 9
ld de,crlf ; linefeed
call writestr ; ... to console
jr boot2 ; boot w/ unit & slice
selerr:
ld de,msginv
call writestr
jr boot1
; Display invalid entry message and restart
ld de,msginv ; error message
call writestr ; display on console
jr boot1 ; loop
boot2:
ld de,crlf
call writestr
ld sp,(stksav)
; Record unit & slice w/ HBIOS
ld bc,0F9E0h ; HBIOS func: set boot info
ld a,(unit) ; get unit
ld d,a ; put in D
@ -112,6 +122,7 @@ boot2:
else
; Get unit & slice from HBIOS
ld bc,0F8E0h ; HBIOS func: get boot info
call 0FFF0h ; do it, D := boot unit, E: := slice
ld a,d ; move unit to A
@ -121,27 +132,118 @@ boot2:
endif
; Check that drive actually exists
ld bc,0F810h ; HBIOS func: get disk count
call 0FFF0h ; do it, E=disk count
ld a,(unit) ; get boot disk unit
cp e ; compare to count
jp nc,err_nodisk ; handle no disk err
; Sense media to determine media format
ld a,(unit) ; Get boot unit
ld c,a ; put in C
ld b,18h ; HBIOS Media function
ld e,1 ; Enable media check/discovery
call 0FFF0H ; HBIOS call
ld a,e ; Resultant media id to accum
or a ; Set flags
;halt
;
; !!! Need to do something on error !!!
;
ret z ; Bail out on error
jp nz,err_diskio ; handle error
ld a,e ; resultant media id to accum
ld (medid),a ; save media id
or a ; set flags, 0 is no media
jp z,err_diskio ; handle no media error
; Initialize slice start LBA & sectors per slice
ld hl,0 ; assume slice starts
ld (lba),hl ; ... at LBA offset
ld (lba+2),hl ; ... of zero
ld hl,16640 ; assume legacy value for
ld (sps),hl ; ... sectors per slice
; If not hard disk, skip partition & slice stuff
ld a,(medid) ; get media id
cp 4 ; hard disk?
jr nz,boot9 ; if not, jump ahead
; Read MBR
ld de,8000h ; LBA address zero
ld hl,0 ; ... to read first sector
ld bc,mbrsec ; read into MBR buffer
ld (dma),bc ; save
ld b,1 ; one sector
ld a,(unit) ; get bootunit
ld c,a ; put in C
call diskread ; do it, no return on err
; Check signature
ld hl,(mbrsec+1FEh) ; get signature
ld a,l ; first byte
cp 055h ; should be $55
jr nz,boot5 ; if not, no part table
ld a,h ; second byte
cp 0AAh ; should be $AA
jr nz,boot5 ; if not, no part table
; Search part table for CP/M entry (type 0x52)
ld b,4 ; four entries in part table
ld hl,mbrsec+1BEh+4 ; offset of first part type
boot3:
ld a,(hl) ; get part type
cp 52h ; CP/M partition?
jr z,boot4 ; cool, grab the LBA offset
ld de,16 ; part table entry size
add hl,de ; bump to next part type
djnz boot3 ; loop thru table
jr boot5 ; too bad, no CP/M partition
boot4:
; Capture the starting LBA of the CP/M partition we found
ld de,4 ; LBA is 4 bytes after part type
add hl,de ; point to it
ld de,lba ; loc to store lba offset
ld bc,4 ; 4 bytes (32 bits)
ldir ; copy it
; For now, it is implied that a slice within a partition
; table will be in the "new" disk format. So, we now
; adjust the sectors per slice and media id.
; Use new slice format sectors per slice value
ld hl,16384 ; new sectors per slice
ld (sps),hl ; save it
; Update media id for new hard disk format
ld a,10 ; new media id
ld (medid),a ; save it
boot5:
; Adjust LBA offset based on target slice
ld a,(slice) ; get boot slice, A is loop cnt
ld hl,(lba) ; set DE:HL
ld de,(lba+2) ; ... to starting LBA
ld bc,(sps) ; sectors per slice
boot6:
or a ; set flags to check loop cntr
jr z,boot8 ; done if counter exhausted
add hl,bc ; add one slice to low word
jr nc,boot7 ; check for carry
inc de ; if so, bump high word
boot7:
dec a ; dec loop downcounter
jr boot6 ; and loop
boot8:
ld (lba),hl ; save new lba, low word
ld (lba+2),de ; save new lba, high word
boot9:
; Locate DPB corresponding to media id
ld hl,dpb$start - dpb$sz
ld de,dpb$sz
ld b,a ; loop count
dsk$login1:
ld a,(medid) ; get media id
ld b,a ; to loop count
boot10:
add hl,de ; next dpb
djnz dsk$login1 ; loop as needed
djnz boot10 ; loop as needed
; hl is ptr to desired dpb
; Stuff DPB ptr (HL) into DPH
ld de,dph0 ; load DPH pointer
ex de,hl ; de = DPB adr, hl = DPH adr
push de ; save DPB adr
@ -149,10 +251,10 @@ dsk$login1:
add hl,de ; hl = adr of DPB field in DPH
pop de ; recover DPB adr
ld (hl),e ; update LSB
inc hl
ld (hl),d ; udpate MSB
inc hl ; point to MSB
ld (hl),d ; update MSB
ret
ret ; done
wboot:
ld a,81H
@ -162,15 +264,14 @@ const:
ld a,82H
halt
conin:
ld bc,0080H ; unit 80h (console), func 0 = CIN
call 0FFF0H
ld bc,0080h ; unit 80h (console), func 0 = CIN
call 0FFF0h ; do it
ld a,e ; put in C
ret ; done
conout:
ld e,c ; output character in E
ld bc,0180H ; unit 80h (console), func 1 = COUT
;rst 08 ; do it
call 0FFF0H
ret ; return
ld bc,0180h ; unit 80h (console), func 1 = COUT
jp 0FFF0h
list:
ld a,85H
halt
@ -197,61 +298,100 @@ setsec:
setdma:
ld (dma),bc
ret
read:
; Check device type
ld a,(unit) ; get unit
ld c,a ; BIOS Disk Unit in C
ld b,12H ; HBIOS SEEK function
push bc ; save it
;push de ; save XDPH pointer
ld b,17h ; HBIOS DEVICE function
rst 08 ; Do it, D=device type
ld a,d ; put in accum
and 0F0h ; isolate high bits
ld b,1 ; assume it is floppy, 1 head bit
ld c,01h ; 1 bit head mask
cp 10h ; floppy?
jr z,seek0 ; yup, skip ahead
ld b,4 ; must be hard disk, 4 head bits
ld c,0Fh ; 4 bit head mask
seek0:
;pop de ; recover XDPH pointer
push bc ; save bc
ld a,(slice) ; get slice
ld e,a ; slice to E
ld h,65 ; number of tracks per slice
call mult8 ; HL now has track offset for slice
pop bc ; recover bc
push hl ; save track offset for now
ld hl,(trk) ; get track value
ld a,l ; lsb of track to a
and c ; apply mask
ld d,a ; save in d
seek1:
srl h ; shift one bit out
rr l ; ... of hl
djnz seek1 ; do all bits
jr nz,read2 ; if not, do LBA i/o
; Floppy I/O
ld de,(sect) ; sector -> de, head(d) becomes zero
ld hl,(trk) ; track -> hl (low bit has head)
srl h ; shift head bit out of hl
rr l ; ... and into carry
rl d ; carry bit (head) into d
jr read3 ; do the disk i/o
; ; *** Simplify this to get rid of slice!!! ***
; ld b,1 ; assume it is floppy, 1 head bit
; ld c,01h ; 1 bit head mask
; push bc ; save bc
; ld a,(slice) ; get slice
; ld e,a ; slice to E
; ld h,65 ; number of tracks per slice
; call mult8 ; HL now has track offset for slice
; pop bc ; recover bc
; push hl ; save track offset for now
; ld hl,(trk) ; get track value
; ld a,l ; lsb of track to a
; and c ; apply mask
; ld d,a ; save in d
;read1:
; srl h ; shift one bit out
; rr l ; ... of hl
; djnz read1 ; do all bits
; ld a,(sect) ; get sector
; ld e,a ; stuff it in e
; ex de,hl ; DE=track, HL=head/sect
; ex (sp),hl ; save head/sect, HL = offset
; add hl,de ; HL has final track value
; pop de ; recover head/sect to de
; jr read3
; LBA I/O
read2:
ld hl,(trk) ; get track
ld de,0 ; clear hiword
ld b,4 ; x16 (16 spt assumed)
call rl32 ; do it
; combine with sector
ld a,(sect) ; get sector
ld e,a ; stuff it in e
ex de,hl ; de=track, hl=head/sect
ex (sp),hl ; save head/sect, hl = offset
add hl,de ; hl has final track value
pop de ; recover head/sect to de
pop bc ; recover function & unit
;rst 08 ; perform seek
call 0FFF0H
; Read Sector
ld b,13h ; HBIOS read
ld a,(unit) ; get boot unit
or l ; combine
ld l,a ; and back to L
; add in lba offset
ld bc,(lba) ; lba offset loword
add hl,bc ; add to cur loword
ex de,hl ; swap
ld bc,(lba+2) ; lba offset hiword
adc hl,bc ; add w/ carry to cur hiword
ex de,hl ; swap back
set 7,d ; set lba access bit
read3:
; DE:HL has sector address to read (LBA or CHS)
ld a,(unit) ; get disk unit
ld c,a ; put in C
ld hl,(dma) ; dma address
ld a,(0FFE0H) ; current bank
ld d,a ; ... to D
ld e,1 ; 1 sector
;rst 08
call 0FFF0H
ld b,1 ; read 1 sector
jr diskread ; read sector and return
diskread:
; Read disk sector(s)
; DE:HL is LBA, B is sector count, C is disk unit
; Seek to requested sector in DE:HL
push bc ; save unit & count
ld b,012h ; HBIOS func: seek
call 0FFF0h ; do it
pop bc ; recover unit & count
jp nz,err_diskio ; handle error
; Read sector(s) into buffer
ld e,b ; transfer count
ld b,013h ; HBIOS func: disk read
ld hl,(dma) ; read into info sec buffer
ld a,(0FFE0h) ; get current bank
ld d,a ; put in D
call 0FFF0h ; do it
jp nz,err_diskio ; handle error
xor a ; signal success
ret ; and done
ret
write:
ld a,8EH
halt
@ -291,10 +431,11 @@ flush:
halt
move:
ex de,hl ; we are passed source in DE and dest in HL
ldir ; use Z80 block move instruction
ex de,hl ; need next addresses in same regs
ret
; On input, DE=src, HL=dest
ex de,hl ; swap HL/DE for LDIR
ldir ; Z80 block move
ex de,hl ; swap back (required!)
ret ; done
time:
ld a,9AH
halt
@ -309,20 +450,19 @@ xmove:
halt
cin:
; input character from console via hbios
ld c,080H ; console unit to c
ld b,00H ; hbios func: input char
call 0FFF0H ; hbios reads character
ld a,e ; move character to a for return
ret
; Input character from console via HBIOS
ld c,080H ; console unit to C
ld b,00H ; HBIOS func: input char
call 0FFF0H ; HBIOS reads character
ld a,e ; To A for return
ret ; done
cout:
; output character to console via hbios
ld e,a ; output char to e
ld c,080H ; console unit to c
ld b,01H ; hbios func: output char
call 0FFF0H ; hbios outputs character
ret
; Output character to console via HBIOS
ld e,a ; output char to E
ld c,080H ; console unit to C
ld b,01H ; HBIOS func: output char
jp 0FFF0H ; output & return
writestr:
push af
@ -339,12 +479,8 @@ writestr2:
pop af
ret
;
; multiply 8-bit values
; in: multiply h by e
; out: hl = result, e = 0, b = 0
;
mult8:
; Multiply: H := H * E
ld d,0
ld l,d
ld b,8
@ -356,6 +492,46 @@ mult8_noadd:
djnz mult8_loop
ret
rl32:
; Left shift DE:HL by B bits (B > 0)
or a ; clear carry
rl l ; rotate L thru carry
rl h ; rotate H thru carry
rl e ; rotate E thru carry
rl d ; rotate D thru carry
djnz rl32 ; loop B times
ret ; done
err_nodisk:
ld hl,str_err_nodisk
jr err
err_noslice:
ld hl,str_err_noslice
jr err
err_diskio:
ld hl,str_err_diskio
jr err
err_sig:
ld hl,str_err_sig
jr err
err_api:
ld hl,str_err_api
jr err
err:
push hl
ld de,str_err_prefix
call writestr
pop de
call writestr
halt
str_err_prefix db "\r\n\r\n*** ","$"
str_err_nodisk db "Disk unit not available","$"
str_err_noslice db "Disk unit does not support slices","$"
str_err_diskio db "Disk I/O failure","$"
str_err_sig db "No system image on disk","$"
str_err_api db "HBIOS API failure","$"
msgunit db 13,10,13,10,'Boot CP/M 3 from Disk Unit: $'
msgslc db ' Slice: $'
msginv db 13,10,13,10,'*** Invalid Selection ***$'
@ -411,7 +587,7 @@ dpb$hd: ; 8MB Hard Disk Drive
db 31 ; blm: block mask
db 1 ; exm: extent mask
dw 2047 ; dsm: total storage in blocks - 1 = (8mb / 4k bls) - 1 = 2047
dw 511 ; drm: dir entries - 1 = 512 - 1 = 511
dw 512-1 ; drm: dir entries - 1 = 512 - 1 = 511
db 11110000b ; al0: dir blk bit map, first byte
db 00000000b ; al1: dir blk bit map, second byte
dw 8000h ; cks: directory check vector size - permanent storage = 8000H
@ -489,6 +665,20 @@ dpb_fd111: ; 8" DS/DD Floppy Drive (1.11M)
db 2 ; psh: 2 for 512 byte sectors
db 3 ; phm: (512 / 128) - 1
dpb$hdnew: ; 8MB Hard Disk Drive (new format)
dw 64 ; spt: sectors per track
db 5 ; bsh: block shift factor
db 31 ; blm: block mask
db 1 ; exm: extent mask
dw 2048 - 1 - 4 ; dsm: total storage in blocks - 1 = 2048 - 1 - resvd tracks
dw 1024 - 1 ; drm: dir entries
db 11111111b ; al0: dir blk bit map, first byte
db 00000000b ; al1: dir blk bit map, second byte
dw 8000h ; cks: directory check vector size - permanent storage = 8000H
dw 2 ; off: reserved tracks
db 2 ; psh: 2 for 512 byte sectors
db 3 ; phm: (512 / 128) - 1
dph0: dw 0 ; xlt, 0 means no translation
db 0,0,0,0,0,0,0,0,0 ; scratch (9 bytes)
db 0 ; mf: media flag
@ -524,6 +714,10 @@ trk ds 2 ; current track
sect ds 2 ; current sector
dma ds 2 ; current DMA address
medid ds 1 ; media id
lba ds 4 ; current lba
sps ds 2 ; sectors per slice
csvbuf ds 128 ; length (CSV) = ((DRM+1)/4)
alvbuf ds 512 ; length (ALV) = ((DSM+1)/4)
dirbuf ds 512 ; sector buffer
@ -531,6 +725,6 @@ dtabuf ds 512 ; sector buffer
ds 64
stack equ $
stksav dw 0
stksav ds 2
end

2
Source/CPM3/boot.z80

@ -41,7 +41,7 @@ tpa$bank equ 0
if banked
; Clone page zero from bank 0 to additional banks
ld b,3 ; last bank
ld b,4 ; last bank
ld c,0 ; src bank
init$2:
push bc ; save bank id's

482
Source/CPM3/diskio.z80

@ -37,7 +37,7 @@
extrn ?bnkxlt
;extrn phex8, cout
extrn phex8, cout
; CP/M 3 Disk definition macros
@ -62,6 +62,7 @@ bell equ 7
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph0: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -69,6 +70,7 @@ dph0: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph1: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -76,6 +78,7 @@ dph1: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph2: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -83,6 +86,7 @@ dph2: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph3: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -90,6 +94,7 @@ dph3: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph4: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -97,6 +102,7 @@ dph4: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph5: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -104,6 +110,7 @@ dph5: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph6: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -111,6 +118,7 @@ dph6: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph7: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -118,6 +126,7 @@ dph7: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph8: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -125,6 +134,7 @@ dph8: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph9: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -132,6 +142,7 @@ dph9: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph10: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -139,6 +150,7 @@ dph10: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph11: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -146,6 +158,7 @@ dph11: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph12: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -153,6 +166,7 @@ dph12: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph13: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -160,6 +174,7 @@ dph13: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph14: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
dw dsk$write
dw dsk$read
@ -167,6 +182,7 @@ dph14: dph 0,dpb$max ; Real DPB filled in at disk login
dw dsk$init
db 0,0 ; HBIOS Disk Unit/Slice (filled in at boot)
dph15: dph 0,dpb$max ; Real DPB filled in at disk login
dw 0, 0 ; LBA Offset
cseg ; DPB must be resident
@ -176,8 +192,8 @@ dpb$max:
db 31 ; blm: block mask
db 1 ; exm: extent mask
dw 2047 ; dsm: total storage in blocks - 1 = (8mb / 4k bls) - 1 = 2047
dw 511 ; drm: dir entries - 1 = 512 - 1 = 511
db 11110000b ; al0: dir blk bit map, first byte
dw 1024 - 1 ; drm: dir entries - 1
db 11111111b ; al0: dir blk bit map, first byte
db 00000000b ; al1: dir blk bit map, second byte
dw 64 ; cks: directory check vector size - 256 / 4
dw 0 ; off: reserved tracks = 16 trks * (16 trks * 16 heads * 16 secs * 512 bytes) = 128k
@ -228,13 +244,13 @@ dpb$rf: ; 4MB RAM Floppy Drive
db 2 ; psh: 2 for 512 byte sectors
db 3 ; phm: (512 / 128) - 1
dpb$hd: ; 8MB Hard Disk Drive
dpb$hd: ; 8MB Hard Disk Drive w/ 512 dir entries
dw 64 ; spt: sectors per track
db 5 ; bsh: block shift factor
db 31 ; blm: block mask
db 1 ; exm: extent mask
dw 2047 ; dsm: total storage in blocks - 1 = (8mb / 4k bls) - 1 = 2047
dw 511 ; drm: dir entries - 1 = 512 - 1 = 511
dw 512 - 1 ; drm: dir entries - 1 = 512 - 1 = 511
db 11110000b ; al0: dir blk bit map, first byte
db 00000000b ; al1: dir blk bit map, second byte
dw 8000h ; cks: directory check vector size - permanent storage = 8000H
@ -312,6 +328,20 @@ dpb_fd111: ; 8" DS/DD Floppy Drive (1.11M)
db 2 ; psh: 2 for 512 byte sectors
db 3 ; phm: (512 / 128) - 1
dpb$hdnew: ; 8MB Hard Disk Drive (new format)
dw 64 ; spt: sectors per track
db 5 ; bsh: block shift factor
db 31 ; blm: block mask
db 1 ; exm: extent mask
dw 2048 - 1 - 4 ; dsm: total storage in blocks - 1 = 2048 - 1 - resvd tracks
dw 1024 - 1 ; drm: dir entries
db 11111111b ; al0: dir blk bit map, first byte
db 00000000b ; al1: dir blk bit map, second byte
dw 8000h ; cks: directory check vector size - permanent storage = 8000H
dw 2 ; off: reserved tracks
db 2 ; psh: 2 for 512 byte sectors
db 3 ; phm: (512 / 128) - 1
dseg ; rest is banked
@ -371,48 +401,152 @@ dsk$login:
;ld a,'L'
;call cout
push de ; save DPH ptr
ld (curdph),de ; save working DPH
ex de,hl ; DPH adr to HL
dec hl ; point to slice
ld a,(hl) ; get slice
ld (slice),a ; save it
dec hl ; point to disk unit
ld a,(hl) ; get unit
ld (unit),a ; save it
call media ; update DPH for media
; Need to do something on error, but bioskrnl provides
; no way for us to return an error.
;jr nz,???
ret
; check media
ld a,(@rdrv) ; get disk unit
;halt
media:
; Set retry address
ld hl,media
ld (retry$adr),hl
; Sense media to determine media format
ld a,(unit) ; Get disk unit
ld c,a ; put in C
ld b,18h ; HBIOS Media function
ld e,1 ; Enable media check/discovery
;rst 08
call 0FFF0H ; HBIOS call
ld a,e ; Resultant media id to accum
or a ; Set flags
;halt
;
; !!! Need to do something on error !!!
;
jr nz,dsk$login0 ; continue if OK
pop de ; else error
ret ; return
dsk$login0:
jp nz,err_diskio ; handle error
ld a,e ; resultant media id to accum
ld (medid),a ; save media id
or a ; set flags, 0 is no media
jp z,err_diskio ; handle no media error
; Initialize slice start LBA & sectors per slice
ld hl,0 ; assume slice starts
ld (lba),hl ; ... at LBA offset
ld (lba+2),hl ; ... of zero
ld hl,16640 ; assume legacy value for
ld (sps),hl ; ... sectors per slice
; If not hard disk, skip partition & slice stuff
ld a,(medid) ; get media id
cp 4 ; hard disk?
jr nz,media9 ; if not, jump ahead
; Read MBR
ld de,8000h ; LBA address zero
ld hl,0 ; ... to read first sector
ld bc,mbrsec ; read into MBR buffer
ld (dma),bc ; save
ld a,(0FFE0h) ; get current HBIOS bank
ld (bank),a ; set DMA bank
ld a,(unit) ; get bootunit
ld c,a ; put in C
ld b,013h ; HBIOS func: disk read
call dsk$io ; do it, no return on err
; Check signature
ld hl,(mbrsec+1FEh) ; get signature
ld a,l ; first byte
cp 055h ; should be $55
jr nz,media5 ; if not, no part table
ld a,h ; second byte
cp 0AAh ; should be $AA
jr nz,media5 ; if not, no part table
; Search part table for CP/M entry (type 0x52)
ld b,4 ; four entries in part table
ld hl,mbrsec+1BEh+4 ; offset of first part type
media3:
ld a,(hl) ; get part type
cp 52h ; CP/M partition?
jr z,media4 ; cool, grab the LBA offset
ld de,16 ; part table entry size
add hl,de ; bump to next part type
djnz media3 ; loop thru table
jr media5 ; too bad, no CP/M partition
media4:
; Capture the starting LBA of the CP/M partition we found
ld de,4 ; LBA is 4 bytes after part type
add hl,de ; point to it
ld de,lba ; loc to store lba offset
ld bc,4 ; 4 bytes (32 bits)
ldir ; copy it
; For now, it is implied that a slice within a partition
; table will be in the "new" disk format. So, we now
; adjust the sectors per slice and media id.
; Use new slice format sectors per slice value
ld hl,16384 ; new sectors per slice
ld (sps),hl ; save it
; Update media id for new hard disk format
ld a,10 ; new media id
ld (medid),a ; save it
media5:
; Adjust LBA offset based on target slice
ld a,(slice) ; get boot slice, A is loop cnt
ld hl,(lba) ; set DE:HL
ld de,(lba+2) ; ... to starting LBA
ld bc,(sps) ; sectors per slice
boot6:
or a ; set flags to check loop cntr
jr z,boot8 ; done if counter exhausted
add hl,bc ; add one slice to low word
jr nc,boot7 ; check for carry
inc de ; if so, bump high word
boot7:
dec a ; dec loop downcounter
jr boot6 ; and loop
boot8:
ld (lba),hl ; save new lba, low word
ld (lba+2),de ; save new lba, high word
media9:
; Locate DPB corresponding to media id
ld hl,dpb$start - dpb$sz
ld de,dpb$sz
ld b,a ; loop count
dsk$login1:
ld a,(medid) ; get media id
ld b,a ; to loop count
media10:
add hl,de ; next dpb
djnz dsk$login1 ; loop as needed
djnz media10 ; loop as needed
; hl is ptr to desired dpb
pop de ; restore DPH ptr
;halt
; Stuff DPB ptr (HL) and LBA offset into DPH
; DPH: DPB @ +12, LBA @ +25
ld de,(curdph) ; load DPH pointer
ex de,hl ; de = DPB adr, hl = DPH adr
push de ; save DPB adr
ld de,12 ; offset of DPB in DPH
add hl,de ; hl = adr of DPB field in DPH
pop de ; recover DPB adr
ld (hl),e ; update LSB
inc hl
ld (hl),d ; udpate MSB
inc hl ; point to MSB
ld (hl),d ; update MSB
ld de,12 ; 12 more bytes to LBA
add hl,de ; HL points to LBA offset field
ld de,lba ; DE points to LBA offset
ex de,hl ; swap for copy
ld bc,4 ; 4 bytes
ldir ; do it
xor a ; signal success
ret ; done
; disk READ and WRITE entry points.
; these entries are called with the following arguments:
@ -429,116 +563,119 @@ dsk$login1:
; if necessary, then return an error code in <A>
dsk$read:
; ld ix,30H
; halt
ld a,13h ; HBIOS disk read function
ld (func),a ; save it
jr dsk$rw ; common disk read/write code
;ld a,'R'
;call cout
dsk$write:
ld a,14h ; HBIOS disk write function
ld (func),a ; save it
jr dsk$rw ; common disk read/write code
push de ; save XDPH pointer
call dsk$seek ; disk seek
pop hl ; restore pointer to HL
ret nz ; abort on seek error
;
dec hl ; point to unit field of XDPH
dec hl
ld c,(hl) ; BIOS Disk Unit in C
ld b,13H ; HBIOS READ function
ld hl,(@dma) ; Dest buffer adr
if banked
ld a,(@dbnk) ; destination bank
call ?bnkxlt
else
ld a,(0FFE0H) ; get current bank
endif
ld d,a ; set desk bank
ld e,1 ; 1 sector
rst 08 ; do it
;call 0FFF0H
dsk$rw:
; Common disk read/write routine
; Assumes func is set to HBIOS read or write
;call phex8
ret ; return
; Save XDPH address
ld (curdph),de ; save to curdph
; lxi h,read$msg ; point at " Read "
; mvi a,88h ! mvi b,01h ; 1797 read + Z80DMA direction
; jmp rw$common
; Set retry address
ld hl,dsk$rw
ld (retry$adr),hl
dsk$write:
;ld ix,32H
;halt
push de ; save XDPH pointer
call dsk$seek ; disk seek
pop hl ; restore pointer to XDPH
ret nz ; abort on seek error
;
dec hl ; point to unit field of XDPH
dec hl
ld c,(hl) ; BIOS Disk Unit in C
ld b,14H ; HBIOS WRITE function
ld hl,(@dma) ; Dest buffer adr
if banked
ld a,(@dbnk) ; destination bank
call ?bnkxlt
else
ld a,(0FFE0H) ; get current bank
endif
ld d,a ; set desk bank
ld e,1 ; 1 sector
rst 08 ; do it
;call 0FFF0H
ret ; return
; lxi h,write$msg ; point at " Write "
; mvi a,0A8h ! mvi b,05h ; 1797 write + Z80DMA direction
; ; jmp wr$common
dsk$seek:
dec de ; point to unit field of XDPH
dec de
ld a,(de) ; get it
; Check device type
ld a,(@rdrv) ; get unit
ld c,a ; BIOS Disk Unit in C
ld b,12H ; HBIOS SEEK function
push bc ; save it
push de ; save XDPH pointer
ld b,17h ; HBIOS DEVICE function
rst 08 ; Do it, D=device type
call 0FFF0h ; do it, D=device type
ld a,d ; put in accum
and 0F0h ; isolate high bits
ld b,1 ; assume it is floppy, 1 head bit
ld c,01h ; 1 bit head mask
cp 10h ; floppy?
jr z,seek0 ; yup, skip ahead
ld b,4 ; must be hard disk, 4 head bits
ld c,0Fh ; 4 bit head mask
seek0:
pop de ; recover XDPH pointer
push bc ; save bc
inc de ; point to slice field of XDPH
ld a,(de) ; get it
ld e,a ; slice to E
ld h,65 ; number of tracks per slice
call mult8 ; HL now has track offset for slice
pop bc ; recover bc
push hl ; save track offset for now
ld hl,(@trk) ; get track value
ld a,l ; lsb of track to a
and c ; apply mask
ld d,a ; save in d
seek1:
srl h ; shift one bit out
rr l ; ... of hl
djnz seek1 ; do all bits
jr nz,dsk$rw2 ; if not, do LBA i/o
; Floppy I/O
ld de,(@sect) ; sector -> de, head(d) becomes zero
ld hl,(@trk) ; track -> hl (low bit has head)
srl h ; shift head bit out of hl
rr l ; ... and into carry
rl d ; carry bit (head) into d
jr dsk$rw9 ; do the disk I/O
dsk$rw2:
; LBA IO: Get LBA offset from DPH
ld hl,(curdph) ; HL := DPH adr
ld de,25+3 ; LBA value + 3
add hl,de ; HL := LBA offset (last byte!)
ld b,(hl) ; hibyte of hiword
dec hl ; bump
ld c,(hl) ; lobyte of hiword
dec hl ; bump
push bc ; save hiword
ld b,(hl) ; hibyte of loword
dec hl ; bump
ld c,(hl) ; lobyte of loword
dec hl ; bump
push bc ; save loword
; Get track and shift into correct bits
ld hl,(@trk) ; get track
ld de,0 ; clear hiword
ld b,4 ; x16 (16 spt assumed)
call rl32 ; do it
; Combine with sector
ld a,(@sect) ; get sector
ld e,a ; stuff it in e
ex de,hl ; de=track, hl=head/sect
ex (sp),hl ; save head/sect, hl = offset
add hl,de ; hl has final track value
pop de ; recover head/sect to de
pop bc ; recover function & unit
rst 08 ; perform seek
;call 0FFF0H
ret
or l ; combine
ld l,a ; and back to L
; Add in LBA offset
pop bc ; lba offset loword
add hl,bc ; add to cur loword
ex de,hl ; swap
pop bc ; lba offset hiword
adc hl,bc ; add w/ carry to cur hiword
ex de,hl ; swap back
set 7,d ; set lba access bit
dsk$rw9:
; DE:HL has sector address to read (LBA or CHS)
ld bc,(@dma) ; get dma address
ld (dma),bc ; save for dsk$io
if banked
ld a,(@dbnk) ; destination bank
call ?bnkxlt ; xlat to HBIOS
else
ld a,(0FFE0H) ; get current bank
endif
ld (bank),a
ld a,(func) ; get HBIOS func code
ld b,a ; put in B
ld a,(@rdrv) ; get disk unit
ld c,a ; put in C
;jr dsk$io ; fall thru to dsk$io!
dsk$io:
; Read/write a disk sector
; DE:HL is CHS/LBA, B is HBIOS func, C is disk unit
; Seek to requested sector in DE:HL
push bc ; save func & unit
ld b,012h ; HBIOS func: seek
call 0FFF0h ; do it
pop bc ; recover func & unit
jp nz,err_diskio ; handle error
; Read sector(s) into buffer
ld e,1 ; transfer count
ld hl,(dma) ; read into info sec buffer
ld a,(bank) ; HBIOS DMA bank
ld d,a ; put in D
call 0FFF0h ; do it
jp nz,err_diskio ; handle error
xor a ; signal success
ret ; and done
;
; multiply 8-bit values
@ -557,6 +694,93 @@ mult8_noadd:
djnz mult8_loop
ret
rl32:
; Left shift DE:HL by B bits (B > 0)
or a ; clear carry
rl l ; rotate L thru carry
rl h ; rotate H thru carry
rl e ; rotate E thru carry
rl d ; rotate D thru carry
djnz rl32 ; loop B times
ret ; done
cin$echo: ; get console input, echo it, and shift to upper case
call ?const ; check for char
or a ; set flags
jr z,cin$echo1 ; nope, continue
call ?conin ; eat extraneous char
jr cin$echo ; and loop
cin$echo1:
call ?conin ; get char
push af ; save it
ld c,a ; put in C
call ?cono ; echo
pop af ; recover it
cp 'a' ; compare
ret c ; done if carry
sub 'a' - 'A' ; make upper case
ret ; and done
; call ?const ! ora a ! jz u$c1 ; see if any char already struck
; call ?conin ! jmp u$conin$echo ; yes, eat it and try again
;u$c1:
; call ?conin ! push psw
; mov c,a ! call ?cono
; pop psw ! cpi 'a' ! rc
; sui 'a'-'A' ; make upper case
; ret
err_nodisk:
ld hl,str_err_nodisk
jr err
err_noslice:
ld hl,str_err_noslice
jr err
err_diskio:
ld hl,str_err_diskio
jr err
err_sig:
ld hl,str_err_sig
jr err
err_api:
ld hl,str_err_api
jr err
err:
push hl
call ?pderr
pop hl
call ?pmsg
ld hl,str_err_retry
call ?pmsg
call cin$echo
cp 'Y'
ret nz
ld hl,(retry$adr)
jp (hl)
str_err_retry db ", Retry (Y/N) ? ",0
str_err_nodisk db ", No disk",0
str_err_noslice db ", No slice",0
str_err_diskio db ", Disk I/O",0
str_err_sig db ", No system",0
str_err_api db ", API failure",0
;
;
;
retry$adr dw ?wboot ; error retry address
curdph dw 0 ; working dph value
medid db 0 ; working media id value
unit db 0 ; working disk unit num
slice db 0 ; working slice num
lba dw 0,0 ; working lba
sps dw 0 ; sectors per slice
mbrsec ds 512 ; MBR sector buffer
dma dw 0 ; current DMA address
bank db 0 ; HBIOS DMA bank
func db 0 ; HBIOS function
;rw$common: ; seek to correct track (if necessary),
; ; initialize DMA controller,
; ; and issue 1797 command.

4
Source/CPM3/genbnk.dat

@ -8,12 +8,12 @@ MEMTOP = FD
BNKSWT = Y
COMBAS = 80
LERROR = Y
NUMSEGS = 03
NUMSEGS = 04
MEMSEG00 = 01,43,00
MEMSEG01 = 0E,72,02
MEMSEG02 = 01,7F,03
MEMSEG03 = 01,7F,04
MEMSEG04 = 00,C0,05
MEMSEG04 = 01,7F,05
MEMSEG05 = 00,C0,06
MEMSEG06 = 00,C0,07
MEMSEG07 = 00,C0,08

3
Source/CPM3/move.z80

@ -69,7 +69,8 @@ xbnkmov:
; 1: TPA BID_AUX 8Ch
; 2: BUFS BID_AUX-1 8Bh
; 3: BUFS BID_AUX-2 8Ah
; ...
; 4: BUFS BID_AUX-3 89h
; 5: BUFS BID_AUX-4 88h
;
; N.B., Below BID_AUX is considered RAM disk bank. Need to
; make sure RAM disk is kept small enough to stay below

3
Source/CPM3/optzpm.lib

@ -1,5 +1,4 @@
; global assembler options for BANKED BIOS
; with Boot Drive swapped into Drive A
; global assembler options for ZPM BIOS
true equ -1
false equ not true

2
Source/CPM3/util.z80

@ -51,7 +51,7 @@ bin2bcd1:
pop bc
ret
if 0
if 1
;
; Print the hex word value in HL
;

139
Source/HBIOS/diskdefs

@ -297,121 +297,158 @@ diskdef wbw_rom1024
os 2.2
end
# UNA 512KB ROM (128KB reserved, 384KB ROM Disk)
# RomWBW 720K floppy media
diskdef wbw_fd720
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom512
# RomWBW 1.44M floppy media
diskdef wbw_fd144
seclen 512
tracks 12
sectrk 64
tracks 160
sectrk 18
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# UNA 512KB ROM (128KB reserved, 896KB ROM Disk)
# RomWBW 360K floppy media
diskdef wbw_fd360
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom1024
# RomWBW 1.20M floppy media
diskdef wbw_fd120
seclen 512
tracks 28
sectrk 64
tracks 160
sectrk 15
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# RomWBW 8MB Hard Disk, LU 0-3
# RomWBW 8MB Hard Disk, first 4 slices
# Legacy format, 512 dir entries, 8,320 sectors / slice
diskdef wbw_hd0
seclen 512
tracks 65
sectrk 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 1
boottrk 16
os 2.2
end
diskdef wbw_hd1
seclen 512
tracks 130
sectrk 256
tracks 2080
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 66
boottrk 1056
os 2.2
end
diskdef wbw_hd2
seclen 512
tracks 195
sectrk 256
tracks 3120
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 131
boottrk 2096
os 2.2
end
diskdef wbw_hd3
seclen 512
tracks 260
sectrk 256
tracks 4160
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 196
boottrk 3136
os 2.2
end
# RomWBW 720K floppy media
diskdef wbw_fd720
# RomWBW 8MB Hard Disk
# New format, 1024 dir entries, 8,192 sectors / slice
# Pure filesystem image, no prefix
diskdef wbw_hd_new
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
tracks 1024
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 2
os 2.2
end
# RomWBW 1.44M floppy media
diskdef wbw_fd144
# RomWBW 8MB Hard Disk, first 4 slices
# New format, 1024 dir entries, 8,192 sectors / slice
# Assumes 256 sector (16 track) hard disk prefix
diskdef wbw_hd0_new
seclen 512
tracks 160
sectrk 18
blocksize 2048
maxdir 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 18
os 2.2
end
# RomWBW 360K floppy media
diskdef wbw_fd360
diskdef wbw_hd1_new
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
tracks 2064
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 1042
os 2.2
end
# RomWBW 1.20M floppy media
diskdef wbw_fd120
diskdef wbw_hd2_new
seclen 512
tracks 160
sectrk 15
blocksize 2048
maxdir 256
tracks 3112
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 2066
os 2.2
end
diskdef wbw_hd3_new
seclen 512
tracks 4136
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 3114
os 2.2
end

548
Source/HBIOS/romldr.asm

@ -106,7 +106,7 @@ bid_cur .equ -1 ; used below to indicate current bank
;
start:
ld sp,bl_stack ; setup private stack
call DELAY_INIT ; init delay functions
call delay_init ; init delay functions
;
; Disable interrupts if IM1 is active because we are switching to page
; zero in user bank and it has not been prepared with IM1 vector yet.
@ -456,7 +456,7 @@ setcon:
ld hl,str_newcon ; new console msg
call pstr ; print string on cur console
pop af ; restore new console unit
call PRTDECB ; print unit num
call prtdecb ; print unit num
;
; Set console unit
ld b,BF_SYSPOKE ; HBIOS func: POKE
@ -479,7 +479,7 @@ setcon:
reboot:
ld hl,str_reboot ; point to message
call pstr ; print it
call LDELAY ; wait for message to display
call ldelay ; wait for message to display
;
#if (BIOS == BIOS_WBW)
;
@ -618,11 +618,11 @@ diskboot:
ld hl,str_boot1
call pstr
ld a,(bootunit)
call PRTDECB
call prtdecb
ld hl,str_boot2
call pstr
ld a,(bootslice)
call PRTDECB
call prtdecb
;
#if (DSKYENABLE)
ld hl,msg_load ; point to load message
@ -632,13 +632,21 @@ diskboot:
#if (BIOS == BIOS_WBW)
;
; Check that drive actually exists
ld c,a ; put in C for func call
;ld c,a ; put in C for func call
ld b,BF_SYSGET ; HBIOS func: sys get
ld c,BF_SYSGET_DIOCNT ; HBIOS sub-func: disk count
rst 08 ; do it, E=disk count
ld a,(bootunit) ; get boot disk unit
cp e ; compare to count
jp nc,err_nodisk ; handle no disk err
;
; Sense media
ld a,(bootunit) ; get boot disk unit
ld c,a ; put in C for func call
ld b,BF_DIOMEDIA ; HBIOS func: media
ld e,1 ; enable media check/discovery
rst 08 ; do it
jp nz,err_diskio ; handle error
;
; If non-zero slice requested, confirm device can handle it
ld a,(bootslice) ; get slice
@ -652,40 +660,6 @@ diskboot:
cp DIODEV_IDE ; IDE is max slice device type
jp c,err_noslice ; no such slice, handle err
;
diskboot1:
; Sense media
ld a,(bootunit) ; get boot disk unit
ld c,a ; put in C for func call
ld b,BF_DIOMEDIA ; HBIOS func: media
ld e,1 ; enable media check/discovery
rst 08 ; do it
jp nz,err_diskio ; handle error
call pdot ; show progress
;
; Seek to boot info sector, third sector
ld a,(bootslice) ; get boot slice
ld e,a ; move to E for mult
ld h,65 ; 65 tracks per slice
call MULT8 ; hl := h * e
ld de,$0002 ; head 0, sector 2
ld b,BF_DIOSEEK ; HBIOS func: seek
ld a,(bootunit) ; get boot disk unit
ld c,a ; put in C
rst 08 ; do it
jp nz,err_diskio ; handle error
call pdot ; show progress
;
; Read sector into local buffer
ld b,BF_DIOREAD ; HBIOS func: disk read
ld a,(bootunit) ; get boot disk unit
ld c,a ; put in C for func call
ld hl,bl_infosec ; read into info sec buffer
ld d,BID_USR ; user bank
ld e,1 ; transfer one sector
rst 08 ; do it
jp nz,err_diskio ; handle error
call pdot ; show progress
;
#endif
;
#if (BIOS == BIOS_UNA)
@ -712,12 +686,67 @@ diskboot1:
jr z,diskboot1 ; if so, OK
jp err_noslice ; no such slice, handle err
;
#endif
;
diskboot1:
; Initialize working LBA value
ld hl,0 ; zero HL
ld (lba),hl ; init
ld (lba+2),hl ; ... LBA
;
; Set legacy sectors per slice
ld hl,16640 ; legacy sectors per slice
ld (sps),hl ; save it
;
; Attempt to read MBR
ld de,0 ; MBR is at
ld hl,0 ; ... first sector
ld bc,bl_mbrsec ; read into MBR buffer
ld (dma),bc ; save
ld b,1 ; one sector
ld a,(bootunit) ; get bootunit
ld c,a ; put in C
call diskread ; do it
ret nz ; abort on error
;
; Check signature
ld hl,(bl_mbrsec+$1FE) ; get signature
ld a,l ; first byte
cp $55 ; should be $55
jr nz,diskboot1c ; if not, no part table
ld a,h ; second byte
cp $AA ; should be $AA
jr nz,diskboot1c ; if not, no part table
;
; Try to find our entry in part table and capture lba offset
ld b,4 ; four entries in part table
ld hl,bl_mbrsec+$1BE+4 ; offset of first entry part type
diskboot1a:
ld a,(hl) ; get part type
cp $52 ; cp/m partition?
jr z,diskboot1b ; cool, grab the lba offset
ld de,16 ; part table entry size
add hl,de ; bump to next entry part type
djnz diskboot1a ; loop thru table
jr diskboot1c ; too bad, no cp/m partition
;
diskboot1b:
; Capture the starting LBA of the CP/M partition we found
ld de,4 ; LBA is 4 bytes after part type
add hl,de ; point to it
ld de,lba ; loc to store lba offset
ld bc,4 ; 4 bytes (32 bits)
ldir ; copy it
; If boot from partition, use new sectors per slice value
ld hl,16384 ; new sectors per slice
ld (sps),hl ; save it
;
diskboot1c:
; Add slice offset
ld a,(bootslice) ; get boot slice, A is loop cnt
ld hl,0 ; DE:HL is LBA
ld de,0 ; ... initialize to zero
ld bc,16640 ; sectors per slice
ld hl,(lba) ; set DE:HL
ld de,(lba+2) ; ... to starting LBA
ld bc,(sps) ; sectors per slice
diskboot2:
or a ; set flags to check loop ctr
jr z,diskboot4 ; done if counter exhausted
@ -729,30 +758,30 @@ diskboot3:
jr diskboot2 ; and loop
;
diskboot4:
ld (loadlba),hl ; save lba, low word
ld (loadlba+2),de ; save lba, high word
ld (lba),hl ; update lba, low word
ld (lba+2),de ; update lba, high word
;
; Seek to boot info sector, third sector
push hl ; save HL
ld hl,str_ldsec ; display prefix
call pstr ; do it
pop hl ; restore HL
call prthex32 ; display starting sector
call pdot ; show progress
;
; Read boot info sector, third sector
ld bc,2 ; sector offset
add hl,bc ; add to LBA value low word
jr nc,diskboot5 ; check for carry
inc de ; if so, bump high word
diskboot5:
ld a,(bootunit) ; get disk unit to boot
ld b,a ; put in B for func call
ld c,$41 ; UNA func: set lba
rst 08 ; set lba
jp nz,err_api ; handle error
ld bc,bl_infosec ; read buffer
ld (dma),bc ; save
ld a,(bootunit) ; disk unit to read
ld c,a ; put in C
ld b,1 ; one sector
call diskread ; do it
ret nz ; abort on error
call pdot ; show progress
;
; Read sector into local buffer
ld c,$42 ; UNA func: read sectors
ld de,bl_infosec ; dest of cpm image
ld l,1 ; sectors to read
rst 08 ; do read
jp nz,err_diskio ; handle error
;
#endif
;
; Check signature
ld de,(bb_sig) ; get signature read
@ -762,6 +791,7 @@ diskboot5:
ld a,$5A ; expected value of second byte
cp e ; compare
jp nz,err_sig ; handle error
call pdot ; show progress
;
; Print disk boot info
; Volume "xxxxxxx" (0xXXXX-0xXXXX, entry @ 0xXXXX)
@ -774,17 +804,17 @@ diskboot5:
call pstr ; print
push hl ; save string ptr
ld bc,(bb_cpmloc) ; get load loc
call PRTHEXWORD ; print it
call prthexword ; print it
pop hl ; restore string ptr
call pstr ; print
push hl ; save string ptr
ld bc,(bb_cpmend) ; get load end
call PRTHEXWORD ; print it
call prthexword ; print it
pop hl ; restore string ptr
call pstr ; print
push hl ; save string ptr
ld bc,(bb_cpment) ; get load end
call PRTHEXWORD ; print it
call prthexword ; print it
pop hl ; restore string ptr
call pstr ; print
;
@ -798,19 +828,25 @@ diskboot5:
ld (loadcnt),a ; ... and save it
call pdot ; show progress
;
#if (BIOS == BIOS_WBW)
;
; Load image into memory
ld b,BF_DIOREAD ; HBIOS func: read sectors
; Start OS load at sector 3
ld hl,(lba) ; low word of saved LBA
ld de,(lba+2) ; high word of saved LBA
ld bc,3 ; offset for sector 3
add hl,bc ; apply it
jr nc,diskboot6 ; check for carry
inc de ; bump high word if so
diskboot6:
ld bc,(bb_cpmloc) ; load address
ld (dma),bc ; and save it
ld a,(loadcnt) ; get sectors to read
ld b,a ; put in B
ld a,(bootunit) ; get boot disk unit
ld c,a ; put in C
ld hl,(bb_cpmloc) ; load address
ld d,BID_USR ; user bank
ld a,(loadcnt) ; get sectors to read
ld e,a ; number of sectors to load
rst 08 ; do it
jp nz,err_diskio ; handle errors
call diskread ; read image
ret nz ; abort on error
call pdot ; show progress
;
#if (BIOS == BIOS_WBW)
;
; Record boot unit/slice
ld b,BF_SYSSET ; hb func: set hbios parameter
@ -823,36 +859,10 @@ diskboot5:
ld e,a ; save in E
rst 08
jp nz,err_api ; handle errors
call pdot ; show progress
;
#endif
;
#if (BIOS == BIOS_UNA)
;
; Start os load at sector 3
ld hl,(loadlba) ; low word of saved LBA
ld de,(loadlba+2) ; high word of saved LBA
ld bc,3 ; offset for sector 3
add hl,bc ; apply it
jr nc,diskboot6 ; check for carry
inc de ; bump high word if so
diskboot6:
ld c,$41 ; UNA func: set lba
ld a,(bootunit) ; get boot disk unit
ld b,a ; move to B
rst 08 ; set lba
jp nz,err_api ; handle error
;
; Read OS image into memory
ld c,$42 ; UNA func: read sectors
ld a,(bootunit) ; get boot disk unit
ld b,a ; move to B
ld de,(bb_cpmloc) ; dest of cpm image
ld a,(loadcnt) ; get sectors to read
ld l,a ; sectors to read
rst 08 ; do read
jp nz,err_diskio ; handle error
call pdot ; show progress
;
; Record boot unit/slice
; UNA provides only a single byte to record the boot unit
@ -876,6 +886,8 @@ diskboot6:
call pdot ; show progress
;
#endif
;
call pdot ; show progress
;
#if (DSKYENABLE)
ld hl,msg_go ; point to go message
@ -886,6 +898,55 @@ diskboot6:
ld hl,(bb_cpment) ; get entry vector
jp (hl) ; and go there
;
; Read disk sector(s)
; DE:HL is LBA, B is sector count, C is disk unit
;
diskread:
;
#if (BIOS == BIOS_UNA)
;
; Seek to requested sector in DE:HL
push bc ; save unit and count
ld b,c ; unit to read in B
ld c,$41 ; UNA func: set lba
rst 08 ; set lba
pop bc ; recover unit and count
jp nz,err_api ; handle error
;
; Read sector(s) into buffer
ld l,b ; sectors to read
ld b,c ; unit to read in B
ld c,$42 ; UNA func: read sectors
ld de,(dma) ; dest for read
rst 08 ; do read
jp nz,err_diskio ; handle error
xor a ; signal success
ret ; and done
;
#endif
;
#if (BIOS == BIOS_WBW)
;
; Seek to requested sector in DE:HL
push bc ; save unit & count
set 7,d ; set LBA access flag
ld b,BF_DIOSEEK ; HBIOS func: seek
rst 08 ; do it
pop bc ; recover unit & count
jp nz,err_diskio ; handle error
;
; Read sector(s) into buffer
ld e,b ; transfer count
ld b,BF_DIOREAD ; HBIOS func: disk read
ld hl,(dma) ; read into info sec buffer
ld d,BID_USR ; user bank
rst 08 ; do it
jp nz,err_diskio ; handle error
xor a ; signal success
ret ; and done
;
#endif
;
;=======================================================================
; Utility functions
;=======================================================================
@ -1079,6 +1140,269 @@ isnum1:
or $FF ; set NZ
ret ; and done
;
; Delay 16us (cpu speed compensated) incuding call/ret invocation
; Register A and flags destroyed
; No compensation for z180 memory wait states
; There is an overhead of 3ts per invocation
; Impact of overhead diminishes as cpu speed increases
;
; cpu scaler (cpuscl) = (cpuhmz - 2) for 16us + 3ts delay
; note: cpuscl must be >= 1!
;
; example: 8mhz cpu (delay goal is 16us)
; loop = ((6 * 16) - 5) = 91ts
; total cost = (91 + 40) = 131ts
; actual delay = (131 / 8) = 16.375us
;
; --- total cost = (loop cost + 40) ts -----------------+
delay: ; 17ts (from invoking call) |
ld a,(cpuscl) ; 13ts |
; |
delay1: ; |
; --- loop = ((cpuscl * 16) - 5) ts ------------+ |
dec a ; 4ts | |
#if (BIOS == BIOS_WBW) ; | |
#if (CPUFAM == CPU_Z180) ; | |
or a ; +4ts for z180 | |
#endif ; | |
#endif ; | |
jr nz,delay1 ; 12ts (nz) / 7ts (z) | |
; ----------------------------------------------+ |
; |
ret ; 10ts (return) |
;-------------------------------------------------------+
;
; Delay 16us * DE (cpu speed compensated)
; Register DE, A, and flags destroyed
; No compensation for z180 memory wait states
; There is a 27ts overhead for call/ret per invocation
; Impact of overhead diminishes as DE and/or cpu speed increases
;
; cpu scaler (cpuscl) = (cpuhmz - 2) for 16us outer loop cost
; note: cpuscl must be > 0!
;
; Example: 8MHz cpu, DE=6250 (delay goal is .1 sec or 100,000us)
; inner loop = ((16 * 6) - 5) = 91ts
; outer loop = ((91 + 37) * 6250) = 800,000ts
; actual delay = ((800,000 + 27) / 8) = 100,003us
;
; --- total cost = (outer loop + 27) ts ------------------------+
vdelay: ; 17ts (from invoking call) |
; |
; --- outer loop = ((inner loop + 37) * de) ts ---------+ |
ld a,(cpuscl) ; 13ts | |
; | |
vdelay1: ; | |
; --- inner loop = ((cpuscl * 16) - 5) ts ------+ | |
#if (BIOS == BIOS_WBW) ; | | |
#if (CPUFAM == CPU_Z180) ; | | |
or a ; +4ts for z180 | | |
#endif ; | | |
#endif ; | | |
dec a ; 4ts | | |
jr nz,vdelay1 ; 12ts (nz) / 7ts (z) | | |
; ----------------------------------------------+ | |
; | |
dec de ; 6ts | |
#if (BIOS == BIOS_WBW) ; | | |
#if (CPUFAM == CPU_Z180) ; | |
or a ; +4ts for z180 | |
#endif ; | |
#endif ; | |
ld a,d ; 4ts | |
or e ; 4ts | |
jp nz,vdelay ; 10ts | |
;-------------------------------------------------------+ |
; |
ret ; 10ts (final return) |
;---------------------------------------------------------------+
;
; Delay about 0.5 seconds
; 500000us / 16us = 31250
;
ldelay:
push af
push de
ld de,31250
call vdelay
pop de
pop af
ret
;
; Initialize delay scaler based on operating cpu speed
; HBIOS *must* be installed and available via rst 8!!!
; CPU scaler := max(1, (phimhz - 2))
;
delay_init:
#if (BIOS == BIOS_UNA)
ld c,$F8 ; UNA bios get phi function
rst 08 ; returns speed in hz in de:hl
ld b,4 ; divide mhz in de:hl by 100000h
delay_init0:
srl d ; ... to get approx cpu speed in
rr e ; ...mhz. throw away hl, and
djnz delay_init0 ; ...right shift de by 4.
inc e ; fix up for value truncation
ld a,e ; put in a
#else
ld b,BF_SYSGET ; HBIOS func=get sys info
ld c,BF_SYSGET_CPUINFO ; HBIOS subfunc=get cpu info
rst 08 ; call HBIOS, rst 08 not yet installed
ld a,l ; put speed in mhz in accum
#endif
cp 3 ; test for <= 2 (special handling)
jr c,delay_init1 ; if <= 2, special processing
sub 2 ; adjust as required by delay functions
jr delay_init2 ; and continue
delay_init1:
ld a,1 ; use the min value of 1
delay_init2:
ld (cpuscl),a ; update cpu scaler value
ret
#if (CPUMHZ < 3)
cpuscl .db 1 ; cpu scaler must be > 0
#else
cpuscl .db CPUMHZ - 2 ; otherwise 2 less than phi mhz
#endif
;
; Print value of a in decimal with leading zero suppression
;
prtdecb:
push hl
push af
ld l,a
ld h,0
call prtdec
pop af
pop hl
ret
;
; Print value of HL in decimal with leading zero suppression
;
prtdec:
push bc
push de
push hl
ld e,'0'
ld bc,-10000
call prtdec1
ld bc,-1000
call prtdec1
ld bc,-100
call prtdec1
ld c,-10
call prtdec1
ld e,0
ld c,-1
call prtdec1
pop hl
pop de
pop bc
ret
prtdec1:
ld a,'0' - 1
prtdec2:
inc a
add hl,bc
jr c,prtdec2
sbc hl,bc
cp e
jr z,prtdec3
ld e,0
call cout
prtdec3:
ret
;
; Short delay functions. No clock speed compensation, so they
; will run longer on slower systems. The number indicates the
; number of call/ret invocations. A single call/ret is
; 27 t-states on a z80, 25 t-states on a z180.
;
; ; z80 z180
; ; ---- ----
dly64: call dly32 ; 1728 1600
dly32: call dly16 ; 864 800
dly16: call dly8 ; 432 400
dly8: call dly4 ; 216 200
dly4: call dly2 ; 108 100
dly2: call dly1 ; 54 50
dly1: ret ; 27 25
;
; Add hl,a
;
; A register is destroyed!
;
addhla:
add a,l
ld l,a
ret nc
inc h
ret
;
; Print the hex byte value in A
;
prthexbyte:
push af
push de
call hexascii
ld a,d
call cout
ld a,e
call cout
pop de
pop af
ret
;
; Print the hex word value in BC
;
prthexword:
push af
ld a,b
call prthexbyte
ld a,c
call prthexbyte
pop af
ret
;
; Print the hex dword value in DE:HL
;
prthex32:
push bc
push de
pop bc
call prthexword
push hl
pop bc
call prthexword
pop bc
ret
;
; Convert binary value in A to ASCII hex characters in DE
;
hexascii:
ld d,a
call hexconv
ld e,a
ld a,d
rlca
rlca
rlca
rlca
call hexconv
ld d,a
ret
;
; Convert low nibble of A to ASCII hex
;
hexconv:
and 0Fh ; low nibble only
add a,90h
daa
adc a,40h
daa
ret
;
;=======================================================================
; Console character I/O helper routines (registers preserved)
;=======================================================================
@ -1241,7 +1565,7 @@ prtall1:
ld hl,str_disk ; prefix string
call pstr ; display it
ld a,c ; index
call PRTDECB ; print it
call prtdecb ; print it
ld hl,str_on ; separator string
call pstr
push bc ; save loop control
@ -1268,7 +1592,7 @@ prtdrv:
and $0F ; isolate device bits
add a,a ; multiple by two for word table
ld hl,devtbl ; point to start of table
call ADDHLA ; add A to HL for table entry
call addhla ; add A to HL for table entry
ld a,(hl) ; deref HL for string adr
inc hl ; ...
ld h,(hl) ; ...
@ -1277,7 +1601,7 @@ prtdrv:
pop hl ; recover HL
pop de ; recover DE
ld a,e ; device number
call PRTDECB ; print it
call prtdecb ; print it
ld a,':' ; suffix
call cout ; print it
ret
@ -1340,7 +1664,7 @@ prtdrv:
ld hl,str_disk ; prefix string
call pstr ; display it
ld a,b ; index
call PRTDECB ; print it
call prtdecb ; print it
ld a,' ' ; formatting
call cout ; do it
ld a,'=' ; formatting
@ -1380,7 +1704,7 @@ prtdrv2: ; print device
pop bc ; recover unit
call pstr ; print device name
ld a,b ; unit to a
call PRTDECB ; print it
call prtdecb ; print it
ld a,':' ; device name suffix
call cout ; print it
ret ; done
@ -1452,10 +1776,12 @@ str_err_api .db "Unexpected hardware BIOS API failure",0
;=======================================================================
;
#define USEDELAY
#include "util.asm"
; #include "util.asm"
;
#if (DSKYENABLE)
#define DSKY_KBD
VDELAY .equ vdelay
DLY2 .equ dly2
#include "dsky.asm"
#endif
;
@ -1492,6 +1818,7 @@ str_binfo2 .db $22," [0x",0
str_binfo3 .db "-0x",0
str_binfo4 .db ", entry @ 0x",0
str_binfo5 .db "]",0
str_ldsec .db ", Sector 0x",0
;
str_help .db "\r\n"
.db "\r\n L - List ROM Applications"
@ -1651,9 +1978,12 @@ bid_ldr .ds 1 ; bank at startup
#endif
#if (BIOS == BIOS_UNA)
bid_ldr .ds 2 ; bank at startup
loadlba .ds 4 ; lba for load, dword
#endif
;
lba .ds 4 ; lba for load, dword
dma .ds 2 ; address for load
sps .ds 2 ; sectors per slice
;
ra_tbl_loc .ds 2 ; points to active ra_tbl
bootunit .ds 1 ; boot disk unit
bootslice .ds 1 ; boot disk slice
@ -1685,5 +2015,11 @@ bb_biloc .ds 2 ; loc to patch boot drive info
bb_cpmloc .ds 2 ; final ram dest for cpm/cbios
bb_cpmend .ds 2 ; end address for load
bb_cpment .ds 2 ; CP/M entry point (cbios boot)
;
;
; Master Boot Record sector is read into area below.
;
bl_mbrsec .equ $
.ds 512
;
.end

26
Source/Images/Build.cmd

@ -4,24 +4,24 @@ setlocal
echo.
echo Building Floppy Disk Images...
echo.
call BuildFD.cmd cpm22 ..\cpm22\cpm_wbw.sys
call BuildFD.cmd zsdos ..\zsdos\zsys_wbw.sys
call BuildFD.cmd nzcom ..\zsdos\zsys_wbw.sys
call BuildFD.cmd cpm3 ..\cpm3\cpmldr.sys
call BuildFD.cmd zpm3 ..\cpm3\cpmldr.sys
call BuildFD.cmd ws4
call BuildFD.cmd cpm22 wbw_fd144 ..\cpm22\cpm_wbw.sys
call BuildFD.cmd zsdos wbw_fd144 ..\zsdos\zsys_wbw.sys
call BuildFD.cmd nzcom wbw_fd144 ..\zsdos\zsys_wbw.sys
call BuildFD.cmd cpm3 wbw_fd144 ..\cpm3\cpmldr.sys
call BuildFD.cmd zpm3 wbw_fd144 ..\cpm3\cpmldr.sys
call BuildFD.cmd ws4 wbw_fd144
echo.
echo Building Hard Disk Images...
echo.
call BuildHD.cmd cpm22 ..\cpm22\cpm_wbw.sys
call BuildHD.cmd zsdos ..\zsdos\zsys_wbw.sys
call BuildHD.cmd nzcom ..\zsdos\zsys_wbw.sys
call BuildHD.cmd cpm3 ..\cpm3\cpmldr.sys
call BuildHD.cmd zpm3 ..\cpm3\cpmldr.sys
call BuildHD.cmd ws4
call BuildHD.cmd cpm22 wbw_hd0 ..\cpm22\cpm_wbw.sys
call BuildHD.cmd zsdos wbw_hd0 ..\zsdos\zsys_wbw.sys
call BuildHD.cmd nzcom wbw_hd0 ..\zsdos\zsys_wbw.sys
call BuildHD.cmd cpm3 wbw_hd0 ..\cpm3\cpmldr.sys
call BuildHD.cmd zpm3 wbw_hd0 ..\cpm3\cpmldr.sys
call BuildHD.cmd ws4 wbw_hd0
if exist ..\BPBIOS\bpbio-ww.rel call BuildHD.cmd bp
if exist ..\BPBIOS\bpbio-ww.rel call BuildHD.cmd bp wbw_hd
echo.
echo Building Combo Disk Image...

38
Source/Images/BuildFD.ps1

@ -1,10 +1,9 @@
#Param([Parameter(Mandatory)]$Disk, $SysFile="")
Param($Disk, $SysFile="")
Param($Disk, $Format="wbw_fd144", $SysFile="")
$ErrorAction = 'Stop'
$ImgFile = "fd_${Disk}.img"
$Fmt = "wbw_fd144"
$MediaID = 6
$Size = 1440KB
$CpmToolsPath = '../../Tools/cpmtools'
@ -13,35 +12,31 @@ $env:PATH = $CpmToolsPath + ';' + $env:PATH
if (-not (Test-Path("d_${Disk}/")))
{
"Source directory d_${Disk} for disk ${Disk} not found!"
Write-Error "Source directory d_${Disk} for disk ${Disk} not found!" -ErrorAction Stop
return
}
"Generating Floppy Disk ${Disk}..."
#$Blank = ([string]([char]0xE5)) * $Size
#Set-Content -Value $Blank -NoNewLine -Path $ImgFile
$Blank = ([byte[]](0xE5) * $Size)
[System.IO.File]::WriteAllBytes($ImgFile, $Blank)
if ($SysFile.Length -gt 0)
{
"Adding System Image $SysFile..."
#$Sys = Get-Content -Path "$SysFile.sys" -Raw
#$Img = Get-Content -Path $ImgFile -Raw
#$NewImg = $Sys + $Img.SubString($Sys.Length, $Img.Length - $Sys.Length)
#Set-Content -NoNewLine -Path $ImgFile $NewImg
{ [byte[]]$SysImg = [System.IO.File]::ReadAllBytes($SysFile) }
else
{ [byte[]]$SysImg = @() }
$Cmd = "mkfs.cpm -f $Fmt -b $SysFile $ImgFile"
$Cmd
Invoke-Expression $Cmd
}
$Image = ($SysImg + ([byte[]](0xE5) * ($Size - $SysImg.length)))
$Image[1410] = 0x4D
$Image[1411] = 0x49
$Image[1412] = 0x44
$Image[1413] = $MediaID
[System.IO.File]::WriteAllBytes($ImgFile, $Image)
for ($Usr=0; $Usr -lt 16; $Usr++)
{
if (Test-Path ("d_${Disk}/u${Usr}/*"))
{
$Cmd = "cpmcp -f $Fmt $ImgFile d_${Disk}/u${Usr}/*.* ${Usr}:"
$Cmd = "cpmcp -f $Format $ImgFile d_${Disk}/u${Usr}/*.* ${Usr}:"
$Cmd
Invoke-Expression $Cmd
}
@ -54,7 +49,7 @@ if (Test-Path("d_${Disk}.txt"))
$Spec = $Line.Trim()
if (($Spec.Length -gt 0) -and ($Spec.Substring(0,1) -ne "#"))
{
$Cmd = "cpmcp -f $Fmt $ImgFile ${Spec}"
$Cmd = "cpmcp -f $Format $ImgFile ${Spec}"
$Cmd
Invoke-Expression $Cmd
}
@ -63,7 +58,6 @@ if (Test-Path("d_${Disk}.txt"))
"Moving image $ImgFile into output directory..."
#&$env:COMSPEC /c move $ImgFile ..\..\Binary\
Move-Item $ImgFile -Destination "..\..\Binary\" -Force
return

53
Source/Images/BuildHD.ps1

@ -1,11 +1,21 @@
#Param([Parameter(Mandatory)]$Disk, $SysFile="")
Param($Disk, $SysFile="")
Param($Disk, $Format="wbw_hd_new", $SysFile="")
$ErrorAction = 'Stop'
$ImgFile = "hd_${Disk}.img"
$Fmt = "wbw_hd0"
$Size = (128KB * 65)
if ($Format -like "*_new")
{
# New hard disk format!!!
$MediaID = 10
$Size = 8 * 1MB
$ImgFile = "hd_${Disk}.bin"
}
else
{
# Legacy hard disk format
$MediaID = 4
$Size = 8320KB
$ImgFile = "hd_${Disk}.img"
}
$CpmToolsPath = '../../Tools/cpmtools'
@ -13,35 +23,31 @@ $env:PATH = $CpmToolsPath + ';' + $env:PATH
if (-not (Test-Path("d_${Disk}/")))
{
"Source directory d_${Disk} for disk ${Disk} not found!"
Write-Error "Source directory d_${Disk} for disk ${Disk} not found!" -ErrorAction Stop
return
}
"Generating Hard Disk ${Disk}..."
#$Blank = ([string]([char]0xE5)) * $Size
#Set-Content -Value $Blank -NoNewLine -Path $ImgFile
$Blank = ([byte[]](0xE5) * $Size)
[System.IO.File]::WriteAllBytes($ImgFile, $Blank)
if ($SysFile.Length -gt 0)
{
"Adding System Image $SysFile..."
#$Sys = Get-Content -Path "$SysFile.sys" -Raw
#$Img = Get-Content -Path $ImgFile -Raw
#$NewImg = $Sys + $Img.SubString($Sys.Length, $Img.Length - $Sys.Length)
#Set-Content -NoNewLine -Path $ImgFile $NewImg
{ [byte[]]$SysImg = [System.IO.File]::ReadAllBytes($SysFile) }
else
{ [byte[]]$SysImg = @() }
$Cmd = "mkfs.cpm -f $Fmt -b $SysFile $ImgFile"
$Cmd
Invoke-Expression $Cmd
}
$Image = ($SysImg + ([byte[]](0xE5) * ($Size - $SysImg.length)))
$Image[1410] = 0x4D
$Image[1411] = 0x49
$Image[1412] = 0x44
$Image[1413] = $MediaID
[System.IO.File]::WriteAllBytes($ImgFile, $Image)
for ($Usr=0; $Usr -lt 16; $Usr++)
{
if (Test-Path ("d_${Disk}/u${Usr}/*"))
{
$Cmd = "cpmcp -f $Fmt $ImgFile d_${Disk}/u${Usr}/*.* ${Usr}:"
$Cmd = "cpmcp -f $Format $ImgFile d_${Disk}/u${Usr}/*.* ${Usr}:"
$Cmd
Invoke-Expression $Cmd
}
@ -54,7 +60,7 @@ if (Test-Path("d_${Disk}.txt"))
$Spec = $Line.Trim()
if (($Spec.Length -gt 0) -and ($Spec.Substring(0,1) -ne "#"))
{
$Cmd = "cpmcp -f $Fmt $ImgFile ${Spec}"
$Cmd = "cpmcp -f $Format $ImgFile ${Spec}"
$Cmd
Invoke-Expression $Cmd
}
@ -63,7 +69,6 @@ if (Test-Path("d_${Disk}.txt"))
"Moving image $ImgFile into output directory..."
#&$env:COMSPEC /c move $ImgFile ..\..\Binary\
Move-Item $ImgFile -Destination "..\..\Binary\" -Force
return

40
Source/Images/BuildNew.cmd

@ -0,0 +1,40 @@
@echo off
setlocal
echo.
echo Building Floppy Disk Images...
echo.
call BuildFD.cmd cpm22 wbw_fd144 ..\cpm22\cpm_wbw.sys
call BuildFD.cmd zsdos wbw_fd144 ..\zsdos\zsys_wbw.sys
call BuildFD.cmd nzcom wbw_fd144 ..\zsdos\zsys_wbw.sys
call BuildFD.cmd cpm3 wbw_fd144 ..\cpm3\cpmldr.sys
call BuildFD.cmd zpm3 wbw_fd144 ..\cpm3\cpmldr.sys
call BuildFD.cmd ws4 wbw_fd144
echo.
echo Building Hard Disk Images...
echo.
call BuildHD.cmd cpm22 wbw_hd_new ..\cpm22\cpm_wbw.sys
call BuildHD.cmd zsdos wbw_hd_new ..\zsdos\zsys_wbw.sys
call BuildHD.cmd nzcom wbw_hd_new ..\zsdos\zsys_wbw.sys
call BuildHD.cmd cpm3 wbw_hd_new ..\cpm3\cpmldr.sys
call BuildHD.cmd zpm3 wbw_hd_new ..\cpm3\cpmldr.sys
call BuildHD.cmd ws4 wbw_hd_new
if exist ..\BPBIOS\bpbio-ww.rel call BuildHD.cmd bp wbw_hd_new
copy hd_prefix.dat ..\..\Binary\
echo.
echo Build Hard Disk Images...
copy /b hd_prefix.dat + ..\..\Binary\hd_cpm22.bin ..\..\Binary\hd_cpm22.img
copy /b hd_prefix.dat + ..\..\Binary\hd_zsdos.bin ..\..\Binary\hd_zsdos.img
copy /b hd_prefix.dat + ..\..\Binary\hd_nzcom.bin ..\..\Binary\hd_nzcom.img
copy /b hd_prefix.dat + ..\..\Binary\hd_cpm3.bin ..\..\Binary\hd_cpm3.img
copy /b hd_prefix.dat + ..\..\Binary\hd_zpm3.bin ..\..\Binary\hd_zpm3.img
copy /b hd_prefix.dat + ..\..\Binary\hd_ws4.bin ..\..\Binary\hd_ws4.img
if exist ..\..\Binary\hd_bp.bin copy /b hd_prefix.dat + ..\..\Binary\hd_bp.bin
echo.
echo Building Combo Disk Image...
copy /b hd_prefix.dat + ..\..\Binary\hd_cpm22.bin + ..\..\Binary\hd_zsdos.bin + ..\..\Binary\hd_nzcom.bin + ..\..\Binary\hd_cpm3.bin + ..\..\Binary\hd_zpm3.bin + ..\..\Binary\hd_ws4.bin ..\..\Binary\hd_combo.img

46
Source/Images/Makefile

@ -5,12 +5,22 @@ SYSTEMS = ../CPM22/cpm_wbw.sys ../ZSDOS/zsys_wbw.sys ../CPM3/cpmldr.sys
FDIMGS = fd_cpm22.img fd_zsdos.img fd_nzcom.img \
fd_cpm3.img fd_zpm3.img fd_ws4.img
FDBIN = fd_cpm22.bin fd_zsdos.bin fd_nzcom.bin \
fd_cpm3.bin fd_zpm3.bin fd_ws4.bin
HDIMGS = hd_cpm22.img hd_zsdos.img hd_nzcom.img \
hd_cpm3.img hd_zpm3.img hd_ws4.img
HDBIN = hd_cpm22.bin hd_zsdos.bin hd_nzcom.bin \
hd_cpm3.bin hd_zpm3.bin hd_ws4.bin
# HDIMGS += hd_bp.img
# HDBIN += hd_bp.bin
OBJECTS = $(FDIMGS) $(HDIMGS) hd_combo.img
OTHERS = blank144 blankhd
HDPREFIX = # Legacy
#HDPREFIX = hd_prefix.dat # New
OBJECTS = $(FDIMGS) $(HDIMGS) hd_combo.img # Legacy
#OBJECTS = $(FDIMGS) $(HDIMGS) $(HDBIN) hd_combo.img # New
OTHERS = blank144 blankhd $(FDBIN) $(HDBIN)
DEST=../../Binary
@ -19,8 +29,8 @@ include $(TOOLS)/Makefile.inc
DIFFPATH = $(DIFFTO)/Binary
hd_combo.img: $(HDIMGS)
cat $(HDIMGS) > $@
hd_combo.img: $(HDPREFIX) $(HDBIN)
cat $^ > $@
#
# this somewhat impenetrable and fragile code is used to build each of the images
@ -30,17 +40,28 @@ hd_combo.img: $(HDIMGS)
# then process the d_{d}.txt file, copying in those files, and finally maybe put
# an OS at the start of each image
#
FDSIZE := 1440
blank144:
@echo Making Blank Floppy of size 1440k
@LANG=en_US.US-ASCII tr '\000' '\345' </dev/zero | dd of=$@ bs=1024 count=1440 2>/dev/null
@echo Making Blank Floppy of size $(FDSIZE)k
@LC_CTYPE=en_US.US-ASCII tr '\000' '\345' </dev/zero | dd of=$@ bs=1024 count=$(FDSIZE) 2>/dev/null
HDSIZE := $(shell expr 128 '*' 65)
HDSIZE := 8320 # Legacy
#HDSIZE := 8192 # New
blankhd:
@echo Making Blank Hd of size $(HDSIZE)k
@LANG=en_US.US-ASCII tr '\000' '\345' </dev/zero | dd of=$@ bs=1024 count=$(HDSIZE) 2>/dev/null
@LC_CTYPE=en_US.US-ASCII tr '\000' '\345' </dev/zero | dd of=$@ bs=1024 count=$(HDSIZE) 2>/dev/null
%.img: %.bin
@if echo $@ | grep -q ^f ; then \
cat $< > $@ ; \
else \
cat $(HDPREFIX) $< > $@ ; \
fi ; \
%.img: $(SYSTEMS) blank144 blankhd Makefile
%.bin: $(SYSTEMS) blank144 blankhd Makefile
@sys= ; \
case $@ in \
(*cpm22*) sys=../CPM22/cpm_wbw.sys;; \
@ -49,8 +70,12 @@ blankhd:
esac ; \
if echo $@ | grep -q ^f ; then \
fmt=wbw_fd144 ; type=fd_ ; proto=blank144 ; \
mid="MID\006" ; \
else \
#fmt=wbw_hd_new ; type=hd_ ; proto=blankhd ; \
#mid="MID\012" ; \
fmt=wbw_hd0 ; type=hd_ ; proto=blankhd ; \
mid="MID\004" ; \
fi ; \
d=$$(echo $(basename $@) | sed s/$$type//) ; \
echo Generating $@ ; \
@ -59,6 +84,7 @@ blankhd:
echo copying system $$sys to $@ ; \
$(BINDIR)/mkfs.cpm -f $$fmt -b $$sys $@ ; \
fi ; \
LC_CTYPE=en_US.US-ASCII echo $$mid | dd bs=1 count=4 seek=1410 conv=notrunc of=$@ ; \
for u in $$(seq 0 15) ; do \
dir=d_$$d/u$$u ; \
if [ -d $$dir ] ; then \
@ -93,7 +119,7 @@ imgdiff:
if echo $$i | grep -q ^f ; then \
fmt=wbw_fd144 ; \
else \
fmt=wbw_hd0 ; \
fmt=wbw_hd0_1024 ; \
fi ; \
$(BINDIR)/cpmls -i -f $$fmt $$i > $$i.ls ; \
$(BINDIR)/cpmls -i -f $$fmt $(DIFFPATH)/$$i > $$i.diff.ls ; \

139
Source/Images/diskdefs

@ -297,121 +297,158 @@ diskdef wbw_rom1024
os 2.2
end
# UNA 512KB ROM (128KB reserved, 384KB ROM Disk)
# RomWBW 720K floppy media
diskdef wbw_fd720
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom512
# RomWBW 1.44M floppy media
diskdef wbw_fd144
seclen 512
tracks 12
sectrk 64
tracks 160
sectrk 18
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# UNA 512KB ROM (128KB reserved, 896KB ROM Disk)
# RomWBW 360K floppy media
diskdef wbw_fd360
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom1024
# RomWBW 1.20M floppy media
diskdef wbw_fd120
seclen 512
tracks 28
sectrk 64
tracks 160
sectrk 15
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# RomWBW 8MB Hard Disk, LU 0-3
# RomWBW 8MB Hard Disk, first 4 slices
# Legacy format, 512 dir entries, 8,320 sectors / slice
diskdef wbw_hd0
seclen 512
tracks 65
sectrk 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 1
boottrk 16
os 2.2
end
diskdef wbw_hd1
seclen 512
tracks 130
sectrk 256
tracks 2080
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 66
boottrk 1056
os 2.2
end
diskdef wbw_hd2
seclen 512
tracks 195
sectrk 256
tracks 3120
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 131
boottrk 2096
os 2.2
end
diskdef wbw_hd3
seclen 512
tracks 260
sectrk 256
tracks 4160
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 196
boottrk 3136
os 2.2
end
# RomWBW 720K floppy media
diskdef wbw_fd720
# RomWBW 8MB Hard Disk
# New format, 1024 dir entries, 8,192 sectors / slice
# Pure filesystem image, no prefix
diskdef wbw_hd_new
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
tracks 1024
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 2
os 2.2
end
# RomWBW 1.44M floppy media
diskdef wbw_fd144
# RomWBW 8MB Hard Disk, first 4 slices
# New format, 1024 dir entries, 8,192 sectors / slice
# Assumes 256 sector (16 track) hard disk prefix
diskdef wbw_hd0_new
seclen 512
tracks 160
sectrk 18
blocksize 2048
maxdir 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 18
os 2.2
end
# RomWBW 360K floppy media
diskdef wbw_fd360
diskdef wbw_hd1_new
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
tracks 2064
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 1042
os 2.2
end
# RomWBW 1.20M floppy media
diskdef wbw_fd120
diskdef wbw_hd2_new
seclen 512
tracks 160
sectrk 15
blocksize 2048
maxdir 256
tracks 3112
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 2066
os 2.2
end
diskdef wbw_hd3_new
seclen 512
tracks 4136
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 3114
os 2.2
end

BIN
Source/Images/hd_prefix.dat

Binary file not shown.

4
Source/ver.inc

@ -1,5 +1,5 @@
#DEFINE RMJ 3
#DEFINE RMN 1
#DEFINE RUP 0
#DEFINE RUP 1
#DEFINE RTP 0
#DEFINE BIOSVER "3.1-pre.16"
#DEFINE BIOSVER "3.1.1-pre.0"

4
Source/ver.lib

@ -1,7 +1,7 @@
rmj equ 3
rmn equ 1
rup equ 0
rup equ 1
rtp equ 0
biosver macro
db "3.1-pre.16"
db "3.1.1-pre.0"
endm

139
Tools/cpmtools/diskdefs

@ -297,121 +297,158 @@ diskdef wbw_rom1024
os 2.2
end
# UNA 512KB ROM (128KB reserved, 384KB ROM Disk)
# RomWBW 720K floppy media
diskdef wbw_fd720
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom512
# RomWBW 1.44M floppy media
diskdef wbw_fd144
seclen 512
tracks 12
sectrk 64
tracks 160
sectrk 18
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# UNA 512KB ROM (128KB reserved, 896KB ROM Disk)
# RomWBW 360K floppy media
diskdef wbw_fd360
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
skew 0
boottrk 4
os 2.2
end
diskdef una_rom1024
# RomWBW 1.20M floppy media
diskdef wbw_fd120
seclen 512
tracks 28
sectrk 64
tracks 160
sectrk 15
blocksize 2048
maxdir 256
skew 0
boottrk 0
boottrk 2
os 2.2
end
# RomWBW 8MB Hard Disk, LU 0-3
# RomWBW 8MB Hard Disk, first 4 slices
# Legacy format, 512 dir entries, 8,320 sectors / slice
diskdef wbw_hd0
seclen 512
tracks 65
sectrk 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 1
boottrk 16
os 2.2
end
diskdef wbw_hd1
seclen 512
tracks 130
sectrk 256
tracks 2080
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 66
boottrk 1056
os 2.2
end
diskdef wbw_hd2
seclen 512
tracks 195
sectrk 256
tracks 3120
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 131
boottrk 2096
os 2.2
end
diskdef wbw_hd3
seclen 512
tracks 260
sectrk 256
tracks 4160
sectrk 16
blocksize 4096
maxdir 512
skew 0
boottrk 196
boottrk 3136
os 2.2
end
# RomWBW 720K floppy media
diskdef wbw_fd720
# RomWBW 8MB Hard Disk
# New format, 1024 dir entries, 8,192 sectors / slice
# Pure filesystem image, no prefix
diskdef wbw_hd_new
seclen 512
tracks 160
sectrk 9
blocksize 2048
maxdir 128
tracks 1024
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 2
os 2.2
end
# RomWBW 1.44M floppy media
diskdef wbw_fd144
# RomWBW 8MB Hard Disk, first 4 slices
# New format, 1024 dir entries, 8,192 sectors / slice
# Assumes 256 sector (16 track) hard disk prefix
diskdef wbw_hd0_new
seclen 512
tracks 160
sectrk 18
blocksize 2048
maxdir 256
tracks 1040
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 18
os 2.2
end
# RomWBW 360K floppy media
diskdef wbw_fd360
diskdef wbw_hd1_new
seclen 512
tracks 80
sectrk 9
blocksize 2048
maxdir 128
tracks 2064
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 4
boottrk 1042
os 2.2
end
# RomWBW 1.20M floppy media
diskdef wbw_fd120
diskdef wbw_hd2_new
seclen 512
tracks 160
sectrk 15
blocksize 2048
maxdir 256
tracks 3112
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 2
boottrk 2066
os 2.2
end
diskdef wbw_hd3_new
seclen 512
tracks 4136
sectrk 16
blocksize 4096
maxdir 1024
skew 0
boottrk 3114
os 2.2
end

Loading…
Cancel
Save