þ a‹R þ w Qþ mU9     þ hý	 o    þ nSystem-wide        NAME  Validate

CODE    SEGMENT  PUBLIC 'CODE'
ASSUME  CS:CODE,DS:CODE,ES:CODE,SS:CODE

PUBLIC    ValidateProgram

;==============================================================================
;
;   ValidateProgram: Check for ROM to make sure this is not a copy
;
;        This procedure banks in each of the 8 rom banks looking for valid
;   ROM headers. If a valid header is found the program compares the Optional
;   ROM Name with the string listed below. The procedure returns if the two
;   match. If they don't match the procedure goes to the next ROM slot. If
;   all ROM slots do not match the "key" string then the procedure prints out
;   an "illegal copy" message and aborts the program.
;
;   NOTE - the Optional ROM Name is placed in the ROM using the ROM Build 
;   program "ROM" options menu. Both this string and the KeyString listed
;   below should match exactly, including the case (upper or lower) of the
;   characters used. To change the KeyString just replace the characters in
;   the quotes below to the KeyString to be used. Up to 50 characters are 
;   allowed. Then use the new keystring for the Optional ROM Name when creating
;   the PROM with ROMBuild.
;
;==============================================================================

KeyString    DB     'Program X',0


InvalidMsg   DB     13,10,'Unauthorized program duplicate detected.',13,10
             DB           'Program aborted.',13,10,'$'

ValidateProgram  PROC  FAR

    PUSH    AX                       ; save the registers
    PUSH    BX
    PUSH    CX
    PUSH    DX
    PUSH    ES
    PUSH    SI

    CLI                              ; turn off interrupts - this is very 
                                     ; important and must not be omited

    MOV     DX,403H                  ; set for NON- 32K EPROM Mode
    MOV     AL,0
    OUT     DX,AL

    MOV     DX,405H                  ; set to enable ROMs
    MOV     AL,1
    OUT     DX,AL

    MOV     CX,8                     ; set loop counter for 8 slots

SearchLoop:
    PUSH    CX                       ; save the loop counter

    MOV     AL,CL                    ; use loop counter to select bank
    DEC     CL                       ; adjust so zero relative

    MOV     DX,440H                  ; get port for first 32K of ROM area
    OUT     DX,AL                    ; bank slot into this area

    INC     DX                       ; get port for second 32K of ROM area
    OUT     DX,AL                    ; bank slot into this area

    INC     DX                       ; get port for third 32K of ROM area
    OUT     DX,AL                    ; bank slot into this area

    INC     DX                       ; get port for last 32K of ROM area
    OUT     DX,AL                    ; bank slot into this area

    MOV     AX,9FF0H                 ; get ROM header segment value
    MOV     ES,AX                    ; set up extra segment
    MOV     BX,0                     ; point to first byte

    CMP     WORD PTR ES:[BX],0BB66H  ; is there a valid rom header ?
    JNE     NextSlot                 ; no - then jump

    ADD     BX,8EH                   ; point to start of Optional ROM Name
    MOV     SI,OFFSET KeyString      ; point to key string

CheckChar:
    MOV     AL,CS:[SI]               ; get a key string character
    CMP     AL,0                     ; is it the end of the string ?
    JE      KeyStringFound           ; yes - key must match then - so jump

    CMP     ES:[BX],AL               ; does it match optional rom name char ?
    JNE     NextSlot                 ; no - doesn't match then - so jump
    INC     BX                       ; point to next rom name char
    INC     SI                       ; point to next key string char
    JMP     CheckChar                ; go check next character
    
NextSlot:
    POP     CX                       ; restore the loop counter
    LOOP    SearchLoop               ; go check next slot

EndProgram:
                                     ; no match was found at this point

    MOV     DX,405H                  ; set to disable roms
    MOV     AL,0
    OUT     DX,AL                    ; disable roms

    STI                              ; restore the interrupts

    PUSH    DS                       ; save the data segment

    PUSH    CS                       ; set data segment to invalid message
    POP     DS

    MOV     DX,OFFSET IllegalMsg     ; get offset of the message
    MOV     AH,9                     ; set for MS-DOS string output
    INT     21H                      ; go output the string

    POP     DS                       ; restore the data segment
    
    MOV     AH,04CH                  ; set to end the program
    MOV     AL,0                     ; set return code
    INT     21H                      ; abort program


KeyStringFound:
                                     ; at this point the string has been found

    POP     CX

    MOV     DX,405H                  ; set to disable roms
    MOV     AL,0
    OUT     DX,AL                    ; disable the ROMs

    STI                              ; reenable interrupts

    POP     SI                       ; restore the registers
    POP     ES
    POP     DX
    POP     CX
    POP     BX
    POP     AX
    RET                              ; return to calling program

ValidateProgram  ENDP

CODE    ENDS
        END   
