; PROGRAM:  UTILPAT -- Utility Patch
; AUTHOR:   Jay Sage
; DATE:     November 30, 1988

; This patch *may* allow BIOS-specific utilities to
; work under NZ-COM.

; The address below must be set to the first free byte
; after the utility's code.

patchaddr       equ     0000h

; The address below must be set to the address at which
; execution will continue after the patch code is
; executed.

startaddr       equ     0000h

; The following macro should be filled in with any opcodes
; that were at address 100H and following and had to be
; replaced by the jump to the patch code.  If the utility
; began with a JP STARTADDR instruction, then leave this
; macro blank

replaced        macro
                               ; put instructions here
               endm

; The macro below is used to enter the list of addresses
; at which LD HL,(0001) instructions appear that must be
; patched.  Replace the symbol ADDR1 by the first such
; address and insert additional similar lines for any other
; addresses to be patched.
;
addrlist        macro
       dw      addr1           ; Repeat for each address
               endm

ldhl    equ     21h             ; Load-hl-direct opcode
offset  equ     5ah - 3         ; Offset from BIOS warm boot entry
                               ; ..to the NZ-COM signature

; The following code will be patched in at address 100h to
; vector control to the patch code.

       org     100h

       jp      patchaddr

; The actual patch code begins here.

       org     patchaddr

; If NZ-COM is running, HL will now contain the ENV address.
; We will need this later, so we save it.

       ld      (envaddr),hl

; Now we must find out if NZ-COM is running.  This is done
; by looking for its signature "NZ-COM" at a specific offset
; from the virtual BIOS warm boot entry point.  If this
; signature is not found, the patch can be skipped.

       ld      hl,(0001)       ; Get possible virtual
                               ; ..BIOS address
       ld      de,offset       ; Offset to signature
       add     hl,de
       ld      de,signature    ; Point to what the
                               ; ..signature should be
       ld      b,sigsize       ; Length of signature
sigloop:
       ld      a,(de)
       cp      (hl)            ; Check character
       inc     de              ; Advance pointers
       inc     hl
       jr      nz,exitpatch    ; Jump if not NZ-COM system
       djnz    sigloop         ; Loop through signature

; We get here if NZ-COM is running.  Now we must make the
; necessary patches to the utility.  First we must determine
; the address of the warm boot entry to the real BIOS.
; NZ-COM keeps the page address at offset 2 into the ENV.

envaddr equ     $ + 1
       ld      hl,$-$          ; Filled in by code above
       inc     hl              ; Advance to CBIOS page
       inc     hl
       ld      a,(hl)          ; Get page of CBIOS
       ld      (cbiospage),a   ; Put it into code below

; Now we patch in the changes to the utility code.

       ld      de,table        ; Point to address table
       ld      b,tablesize     ; Addresses in table
patchloop:
       ld      a,(de)          ; Low byte of address
       inc     de              ; Advance pointer
       ld      l,a             ; Put in low byte of HL
       ld      a,(de)          ; High byte of address
       inc     de              ; Advance pointer
       ld      h,a             ; Put in high byte of HL
       ld      (hl),ldhl       ; Patch in direct-load opcode
       inc     hl
       ld      (hl),03H        ; Low warm boot address
       inc     hl
cbiospage equ   $ + 1
       ld      (hl),0          ; Filled in by code above
       djnz    patchloop       ; Loop through address list

exitpatch:

; Here we have to exit from the patch and resume execution
; of the original utility.  First we execute instructions, if
; any, replaced by the patch intercept code.

       replaced                ; Macro

; Then we jump to the utility code.

       jp      startaddr

; The following is what the NZ-COM signature should look like.

signature:
       db      'NZ-COM'
sigsize equ     $ - signature

; We put the table of addresses to patch here.

table:
       addrlist                ; Macro with address list
tablesize       equ     ( $ - table ) / 2

       end