From 67ede2369446a6ab954cdb4f22e537b5b34cb6aa Mon Sep 17 00:00:00 2001 From: Wayne Warthen Date: Thu, 7 Apr 2016 22:56:46 -0700 Subject: [PATCH] Clean Up Drive Assignment Code --- Source/Apps/Assign.asm | 182 ++++++++++++++++++++++++++--------------- Source/CBIOS/cbios.asm | 60 +++++++------- 2 files changed, 148 insertions(+), 94 deletions(-) diff --git a/Source/Apps/Assign.asm b/Source/Apps/Assign.asm index e00a6b18..d01197fb 100644 --- a/Source/Apps/Assign.asm +++ b/Source/Apps/Assign.asm @@ -19,6 +19,7 @@ ; ; Change Log: ; 2016-03-21 [WBW] Updated for HBIOS 2.8 +; 2016-04-07 [WBW] Determine key memory addresses dynamically ;_______________________________________________________________________________ ; ; ToDo: @@ -77,11 +78,11 @@ exit: ; clean up and return to command processor ; init: ; - ; locate cbios function table address + ; locate start of cbios (function jump table) ld hl,(restart+1) ; load address of CP/M restart vector ld de,-3 ; adjustment for start of table add hl,de ; HL now has start of table - ld (cbftbl),hl ; save it + ld (bioloc),hl ; save it ; ; get location of config data and verify integrity ld hl,stamp ; HL := adr or RomWBW zero page stamp @@ -133,6 +134,10 @@ init: ld c,a ; set BC := 0A ld b,0 ; ... so BC is length to copy ldir ; do the copy +; + ; determine end of CBIOS (assume HBIOS for now) + ld hl,($FFFE) ; get proxy start address + ld (bioend),hl ; save as CBIOS end address ; ; check for UNA (UBIOS) ld a,($fffd) ; fixed location of UNA API vector @@ -148,8 +153,23 @@ init: jr nz,initx ; if not, not UNA ld hl,unamod ; point to UNA mode flag ld (hl),$ff ; set UNA mode + ld hl,$FF00 ; assumed start of UNA proxy + ld (bioend),hl ; save as CBIOS end address ; initx: + ; compute size of CBIOS + ld hl,(bioend) ; HL := end address + ld de,(bioloc) ; DE := starting address + xor a ; clear carry + sbc hl,de ; subtract to get size in HL + ld (biosiz),hl ; and save it +; + ; establish heap limit + ld hl,(bioend) ; HL := end of CBIOS address + ld de,-$40 ; allow 40 bytes for CBIOS stack + add hl,de ; adjust + ld (heaplim),hl ; save it +; ; return success xor a ; signal success ret ; return @@ -336,19 +356,19 @@ devlstu1: ; install: ; capture CBIOS snapshot and stack frame for error recovery - ld hl,$e600 ; start of CBIOS + ld hl,(bioloc) ; start of CBIOS ld de,$8000 ; save it here - ld bc,$fc00 - $e600 ; size of CBIOS + ld bc,(biosiz) ; size of CBIOS ldir ; save it ld (xstksav),sp ; save stack frame ; clear CBIOS buffer area ld hl,(maploc) ; start fill at drive map - ld a,$FC ; stop when msb is $FC + ld a,(bioend + 1) ; msb of CBIOS end address to A install1: ld e,0 ; fill with null ld (hl),e ; fill next byte inc hl ; point to next byte - cp h ; is H == $FC? + cp h ; is H == msb of CBIOS end address? jr nz,install1 ; if not, loop ; ; determine the drive map entry count @@ -384,15 +404,13 @@ install3: ld de,(maploc) ; target is CBIOS map loc ldir ; do it ; - ; set start of allocation memory - ld (buftop),de ; DE has next byte available + ; set start of memory allocation heap + ld (heaptop),de ; DE has next byte available ; ; allocate directory buffer - ld bc,128 ; size of directory buffer + ld hl,128 ; size of directory buffer call alloc ; allocate the space - jp nz,instovf ; handle overflow error - push bc ; move mem pointer - pop hl ; ... to hl + jp c,instovf ; handle overflow error ld (dirbuf),hl ; ... and save in dirbuf ; dph_init: @@ -415,16 +433,16 @@ dph_init1: jr dph_init3 ; dph_init2: + ld a,(hl) ; unit to A push bc ; save loop control push hl ; save drive map pointer - ld bc,16 ; size of a DPH structure + ld hl,16 ; size of a DPH structure call alloc ; allocate space for dph - jp nz,instovf ; handle overflow error - push bc ; save DPH location - push bc ; move DPH location + jp c,instovf ; handle overflow error + push hl ; save DPH location + push hl ; move DPH location pop de ; ... to DE - ld a,(hl) ; unit to A - call makdph ; make the DPH + call makdph ; make the DPH, unit in A from above pop de ; restore DPH pointer to DE pop hl ; restore drive map pointer to HL pop bc ; restore loop control @@ -443,8 +461,8 @@ dph_init3: call crlf2 ld de,indent call prtstr - ld hl,$fc00 ; subtract high water - ld de,(buftop) ; ... from top of cbios + ld hl,(heaplim) ; subtract high water + ld de,(heaptop) ; ... from top of cbios or a ; ... with cf clear sbc hl,de ; ... so hl gets bytes free call prtdecw ; print it @@ -544,19 +562,57 @@ makdph1: dec de ; ... prefix data (cks & als buf sizes) call makdph2 ; handle cks buf, then fall thru for als buf ret nz ; bail out on error + +;makdph2: +; ex de,hl ; point hl to cks/als size adr +; ld c,(hl) ; bc := cks/als size +; inc hl ; ... and bump +; ld b,(hl) ; ... past +; inc hl ; ... cks/als size +; ex de,hl ; bc and hl roles restored +; ld a,b ; check to see +; or c ; ... if bc is zero +; jr z,makdph3 ; if zero, bypass alloc, use zero for address +; call alloc ; alloc bc bytes, address returned in bc +; jp nz,instovf ; handle overflow error +;makdph3: +; ld (hl),c ; save cks/als buf +; inc hl ; ... address in +; ld (hl),b ; ... dph and bump +; inc hl ; ... to next dph entry +; xor a ; signal success +; ret + makdph2: - ex de,hl ; point hl to cks/als size adr - ld c,(hl) ; bc := cks/als size - inc hl ; ... and bump - ld b,(hl) ; ... past - inc hl ; ... cks/als size - ex de,hl ; bc and hl roles restored - ld a,b ; check to see - or c ; ... if bc is zero - jr z,makdph3 ; if zero, bypass alloc, use zero for address - call alloc ; alloc bc bytes, address returned in bc - jp nz,instovf ; handle overflow error + ; DE = address of CKS or ALS buf to allocate + ; HL = address of field in DPH to get allocated address + push hl ; save DPH field ptr + pop bc ; into BC +; + ; HL := alloc size, DE bumped + ex de,hl + ld e,(hl) ; get size to allocate + inc hl ; ... + ld d,(hl) ; ... into HL + inc hl ; and bump DE + ex de,hl +; + ; check for size of zero, special case + ld a,h ; check to see + or l ; ... if hl is zero + jr z,makdph3 ; if so, jump ahead using hl as address +; + ; allocate memory + call alloc ; do the allocation + jp c,instovf ; bail out on overflow + makdph3: + ; swap hl and bc + push bc ; bc -> (sp) + ex (sp),hl ; (sp) -> hl, hl -> (sp) + pop bc ; (sp) -> bc +; + ; save allocated address ld (hl),c ; save cks/als buf inc hl ; ... address in ld (hl),b ; ... dph and bump @@ -570,40 +626,30 @@ instovf: ; restore stack frame and CBIOS image ld sp,(xstksav) ; restore stack frame ld hl,$8000 ; start of CBIOS image buffer - ld de,$e600 ; start of CBIOS - ld bc,$fc00 - $e600 ; size of CBIOS + ld de,(bioloc) ; start of CBIOS + ld bc,(biosiz) ; size of CBIOS ldir ; restore it jp errovf ; -alloc: +; Allocate HL bytes from heap +; Return pointer to allocated memory in HL +; On overflow error, C set ; -; allocate bc bytes from buf pool, return starting -; address in bc. leave all other regs alone except a -; z for success, nz for failure -; - push de ; save original de - push hl ; save original hl - ld hl,(buftop) ; hl := current buffer top - push hl ; save as start of new buffer - push bc ; get byte count - pop de ; ... into de - add hl,de ; add it to buffer top - ld a,$ff ; assume overflow failure - jr c,alloc1 ; if overflow, bypass with a == $ff - push hl ; save it - ld de,$10000 - $FC00 + $40 ; setup de for overflow test - add hl,de ; check for overflow - pop hl ; recover hl - ld a,$ff ; assume failure - jr c,alloc1 ; if overflow, continue with a == $ff - ld (buftop),hl ; save new top - inc a ; signal success -; -alloc1: - pop bc ; buf start address to bc - pop hl ; restore original hl - pop de ; restore original de - or a ; signal success +alloc: + push de ; save de so we can use it for work reg + ld de,(heaptop) ; get current heap top + push de ; and save for return value + add hl,de ; add requested space, hl := new heap top + jr c,allocx ; test for cpu memory space overflow + ld de,(heaplim) ; load de with heap limit + ex de,hl ; de=new heaptop, hl=heaplim + sbc hl,de ; heaplim - heaptop + jr c,allocx ; c set on overflow error + ; allocation succeeded, commit new heaptop + ld (heaptop),de ; save new heaptop +allocx: + pop hl ; return value to hl + pop de ; recover de ret ; ; Scan drive map table for integrity @@ -1461,7 +1507,7 @@ cbios: ld a,(hl) ; get the function offset inc hl ; point past value following call instruction ex (sp),hl ; put address back at top of stack and recover HL - ld hl,(cbftbl) ; address of CBIOS function table to HL + ld hl,(bioloc) ; address of CBIOS function table to HL call addhl ; determine specific function address jp (hl) ; invoke CBIOS ; @@ -1564,9 +1610,13 @@ err2: ; without the string ; Storage Section ;=============================================================================== ; -cbftbl .dw 0 ; address of CBIOS function table +; +bioloc .dw 0 ; CBIOS starting address +bioend .dw 0 ; CBIOS ending address +biosiz .dw 0 ; CBIOS size (in bytes) maploc .dw 0 ; location of CBIOS drive map table dpbloc .dw 0 ; location of CBIOS DPB map table +; drives: dstdrv .db 0 ; destination drive srcdrv .db 0 ; source drive @@ -1582,7 +1632,9 @@ dstptr .dw 0 ; destination pointer for copy tmpent .fill 4,0 ; space to save a table entry tmpstr .fill 9,0 ; temporary string of up to 8 chars, zero term ; -buftop .dw 0 ; memory allocation buffer top +heaptop .dw 0 ; current address of top of heap memory +heaplim .dw 0 ; heap limit address +; dirbuf .dw 0 ; directory buffer location ; mapwrk .fill (4 * 16),$FF ; working copy of drive map @@ -1629,7 +1681,7 @@ stack .equ $ ; stack top ; Messages ; indent .db " ",0 -msgban1 .db "ASSIGN v1.0b for RomWBW CP/M 2.2, 20-Mar-2016",0 +msgban1 .db "ASSIGN v1.0c for RomWBW CP/M 2.2, 7-Apr-2016",0 msghb .db " (HBIOS Mode)",0 msgub .db " (UBIOS Mode)",0 msgban2 .db "Copyright 2016, Wayne Warthen, GNU GPL v3",0 diff --git a/Source/CBIOS/cbios.asm b/Source/CBIOS/cbios.asm index a0aed222..f2a9e8e3 100644 --- a/Source/CBIOS/cbios.asm +++ b/Source/CBIOS/cbios.asm @@ -1907,7 +1907,8 @@ INIT: ; DISPLAY FREE MEMORY LD DE,STR_LDR2 ; FORMATTING CALL WRITESTR ; AND PRINT IT - LD HL,CBIOS_END ; SUBTRACT HIGH WATER + ;LD HL,CBIOS_END ; SUBTRACT HIGH WATER + LD HL,HEAPEND ; SUBTRACT HIGH WATER LD DE,(HEAPTOP) ; ... FROM TOP OF CBIOS OR A ; ... WITH CF CLEAR SBC HL,DE ; ... SO HL GETS BYTES FREE @@ -2309,7 +2310,8 @@ DRV_INIT8: ; SLICE CREATION LOOP ; ALLOCATE ENTRY AND FILL IN UNIT, SLICE LD HL,4 ; 4 BYTES PER ENTRY CALL ALLOC ; ALLOCATE SPACE - CALL NZ,PANIC ; SHOULD NEVER ERROR HERE + ;CALL NZ,PANIC ; SHOULD NEVER ERROR HERE + CALL C,PANIC ; SHOULD NEVER ERROR HERE LD (HL),D ; SAVE UNIT IN FIRST BYTE OF DRVMAP ENTRY INC HL ; POINT TO NEXT BYTE OF DRVMAP ENTRY LD (HL),E ; SAVE SLICE NUM IN SECOND BYTE OF DRVMAP ENTRY @@ -2425,7 +2427,8 @@ DRV_INIT8: ; SLICE CREATION LOOP ; ALLOCATE ENTRY AND FILL IN UNIT, SLICE LD HL,4 ; 4 BYTES PER ENTRY CALL ALLOC ; ALLOCATE SPACE - CALL NZ,PANIC ; SHOULD NEVER ERROR HERE + ;CALL NZ,PANIC ; SHOULD NEVER ERROR HERE + CALL C,PANIC ; SHOULD NEVER ERROR HERE LD (HL),D ; SAVE UNIT IN FIRST BYTE OF DRVMAP ENTRY INC HL ; POINT TO NEXT BYTE OF DRVMAP ENTRY LD (HL),E ; SAVE SLICE NUM IN SECOND BYTE OF DRVMAP ENTRY @@ -2459,7 +2462,8 @@ DPH_INIT: ADD HL,HL ; ... OF DPH (16) ADD HL,HL ; ... FOR TOTAL SIZE CALL ALLOC ; ALLOCATE THE SPACE - CALL NZ,PANIC ; SHOULD NEVER ERROR + ;CALL NZ,PANIC ; SHOULD NEVER ERROR + CALL C,PANIC ; SHOULD NEVER ERROR ; ; SET DPHTOP TO START OF ALLOCATED SPACE LD (DPHTOP),HL ; ... AND SAVE IN DPHTOP @@ -2467,7 +2471,8 @@ DPH_INIT: ; ALLOCATE DIRECTORY BUFFER LD HL,128 ; SIZE OF DIRECTORY BUFFER CALL ALLOC ; ALLOCATE THE SPACE - CALL NZ,PANIC ; SHOULD NEVER ERROR + ;CALL NZ,PANIC ; SHOULD NEVER ERROR + CALL C,PANIC ; SHOULD NEVER ERROR LD (DIRBUF),HL ; ... AND SAVE IN DIRBUF ; ; SETUP FOR DPH BUILD LOOP @@ -2641,7 +2646,8 @@ MAKDPH2: PUSH HL ; MOVE ALLOC RESULT PTR POP BC ; ... TO BC POP HL ; RECOVER DPH PTR TO HL - JR NZ,ERR_HEAPOVF ; HANDLE POSSIBLE ALLOC OVERFLOW HERE + ;JR NZ,ERR_HEAPOVF ; HANDLE POSSIBLE ALLOC OVERFLOW HERE + JR C,ERR_HEAPOVF ; HANDLE POSSIBLE ALLOC OVERFLOW HERE LD (HL),C ; SAVE CKS/ALS BUF INC HL ; ... ADDRESS IN LD (HL),B ; ... DPH AND BUMP @@ -2649,30 +2655,26 @@ MAKDPH2: XOR A ; SIGNAL SUCCESS RET ; -ALLOC: +; ALLOCATE HL BYTES FROM HEAP +; RETURN POINTER TO ALLOCATED MEMORY IN HL +; ON OVERFLOW ERROR, C SET ; -; ALLOCATE HL BYTES FROM HEAP, RETURN STARTING -; ADDRESS IN HL. LEAVE ALL OTHER REGS ALONE EXCEPT A -; Z FOR SUCCESS, NZ FOR FAILURE -; - PUSH BC ; SAVE ORIGINAL BC - LD BC,(HEAPTOP) ; BC := CURRENT HEAP TOP - PUSH BC ; SAVE AS START OF REQUESTED BUFFER - ADD HL,BC ; HL := NEW HEAP TOP - LD A,$FF ; ASSUME OVERFLOW FAILURE - JR C,ALLOC1 ; IF MEMTOP OVERFLOW, EXIT WITH A == $FF - PUSH HL ; OTHERWISE, SAVE NEW HEAP TOP VALUE - LD BC,MEMTOP - HEAPEND ; SETUP BC FOR HEAP OVERFLOW TEST - ADD HL,BC ; CHECK FOR HEAP OVERFLOW - POP HL ; RECOVER HL (NEW HEAP TOP VALUE) - JR C,ALLOC1 ; IF HEAP OVERFLOW, EXIT WITH A == $FF - LD (HEAPTOP),HL ; SAVE NEW HEAP TOP - INC A ; SIGNAL SUCCESS -; -ALLOC1: - POP HL ; ALLOCATED BUF START ADDRESS TO HL - POP BC ; RESTORE BC - OR A ; SET ZF TO SIGNAL RESULT +ALLOC: + PUSH DE ; SAVE DE SO WE CAN USE IT FOR WORK REG + LD DE,(HEAPTOP) ; GET CURRENT HEAP TOP + PUSH DE ; AND SAVE FOR RETURN VALUE + ADD HL,DE ; ADD REQUESTED SPACE, HL := NEW HEAP TOP + JR C,ALLOCX ; TEST FOR CPU MEMORY SPACE OVERFLOW + ;LD DE,(HEAPLIM) ; LOAD DE WITH HEAP LIMIT + LD DE,HEAPEND ; LOAD DE WITH HEAP LIMIT + EX DE,HL ; DE=NEW HEAPTOP, HL=HEAPLIM + SBC HL,DE ; HEAPLIM - HEAPTOP + JR C,ALLOCX ; C SET ON OVERFLOW ERROR + ; ALLOCATION SUCCEEDED, COMMIT NEW HEAPTOP + LD (HEAPTOP),DE ; SAVE NEW HEAPTOP +ALLOCX: + POP HL ; RETURN VALUE TO HL + POP DE ; RECOVER DE RET ; ERR_HEAPOVF: