Zaxxon speed patch by dOnut in 1997

Just start the game with "Zaxxonp.com" and it will run at playable speed.
For those interested in the details, take a look at the listing.

---------------------------------------------------------------------------

Title patcher.asm
; by dOnut hOle

.286
.model tiny

.code
        org 100h
begin:  jmp init


; ****** MACROS ********
CR         equ     0Dh
LF         equ     0Ah
EOLN       equ     '$'
SIGNATURE  equ     0ffffh
SIGNATURE2 equ     0fffeh
INTERRUPT  equ     10h

;********* Resident Data **********
START             equ $
oldint_ofs        dw  0000h
oldint_seg        dw  0000h
int_no            db  INTERRUPT
data_start        db  01h                      ;Number of S&R-Loops
                  db  00h                      ;Flag: already Replaced ?
                  dw  0000                     ;offset to data_start2
                  db  02h                      ;search_seg1  (02=CS)
                  dw  04bah                    ;search_ofs1
                  dw  0000h                    ;search_seg_add1
                  db  09h                      ;search_bytes1
                  db  0b9h,0b0h,000h           ;search_data1
                  db  0beh,010h,009h
                  db  0bfh,00ah,000h
                  db  01h                      ;replace_loops1

                  db  02h                      ;replace_seg1 (02=CS)
                  dw  04bah                    ;replace_ofs1
                  dw  0000h                    ;replace_seg_add1
                  db  09h                      ;replace_bytes1
                  db  050h,0b8h,0feh,0ffh      ;replace_data1
                  db  0cdh,010h,058h,090h,090h

save_sp           dw  0
                  db  100 DUP(0)
STACKFRAME        equ $

;***** a procedure of the interrupt-routine ******
set_address  proc near
          lodsb                     ; load segment from ds:si
          cmp al,00                 ; 00h=DS
          jz _DS_
          cmp al,01                 ; 01h=ES
          jz _ES_
          cmp al,02                 ; 02h=CS
          jz _CS_
          mov dx,ss                 ; >02h = SS
          jmp FOUR
_DS_:     mov dx,ss:[-02+bp]
          jmp FOUR
_ES_:      mov dx,ss:[-04+bp]
          jmp FOUR
_CS_:     mov dx,ss:[14h+bp]
FOUR:     lodsw                    ; load segment_ofs from ds:si
          mov di,ax                ; and store it into di
          lodsw                    ; load segment_add from ds:si 
          add ax,dx                ; add it to segment in dx
          mov es,ax                ; es:di = (seg+seg_add):seg_ofs
          ret
endp set_address

;******* this is the interrupt-routine *********
new_int   proc far
          pushf
          pusha

          cmp ax,SIGNATURE         ; asking for signature ???
          jne normal

givesig:  popa
          popf
          mov bx,SIGNATURE         ; signature FFFF in bx given back
          iret

normal:   mov bp,sp
          push ds
          push es
          cld
          push cs
          pop ds

          cmp ax,SIGNATURE2        ; called from replacement
          jne normal2

          mov cx,04
waitscan: mov dx,03dah
wait1:    in al,dx
          test al,08h
          jz wait1
wait2:    in al,dx
          test al,08h
          jnz wait2
          loop waitscan

          pop es
          pop ds
          popa
          popf
          mov cx,0b0h
          mov si,0910h
          mov di,0ah
          iret

normal2:  mov si,offset data_start
          lodsb                     ; load s&R-loops from ds:si
          cbw
          xchg ax,cx                ; set outer loop-counter
search:       push cx
              mov bx,si
              lodsb                 ; load replaced-flag from ds:si
              or al,al              ; flag = 0 ?
              lodsw                 ; load offset to next data from ds:si
              push ax
              jnz endloop           ; if flag <> 0 then jump over this loop
              call set_address      ; set address to search
              lodsb                 ; load search_bytes from ds:si
              cbw
              xchg ax,cx            ; and store it into inner loop-counter
              repz cmpsb            ; compare with search_data
              jnz endloop           ; not equal (string not found)
              lodsb                 ; load replace-loops from ds:si
              cbw
              xchg ax,cx            ; and store it into middle loop counter
Loop_me:          push cx
                  call set_address  ; set address to replace
                  lodsb             ; load replace_bytes from ds:si
                  cbw
                  xchg ax,cx        ; and store it into inner loop counter
                  repz movsb        ; replace bytes
                  ;mov byte ptr [bx],01  ; set flag to 'replaced'
                  pop cx
              loop loop_me  
endloop:      pop si                ; offset to next data
              pop cx
          loop search
          pop es
          pop ds
jumpold:  popa
          popf
          jmp dword ptr cs:[oldint_ofs]
new_int endp


;********* not resident data ************
FINISH      equ     $
MESS        db      'Zaxxon speed patch by dOnut hOle 1997',CR,LF,EOLN
PROG        db      'zaxxon.com',0
FNAME       db      60 dup(0)
PARAM       dw      0
            db      80h,0
PARAM1      dw      5 dup(0)
ERR1        db      'ERROR: Not enough memory.  '
ERR2        db      'Starting as TSR.',CR,LF,EOLN
REMOVE      db      'Removing TSR. ',CR,LF,EOLN

;******* the main program is starting here ************
init:
            cli
            mov [save_sp],sp
            mov sp,offset STACKFRAME    ; define stack
            sti

            mov ax,SIGNATURE
            xor bx,bx
            int INTERRUPT               ; check if already installed
            cmp bx,SIGNATURE
            jne install                 ; interrupt not yet hooked

            ;******* Uninstall TSR ********
            mov al,[int_no]
            mov ah,35h
            int 21h                     ; get segment of interrupt (es)
            push ds
            lds dx,dword ptr es:[oldint_ofs]
            mov ah,25h
            int 21h                     ; restore interrupt-vector
            pop ds

            push es
            mov es,es:[02ch]            ; get segment from PSP
            mov ah,49h
            int 21h                     ; free Memory
            pop es
            mov ah,49h
            int 21h                     ; free Memory

            push cs
            pop ds
            mov ah,9h
            mov dx,offset REMOVE
            int 21h                     ; print message
            jmp exit

install:    ;********* install interrupt **********
            mov ah,35h
            mov al,cs:[int_no]
            int 21h                     ; read interrupt vector
            mov cs:[oldint_ofs],bx      ; store offset 
            mov cs:[oldint_seg],es      ; store segment 
            mov ah,25h  
            mov dx,offset new_int
            int 21h                     ; set new interrupt vector

            mov ah,9h
            mov dx,offset MESS
            int 21h                     ; print message

            push cs
            pop es
            mov bx,offset ENDCODE       ;Get end of memory
            add bx,15
            mov cl,4                
            shr bx,cl                   ;div 16
            mov ah,4Ah            
            int 21h                     ;Reallocate memory
            jnc GetName                 ;If no error, continue

            mov ah,9h
            mov dx,offset ERR1
            int 21h                     ;Write error-string
            jmp tsr

GetName:    ;****** get the path from the environment ****
            mov es,cs:[02ch]            ;Segment of Environment
            xor di,di
            xor ax,ax
SearchEnv:    cmp al,es:[di]            ;Search two zeroes
              je SearchEnd
              mov cx,0ffffh
              repnz scasb
            jmp SearchEnv
SearchEnd:  add di,03                   ;es:di points at path+name
            push di
            mov cx,100h                 ;Search End of string 
            repnz scasb
            not cl                      ;Cl contains length
            std
            mov al,'\'
            repnz scasb                 ;search last '\'
            add cl,3
            cld
            ;******* assemble full name from path and given name ********
            pop di
            mov si,di
            mov di,offset FNAME
            push es
            pop ds
            push cs
            pop es
            rep movsb                   ; path is copied to NAME
            push cs
            pop ds
            mov si,offset PROG
COPY_PROG:  cmp byte ptr [si],00
            je COPY_END
            MOVSB                       ; PROG is copied to NAME
            jmp COPY_PROG               
COPY_END:   MOVSB
            ;****** load and execute the child program **********
            mov ax,cs
            mov PARAM,ax
            mov PARAM1,ax
            mov bx,offset PARAM
            mov dx,offset FNAME
            mov ah,4Bh
            mov al,00h
            int 21h                     ;Load and execute child program
            jnc uninstall               ;If no error, continue

            mov ah,9h                   
            mov dx,offset ERR2
            int 21h                     ;Write error- string
            jmp tsr

uninstall:  ;********** restore old interrupt ***********
            mov ah,25h                  ;Restore interrupt vector
            mov al,[int_no]
            mov dx,[oldint_ofs]
            mov bx,[oldint_seg]
            mov ds,bx
            int 21h

EXIT:       push cs
            pop ds
            cli
            mov sp,[save_sp]
            sti
            mov ax,4C00h                     ;Exit with error code 0
            int 21h

TSR:        ;********** go resident ***********
            mov dx,offset FINISH             ;Offset of booster
            add dx,15
            mov cl,4
            shr dx,cl
            mov ax,3100h
            int 21h                          ;Exit with ejection of booster
                                         
ENDCODE     equ $
end      begin
