        page    ,132
        title   Spy Hunter

;spyhunt.asm -- loader program for Spy Hunter
; The Ross DOS
; 5-27-86
; From a great southern Engineering / Science college

CR      equ     13                      ;carriage return
LF      equ     10                      ;line feed

cseg    segment para public 'code'
        assume cs:cseg,ss:stack         ;already set by DOS loader

cosmic  proc    far                     ;entry point from dos
        push    ds                      ;set up the stack to
        xor     ax,ax                   ; the double word vector so the
        push    ax                      ; far return will go back to dos

        mov     ax,dseg                 ;set up addressability to
        mov     ds,ax                   ; the data segment
        assume  ds:dseg                 ;tell the assembler what I did

;switch to the color monitor

        push    es                      ;save the extra segment
        mov     ax,0                    ;set the
        mov     es,ax                   ; extra segment to 0
        mov     bx,449h                 ;offset
        mov     byte ptr es:[bx],2      ;80-colomn text, no color, CGA
        pop     es                      ;restore the extra segment

;set video mode

        mov     al,2                    ;mode, text 80x25
        mov     ah,0                    ;service 0 of int 10h
        int     10h                     ;set video mode

;turn off the screen

        mov     dx,3d8h                 ;CGA port to set mode
        mov     al,0001b                ;set bit 3 off to turn video off
        out     dx,al                   ;set new mode

;display text

        mov     dx,offset text1         ;data address
        mov     ah,9h                   ;service 9h of int 21h
        int     21h                     ;display text

;turn on the screen

        mov     dx,3d8h                 ;CGA port to set mode
        mov     al,1001b                ;set bit 3 on to turn video on
        out     dx,al                   ;set new mode

;wait for a key

        mov     ah,8h                   ;service 8h of int 21h
        int     21h                     ;wait for a key

;display text

        mov     dx,offset text2         ;data address
        mov     ah,9h                   ;service 9h of int 21h
        int     21h                     ;display text

;modify memory block allocated by DOS

                                        ;the extra segment is already set
        mov     bx,10h                  ;skip to the end of the PSP
        mov     ah,4ah                  ;service 4ah of int 21h
        int     21h                     ;free memory

;allocate enough memory

        mov     bx,gsize                ;memory game program needs
        mov     ah,48h                  ;service 48h of int 21h
        int     21h                     ;allocate memory
        jnc     sabs                    ;jump if no error
        jmp     err1                    ;jump on error
sabs:   mov     buffer,ax               ;save allocated buffer segment

;open the program file

        mov     dx,offset file          ;data address
        mov     al,0                    ;read only
        mov     ah,3dh                  ;service 3dh
        int     21h                     ; of int 21h
        jnc     rtf                     ;jump if no error
        jmp     err2                    ;jump on error

;read the file into memory

rtf:    mov     bx,ax                   ;bx is the file handle
        mov     ax,ds                   ;save the data segment
        mov     es,ax                   ; using the extra segment

        mov     cx,28                   ;read in 28 tracks (112 KB)
        mov     ax,buffer               ;get the buffer's segment address
        mov     ds,ax                   ;ds now starts at the buffer

rfm:    push    cx                      ;save the count
        mov     dx,0                    ;buffer offset is 0
        mov     cx,1000h                ;read in 4 KB of data
        mov     ah,3fh                  ;service 3fh of int 21h
        int     21h                     ;read in part of the file
        pop     cx                      ;restore the count
        jnc     ids                     ;jump on no error
        jmp     err3                    ;jump on error
ids:    mov     ax,ds                   ;increment the data segment
        add     ax,100h                 ; by 100h
        mov     ds,ax                   ; which is 4 KB (absolute address)
        loop    rfm                     ;loop and finish the count

;restore the data segment

        mov     ax,es                   ;get the data segment from
        mov     ds,ax                   ; the extra sement

;close the file

        mov     ah,3eh                  ;service 3ef of int 21h
        int     21h                     ;close the file
        jnc     wuds                    ;jump on no error
        jmp     err4                    ;jump on error

;wait until the drive stops

wuds:   mov     ax,0                    ;set the
        mov     es,ax                   ; extra segment to beginning of memory
wait:   mov     al,es:[43fh]            ;get the byte which has the drive status
        cmp     al,0                    ;is it zero?
        jne     wait                    ;no, then loop until it is

;reset the int 8h vector

        mov     ax,0                    ;set the
        mov     es,ax                   ; extra segment to beginning of memory
        mov     bx,8h*4                 ;vector offset
        mov     ax,int8h                ;offset
        mov     cx,rom                  ;segment
        mov     es:[bx],ax              ;reset vector offset
        mov     es:[bx+2],cx            ;reset vector segment

;reset the int 9h vector

        mov     ax,0                    ;set the
        mov     es,ax                   ; extra segment to beginning of memory
        mov     bx,9h*4                 ;vector offset
        mov     ax,int9h                ;offset
        mov     cx,rom                  ;segment
        mov     es:[bx],ax              ;reset vector offset
        mov     es:[bx+2],cx            ;reset vector segment

;reset the int 16h vector

        mov     ax,0                    ;set the
        mov     es,ax                   ; extra segment to beginning of memory
        mov     bx,16h*4                ;vector offset
        mov     ax,int16h               ;offset
        mov     cx,rom                  ;segment
        mov     es:[bx],ax              ;reset vector offset
        mov     es:[bx+2],cx            ;reset vector segment

;reset the int 1bh vector

        mov     ax,0                    ;set the
        mov     es,ax                   ; extra segment to beginning of memory
        mov     bx,1bh*4                ;vector offset
        mov     ax,int1ch               ;offset
        mov     cx,rom                  ;segment
        mov     es:[bx],ax              ;reset vector offset
        mov     es:[bx+2],cx            ;reset vector segment

;reset the int 1ch vector

        mov     ax,0                    ;set the
        mov     es,ax                   ; extra segment to beginning of memory
        mov     bx,1ch*4                ;vector offset
        mov     ax,int1ch               ;offset
        mov     cx,rom                  ;segment
        mov     es:[bx],ax              ;reset vector offset
        mov     es:[bx+2],cx            ;reset vector segment

;move the program down to low memory

        push    ds
        mov     si,0                    ;source offset
        mov     di,0ff1h                ;destination offset
        mov     ax,buffer               ;set the data segment
        mov     ds,ax                   ; to the buffer
        mov     ax,100h                 ;set the extra segment
        mov     es,ax                   ; to low memory
        mov     cx,0e000h               ;move 56 KB
    rep movsb                           ;move it...

        mov     si,0                    ;source offset
        mov     di,0ff1h                ;destination offset
        mov     ax,ds                   ;get the data segment
        add     ax,0e00h                ; and inc it
        mov     ds,ax                   ; 56KB up memory
        mov     ax,es                   ;get the extra segment
        add     ax,0e00h                ; and inc it
        mov     es,ax                   ; 56KB up memory
        mov     cx,0e000h               ;move 56 KB
    rep movsb                           ;move it...
        pop     ds

;set the register for the program

        mov     ax,200h                 ;set the
        mov     ds,ax                   ; data segment to 200h
        mov     es,ax                   ; extra segment to 200h
        mov     ax,1e00h                ;set the
        mov     ss,ax                   ; stack segment to 1e00h
        mov     sp,1ff0h                ;set the stack pointer to 200h

;run the program

        sti
        db      0eah,0,10h,0,1

;error # 1 -- memory allocation

err1:   lea     dx,error1               ;data address
        mov     ah,9h                   ;service 9h of int 21h
        int     21h                     ;display text
        jmp     done

;error # 2 -- file open error

err2:   lea     dx,error2               ;data address
        mov     ah,9h                   ;service 9h of int 21h
        int     21h                     ;display text
        jmp     done

;error # 3 -- file read error

err3:   mov     ax,es                   ;restore the
        mov     ds,ax                   ; data segment
        lea     dx,error3               ;data address
        mov     ah,9h                   ;service 9h of int 21h
        int     21h                     ;display text
        jmp     done

;error # 4 -- file close error

err4:   lea     dx,error4               ;data address
        mov     ah,9h                   ;service 9h of int 21h
        int     21h                     ;display text

done:   ret                             ;return to DOS
cosmic  endp
cseg    ends

dseg    segment para public 'data'

text1   db      'Spy Hunter',CR,LF
        db      '(C) Copyright 1984 by Bally Midway',CR,LF,CR,LF
        db      'Broken by The Ross DOS  5-27-86',CR,LF,CR,LF
        db      'Uses file SPYHUNT.PRG',CR,LF
        db      'Requires DOS 2.XX or 3.XX',CR,LF
        db      'Requires 120k of free memory',CR,LF
        db      'Requires a IBM compatible color graphics adapter',CR,LF,CR,LF
        db      'This program does the following:',CR,LF
        db      ' gets loaded into high memory',CR,LF
        db      ' allocates 120 KB of RAM (enough to load SPYHUNT.PRG into)',CR,LF
        db      ' loads SPYHUNT.PRG into the allocated block',CR,LF
        db      ' sets interupts 8h,9h,10,16h,1bh,1ch to their initial ROM values',CR,LF
        db      ' moves the program to 0:100h (low memory)',CR,LF
        db      ' sets the registers to their required initial values',CR,LF
        db      ' executes the program by doing a far jump to 100:1000h',CR,LF,CR,LF
        db      'Since this game provides no method to return to DOS (and infact destroys DOS',CR,LF
        db      'when moved to low memory), a reboot or power off is required to quit.',CR,LF,CR,LF
        db      'To stop now, press Crtl-Break.',CR,LF,CR,LF
        db      '* Press any key to continue *','$'
text2   db      CR,LF,CR,LF
        db      'Loading...$'
file    db      'SPYHUNT.PRG',0
error1  db      CR,LF,'ERROR: Cannot allocate enough memory',CR,LF,'$'
error2  db      CR,LF,'ERROR: Cannot open file SPYHUNT.PRG',CR,LF,'$'
error3  db      CR,LF,'ERROR: Cannot read file SPYHUNT.PRG',CR,LF,'$'
error4  db      CR,LF,'ERROR: Cannot close file SPYHUNT.PRG',CR,LF,'$'
buffer  dw      ?                       ;holds the buffer segment
int8h   dw      0fea5h                  ;offset of int 1ch
int9h   dw      0e987h                  ;offset of int 1ch
int16h  dw      0e82eh                  ;offset of int 16h
int1bh  dw      0ff53h                  ;offset of int 1ch
int1ch  dw      0ff53h                  ;offset of int 1ch
rom     dw      0f000h                  ;segment ROM starts at
gsize   dw      1d4ch+100h              ;number of paragraphs game program needs
gjump   dd      ?
dseg    ends

stack   segment para stack 'stack'
        db      64 dup("stack   ")      ;256 word stack area
stack   ends
        end     cosmic                  ;enter at entpt from DOS
