jmp START ;===========DATA=========== u3cfg db "U3.CFG",0 midpak db "MIDPAK.COM",0 midpak_start db 2," 8",0dh,0 midpak_stop db 2," u",0dh,0 u3ega db "U3EGA.COM",0 u3vga db "U3VGA.COM",0 u3_params db 3,20h,0ffh,0ffh,0dh,0 file_error db "Error reading U3.CFG",0ah,0dh,"$" midpak_error db "Error loading MIDPAK MIDI Driver",0ah,0dh,"$" launch_error db "Error launching Ultima III",0ah,0dh,"$" i_data db 0,0,0,0,0,0,0,0,0,0,0,0 i_flag db 0 cfgdata db 0,0,0,0 prm_block db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 fcb db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;===========CODE=========== START: ; resize memory block to 0x500 bytes mov ah,4ah mov bx,0500h int 21h ; resize ; move stack to end of memory block mov ax,cs mov ss,ax mov sp,04fe ; copy cs into ds push cs pop ds ; open u3.cfg file mov ah,3dh mov al,00h mov dx,offset u3cfg int 21h ; OPEN jc LOAD_FAILURE ; go here on error ; save file handle mov bx,ax ; read u3.cfg file mov ah,3fh mov cx,04h mov dx,offset cfgdata int 21h ; READ jc LOAD_FAILURE ; go here on error ; close file mov ah,3eh int 21h ; CLOSE jnc LOAD_SUCCESS ; go here on success LOAD_FAILURE: ; print error message mov dx,offset file_error call ERROR LOAD_SUCCESS: ; set new interrupt vectors call SET_VECTORS ; set i_flag to 01 (indicates we have set new interrupts) mov byte ptr [offset i_flag],01h ; save offset to parameter block in bx mov bp,offset prm_block ; save offset to cfgdata in bx mov bx,offset cfgdata push bx ; if 1st byte != 01, jump to autosave cmp byte ptr [bx],01h jnz GRAPHIC_MODE ; fill parameter block mov bx,bp ; set parameter block mov word ptr [bx],0000h mov [bx+02h],offset midpak_start mov [bx+04h],ds mov word ptr [bx+06h],offset fcb mov [bx+08h],ds mov word ptr [bx+0ah],offset fcb mov [bx+0ch],ds ; run midpak program mov ax,4b00h xor cx,cx ; clear cx mov dx,offset midpak int 21h ; execute jnz GRAPHIC_MODE ; jump here on success ; print midpak error & exit mov dx,offset midpak_error call ERROR GRAPHIC_MODE: pop bx ; if 4th byte == 01, jump to vga cmp byte ptr [bx+03h],01h jz VGA ; set dx = offset of "u3ega.com" mov dx,offset u3ega jmp LAUNCH_PROGRAM VGA: ; set dx = offset of "u3vga.com" mov dx,offset u3vga LAUNCH_PROGRAM: push bx ; fill parameter block mov bx,bp ; set parameter block mov word ptr [bx],0000h mov word ptr [bx+02h],offset u3_params mov [bx+04h],cs mov word ptr [bx+06h],offset fcb mov [bx+08h],cs mov word ptr [bx+0ah],offset fcb mov [bx+0ch],cs ; launch Ultima 3 mov ax,4b00h xor cx,cx ; clear cx int 21h ; execute jnz STOP_MIDPAK ; jump here on success ; print launch error & exit mov dx,offset launch_error call U3_ERROR STOP_MIDPAK: pop bx ; if 1st byte != 01, jump to exit cmp byte ptr [bx],01h jnz EXIT ; fill parameter block mov bx,bp ; set parameter block mov word ptr [bx],0000h mov [bx+02h],offset midpak_stop mov [bx+04h],ds mov word ptr [bx+06h],offset fcb mov [bx+08h],ds mov word ptr [bx+0ah],offset fcb mov [bx+0ch],ds ; run midpak program mov ax,4b00h xor cx,cx ; clear cx mov dx,offset midpak int 21h ; execute jnz EXIT ; jump here on success ; print midpak error & exit mov dx,offset midpak_error call ERROR EXIT: ; set errorlevel for exit mov al,00h ; i_flag will be set to 01 if interrupt vectors have been set cmp byte ptr [offset i_flag],01h jnz TERMINATE ; reset the interrupt vectors call RESET_VECTORS TERMINATE: ; exit with errorlevel al mov ah,4ch int 21h ; exit ;===========FCNS=========== WRAPPER: ; wrapper fcn (does nothing) iret ULTIMA3_INT: push bx ; set bx as offset to config data mov bx,offset cfgdata ; fcn 00 = autosave check cmp ah,00 jz AUTOSAVE ; fcn 01 = frame limiter check cmp ah,01 jz FRAMELIMITER jmp RETURN AUTOSAVE: ; returns al=01 if autosave enabled cs: mov al,[bx+01h] jmp RETURN FRAMELIMITER: ; returns al=01 if frame limiter enabled cs: mov al,[bx+02h] RETURN: pop bx iret SET_VECTORS: pushf push ax push cx push si push di push ds push es cli ; clear interrupt flag cld ; clear direction flag push ds pop es ; copy ds into es xor ax,ax ; clear ax mov ds,ax ; clear ds ; set source/dest index mov si,0194h ; offset of int vect 65 mov di,offset i_data ; offset of backup int table ; move 4 words mov cx,0004h rep movsw ; move a word from ds:si to es:di ; set default values for new vectors mov word ptr [0194],ULTIMA3_INT mov [0196],cs mov word ptr [0198],WRAPPER mov [019a],cs sti ; set interrupt flag ; return pop es pop ds ; restore ds pop di pop si pop cx pop ax popf ret RESET_VECTORS: pushf push ax push cx push si push di push es cli ; clear interrupt flag ; set es to interrupt vector table xor ax,ax ; clear ax mov es,ax ; clear es ; set source/dest index mov si,offset i_data ; offset of backup int table mov di,0194h ; offset of int vect 64 ; move 4 words mov cx,0004h rep movsw ; move a word from ds:si to es:di sti ; set interrupt flag ; return pop es pop di pop si pop cx pop ax popf ret ERROR: ; print error message mov ah,09h int 21h ; print string ; exit with errorlevel 1 mov al,01h jmp EXIT U3_ERROR: ; print error message mov ah,09h int 21h ; print string ; return to unload the midpak driver first before quitting ret