;install.asm
;jeff leyda
;9/8/97
;
;installation program for floppy disk boot emulator  (aka flopper)
;compiled with tasm/tlink
;portions of the boot-through bootsector code (c) 1992, Urmas Rahu
;
;
;Modified 10/9/99
; Changed install to copy the original bootsector to the outer
; portion of the diskette, so that after the vector table is saved, the
; original bootsector is restored so the disk doesn't have to be reformatted.



	cseg segment
	assume cs: cseg,ds:cseg,es:cseg,ss:cseg
	


	org 100h


main:   jmp go
;----------------------------------------------------------------------------
;variables and data
;----------------------------------------------------------------------------
SECSIZE         equ     512                     ; standard sector size
MAGIC           equ     42                      ; the answer to life, universe      
						; and everything

vectortbl       db      "vectable.dat",0   ;file to store vector table in

;****************************************************************************

bootsector:     jmp     short bootcode          ; boot sector starts here
		nop

bootdata        db      1bH dup (?)             ; near jump to boot code
oldsectorcx     dw      ?                       ; cx,dx values of where the
oldsectordx     dw      ?                       ; original sector is stored

hdload:         mov     ax, 0201H               ; this part of code will be
		mov     bx, 07c0H               ;  copied to 07c0:0200, just
		mov     es, bx                  ;  above the boot sector image,
		xor     bx, bx                  ;  so that the hard disk boot
		mov     cx, 0001H               ;  sector will fit right below
		mov     dx, 0080H               ;  it.
		int     13H                     ; read hard drive's boot record

		db      0e9H                    ; jump to hard disk boot code
		dw      -SECSIZE - (hdload_end-hdload)  ; (at 07c0:0000)
hdload_end      label   byte

bootcode:                                       ; start of my boot code
                ; grab old boot sector and replace this one.
                mov     ax, 0201h
                mov     si, 7c1eh               ; we know we booted to 0:7c00
                                                ;
                mov     bx, es:[si]
                mov     cx, bx
                add     si, 2
                mov     bx, es:[si]
                mov     dx, bx
                mov     bx, 07c0h
                int     13h                     ; read last sector

                push    cx
                push    dx

                mov     ax, 0301h               ; write it as 1st sector
                mov     cx, 1
                mov     dx, 0
                int     13h

                pop     dx
                pop     cx

		mov     bx,40h                  ; set a flag at 40:f0h
		mov     es,bx                   ; so install knows that
		mov     bx,0f0h                 ; the vector table has been
		mov     byte ptr es:[bx],MAGIC  ; saved.  

		mov     bx,0                    ; write vector table info
                mov     es,bx                   ; to last 2 sectors on disk.
		mov     ax,0302h                ;
                sub     cx,1                    ;
              ;  mov     dx,0                   ;
		int     13h                     ;

		mov     bx, 07c0H
		mov     ds, bx                  ; set segment regs to 07c0
		mov     es, bx
		
		mov     bx, message - bootsector
		mov     ah, 0eH

dispmsg:        mov     al, [bx]                ; show message of bypassing
		cmp     al, 0
		jz      copycode
		int     10H                     ; write teletype
		inc     bx
                jmp     dispmsg   

copycode:
		xor     ax,ax                   ; wait for a keypress
		int     16h


		mov     si, hdload - bootsector ; copy the hard disk boot sector
		mov     di, SECSIZE             ; loader to 07c0:0200
		mov     cx, bootcode - hdload
		cld
	rep     movsb
		
		db      0e9H                    ; jump to hard disk boot sector
		dw      SECSIZE - (copycode_end - bootsector)   ; loader
copycode_end    label   byte                    ; (at 07c0:0200)



message         db      13,"Interrupt vector table saved.",10,13
		db      "The computer will now continue booting to the C: drive."
		db      10,13,10,13,"Please re-run the install.com program after booting."
		db      10,13,10,13,"Press any key to continue...",10,13,0
filler          db      SECSIZE - (filler-bootsector) dup (' ')



old_bootdata:   db      1eH dup (?)             ; old boot sector will be 
old_bootcode:   db      (512-1eH) dup (?)       ;  read here

;****************************************************************************







welcomemsg      db      "Welcome to Flopper, the diskette boot emulator. "
                db      "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ "
		db      "                                                "
		db      "Once installed, this program will allow you to  "
		db      "play many games from the early 1980's that were " 
		db      "released as a self booting 360k floppy disks.   "
		db      "                                                "
		db      "This program emulates a floppy diskette bootup  " 
		db      "under DOS from a disk image file on your drive. "
		db      "                                                "
		db      "                                                "
		db      "Press ENTER to continue installation            "
		db      "or ESC to quit                                  "
		db      -1

step1           db      "Requirements:                                   "
		db      "ÄÄÄÄÄÄÄÄÄÄÄÄÄ                                   "
		db      "                                                "
                db      "Flopper requires the following hardware:        "
		db      " þ 386 or higher CPU                            "
		db      " þ at least 2mb of memory                       "
		db      " þ 1 floppy drive (hard drive preferred)        "
		db      " þ DOS 2.1 or higher                            "   
                db      " þ diskette images                              "
		db      "                                                "
		db      "                                                "
		db      "Press ENTER to continue installation            "
		db      "or ESC to quit                                  "
		db      -1


step2           db      "Requirements, page 2:                           "
                db      "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ                           "
		db      "This program installation will require a blank, "
		db      "formatted floppy diskette for A: drive of this  "
                db      "computer. Flopper needs some information from   "
                db      "your computer which is only available during    "
                db      "boot BEFORE the operating system loads, so we   "
                db      "need to make a special boot diskette.           "
                db      "                                                "
                db      "You will not need this disk after installation. "
		db      "                                                "
		db      "Press ENTER to continue installation            "
		db      "or ESC to quit                                  "
		db      -1

step3           db      "Insert floppy diskette now                      "
		db      "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ                      "
		db      "                                                "
		db      "This program is about to create a specialized   "
		db      "bootup disk, which will gather some information "
		db      "about the computer at its booting stage.        "
		db      "                                                "
		db      "Once this disk has been created, the computer   "
		db      "will then reboot to the bootup disk.            "
		db      "                                                "
		db      "                                                "
		db      "Insert a formatted disk into drive A: now and   "
		db      "press ENTER.  Or press ESC to quit.             "
		db      -1

step4           db      "Time to reboot...                               "
		db      "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ                               "
		db      "                                                "
		db      "The computer will now reboot.                   "
		db      "                                                "
		db      "If you are running this program in a DOS shell  "
		db      "under windows, you should press ESC now, exit   "
		db      "windows, then reboot to this floppy diskette.   "
		db      "                                                "
		db      "Follow the directions on the screen after you   "
		db      "have booted to this diskette.                   "
		db      "                                                "
		db      "Press ENTER to continue reboot or ESC to quit.  "
		db      -1


endingmsg       db      "Welcome back.                                   "
                db      "ÄÄÄÄÄÄÄÄÄÄÄÄÄ                                   "
		db      "                                                "
		db      "Now that the vital bootup information has been  "
		db      "gathered from your computer, the final step in  "
		db      "this installation process is to save the data   "
		db      "to a file.                                      "
		db      "                                                "
		db      "Make sure the floppy disk is still in the drive."
		db      "                                                "
		db      "                                                "
		db      "                                                "
                db      "Press ENTER to continue or ESC to quit.         "
		db      -1

finished        db      "All Done!                                       "
                db      "ÄÄÄÄÄÄÄÄÄ                                       "
		db      "                                                "
                db      "Flopper is ready for use.  You no longer need   "
                db      "the floppy diskette, please remove it from the  "
                db      "drive.                                          "
                db      "                                                "
		db      "                                                "
		db      "                                                "
		db      "To play a game, simply type FLOPPER  <filename> "
		db      "where filename is a valid diskette image.       "
		db      "                                                "
		db      "Press any key to quit.                          "
		db      -1


floperror       db      "Floppy disk read/write error!                   "
		db      "ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ                   "
		db      "                                                "
		db      "The floppy disk in drive A: is either not       "
		db      "inserted into the drive or is not formatted.    "
		db      "                                                "
		db      "Please check the drive or replace the diskeete. "
		db      "                                                "
		db      "                                                "
		db      "                                                "
		db      "                                                "
                db      "Press ENTER to continue or ESC to quit.         "
		db      "                                                "
		db      -1






draw_line proc
;DX=row,col
;cx=count
;bl=color
;al=character
    dec dh
    push cx
    call pos_cursor
    mov ah,9
    mov bh,0
    int 10h
    pop cx

    dec si
    cmp si,0
    jnz draw_line

    ret
draw_line endp

pos_cursor proc
;positions cursor at DX (row,col)
    mov ah,2
    mov bh,0
    int 10h
    ret
pos_cursor endp



dotext proc
	text_len = 48

	mov dh,12
        mov bx,17h        ; default to blue unless carry flag is set
        jnc disp_text
        mov bx,47h        ; red text

disp_text:
	mov ax,1300h
	mov cx,text_len
	mov dl,16
	int 10h

	add bp,text_len
	inc dh
	cmp byte ptr es:[bp],-1
	jnz disp_text

	ret
dotext endp

anykey proc
;wait for a keypress.  If it's ENTER, keep going, ESC, set carry
	xor ax,ax
	int 16h
	clc

	cmp al,13
	jz doit
	cmp al,27
	jnz anykey
	stc
doit:
	ret
anykey endp



drawscreen proc


	mov ah,02h         ;use bios video to
	mov bh,00h         ;set cursor position to top left
	mov dx,00h         ;of screen
	int 10h            ;bios function 02h
	;
	mov ah,09h         ;now using function 09h
	mov cx,04000       ;print a space char 04000h times
	mov al,177         ;char to clear with
	mov bl,13h         ;attribute of character
	int 10h            ;clear it!
	;
	mov ah,02h         ;now let's put the
	mov bh,00h         ;cursor back up in
	mov dx,00h         ;the upper left corner
	int 10h            ;bios video function




      ;draw the box + shadow




    mov dh,25                ;draw box
    mov dl,15                ;move cursor to row,17
    mov al,219
    mov cx,50
    mov bl,1
    mov si,14                ;depth of box
    call draw_line

    mov dh,25
    mov dl,65                ;draw vertical shadow
    mov al,176
    mov cx,1
    mov si,13
    mov bl,8
    call draw_line


    mov dh,26
    mov dl,16
    mov al,176               ;draw under shadow
    mov cx,50
    mov si,1
    mov bl,8
    call draw_line



	;display text in window

    ret

drawscreen endp

check4driveready        proc
; read disk up to 3 times waiting for drive to read/write OK.


        push    ax
        push    bx
        push    cx
        push    dx
        push    bp
        push    si
        push    di


        mov bp,3
readflop:
        dec     bp
        jz      floppyerror
        mov     ax,0
        mov     dl,0
        int     13h

        mov     ax, 0201h               ; do a fake read of drive A:
        lea     bx, endflag
        mov     cx, 1
        mov     dx, 0
        int     13h
        jc      readflop


        mov     ax, 0301h
        int     13h                     ; write data back, check for WP
        jc      readflop

        jmp     driveisready


floppyerror:


        ; save the screen so we can "pop up" error window

        lea     di, endflag  ;es is already pointing there
        xor     si, si
        push    ds
        mov     ax, 0b800h
        mov     ds, ax
        mov     cx, 80*2*50
        rep     movsb
        pop     ds




        mov     dh, 25                  ; draw box
        mov     dl, 15                  ; move cursor to row,17
        mov     al, 219
        mov     cx, 50
        mov     bl, 4                   ; red
        mov     si, 14                  ; depth of box
        call    draw_line

        lea     bp,floperror
        stc                             ; carry=red text 
        call    dotext
        call    anykey
        jc      bail

        lea     si, endflag             ; restore screen
        xor     di, di
        push    es
        mov     ax, 0b800h
        mov     es, ax
        mov     cx, 80*2*50
        rep     movsb
        pop     es

driveisready:

        pop     di
        pop     si
        pop     bp
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        ret


bail:
        mov     ax, 3
        int     10h

        mov     ax, 4c01h
        int     21h


check4driveready endp






findlastsector proc
;exits with CX, DX pointing to last sector on current disk


        ; read existing boot sector

	lea bx,endflag
	mov ax,0201h
	mov cx,1
	mov dx,0
	int 13h


        ; save boot sector to last sector on diskette.
        ; 1st, see if this is 40 or 80 tracks.

        lea     bx, endflag
        mov     si, bx                  ;
        add     bx, 512                 ; make room for new sector to read 
        add     si, 18h
        mov     cl, byte ptr[si]        ; load maximum sectors/track
        add     si, 2                   
        mov     dh, byte ptr[si]        ; load maximum heads/disk
        dec     dh                      ; make 0 based
        mov     ch, 79                  ; try HDD disk 1st
        mov     ax, 0201h


readlastsector:
        push    ax
        push    bx
        push    cx
        push    dx
        push    si
        int     13h                     ; save all registers, cuz we'll need
        pop     si                      ; em again in a second
        pop     dx
        pop     cx
        pop     bx
        pop     ax
        jnc     findlastexit


        ; must be a low density disk

        mov     ch, 39h
        jmp     readlastsector          


findlastexit:
        ret

findlastsector endp

write_bootsector proc
;this routine writes the actual boot sector to the floppy drive and makes
;sure the drive is ready and readable.

        call    check4driveready

        mov     ax, 0201h
        lea     bx, endflag
        mov     cx, 1
        mov     dx, 0
        int     13h


        call    findlastsector

        push    cx
        push    dx

        mov     ax, 0301h
        lea     bx, endflag             ; point back to original bootsector
        int     13h                     ; save to last sector on disk
                                        ; no error check; we'll get that
        pop     dx                      ; on the next write.
        pop     cx

        lea     si, oldsectorcx         ; save off cx/dx of orig boot sector
        mov     word ptr [si], cx       ; for loading at next boot.
        
        lea     si, oldsectordx
        mov     word ptr [si], dx


        mov     ax, 0                   ; reset
        mov     dl, 0
        int     13h

        mov     ax, 0301h               ; write new boot sector
        lea     bx, bootsector
        mov     dx, 0
        mov     cx, 1
        int     13h
        ret                             



	jmp write_bootsector

write_bootsector endp




write_vectable proc
;this routine reads the vector table from the floppy disk and write it to a
;file.


        call    check4driveready

        mov     ax, 0201h
        lea     bx, endflag
        mov     cx, 1
        mov     dx, 0
        int     13h

        call    findlastsector

        dec     cl                      ; back up by 1 sector





	mov ax,0
	mov dl,0
	int 13h

	lea bx,endflag
	mov ax,0202h
	int 13h


	mov ah,3ch                             ;open our filename
	mov cx,0                               ;
        lea dx,vectortbl                       ;no error checking. 
        int 21h                                ;this shouldn't fail

	mov bx,ax

	mov ah,40h                             ;write contents to a file
	mov cx,1024                            ;write 1k of data
	lea dx,endflag                         ;
        int 21h                                ;no error checking
    ;   jc writeerror                          ;if this fails, there are
                                               ;bigger problems to deal with.
	mov ah,3eh                             ;close file
	int 21h
	ret

write_vectable endp



go:

	mov ax,3
	int 10h
	mov ax,1112h
	int 10h            ;switch to 80x50




	; see where we are in the installation process.


	push bx
	push es
	mov bx,40h
	mov es,bx
	mov bx,0f0h
	cmp byte ptr es:[bx],MAGIC
	mov byte ptr es:[bx],0
	pop es
	pop bx
	jnz begining





	call drawscreen
	lea bp, endingmsg
        call dotext
	call anykey
	jc exit

	
	call write_vectable

	call drawscreen
	lea bp, finished
        call dotext

	xor ax,ax                              ;wait for a key
	int 16h
        jmp bail                               ;done


begining:
	call drawscreen
	lea bp,welcomemsg
        call dotext
	call anykey
	jc exit

	call drawscreen

	lea bp,step1
        call dotext
	call anykey
	jc exit

	call drawscreen
	lea bp,step2
        call dotext
	call anykey
	jc exit

	call drawscreen
	lea bp,step3
        call dotext
	call anykey
	jc exit


	call write_bootsector



	call drawscreen
	lea bp,step4
        call dotext
	call anykey
	jc exit


	;create flag file for when we come back.

	mov ax,-1
	push ax                            ; jump to FFFF:0 for a reboot!
	mov ax,0
	push ax
	retf


exit:
	mov ax,3
	int 10h

	mov ax,4c01h
	int 21h






endflag:
cseg ends
end main




