comment %
release version 0.2.6  05/02/00

See history.txt for revision notes and differences.

        
floppy diskette boot emulator  (aka flopper)
jeff leyda
jeff@silent.net


flat real mode memory routines written by NiX / MASSiVE
cpu id code comes from the book "undocumented PC"
chooser portion written by demonlord


the following code and concept are to remain in the public domain as
freeware to be used and modified by anyone who choses to use it.
please don't be a dick and steal the code and try to sell it! 

compiled with TASM 3.0, linked with MS-LINK 5.10
will compile with TLINK using the /3 option.
will also compile with MASM/LINK

main documentation for program usage can be found in the file INSTALL.HTM
or INSTALL.TXT


様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様
memory map:

        0:0 -> 512k             DOS/game
        513k -> ?               flopper suport routines
        1mb -> 1mb+512k         DOS/game  (1mb defined in equates.inc)
        1mb+512k - >1mb+513k    registers/reserved space
        1mb+513k - >xxx         disk image
        
様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様

TODO:
       .cpu slowdown support  keep slowing down and testing the cpu speed
        til it hits ~5Mhz.   All of these games were originally written for
        a 4.77Mhz machine in the first place. 
       .support for 128 and 1k and 2k byte sector sizes
       .better keyboard intercept routines.  some games don't like the
         intercept that i'm doing right now.  (jumpman)
       .add opening screen display?
       .shell to dos feature from within chooser
       .command line switches to over-ride defaults.  ie: disk size, cpu
        slowdown, etc.
       .windows version using V-86 mode.  We could do SOOO much with this.

%
STAPEL SEGMENT STACK USE16 'Stack'
dw 200 dup(?)
STAPEL ENDS

CODE SEGMENT USE16
Assume cs:code, ss:stapel



;陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳
; Include files
;陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳陳
include constant.inc    ; Stuff that never changes.
include equates.inc     ; run time and compile time variables
include debug.inc       ; debugger support.  Not really needed for now.
include flatmem.inc     ; Generic Memory and Flat Real Mode routines
include revector.inc    ; interrupt vector table loading routines
include cpu.inc         ; detect CPU code support
include diskette.inc    ; diskette definitions and code
include fileio.inc      ; file opening, closing, etc code
include cmdline.inc     ; command line input routines
include flopisr.inc     ; flopper ISR support code
include scrnshot.inc    ; screenshot support code
include rtc.inc         ; real time clock/cpu slowdown routines
;include misc.inc       ;junk.  old code that may be needed someday

;様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様
;                          MAIN CODE STARTING POINT
;様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様
Start:

        ; system checks, get into flat memory model

        call    check_cpu               ; requires at least a 386. 
        call    check_himem             ; no himem.sys!       
        call    check_2mb               ; requires at least 2mb
        call    Set4Gig                 ; Swap to Flat Real Mode
        call    EnableA20               ; Enable the A20-line

        cli
        mov     bx, ss
        mov     cs:[ss_val], bx
        sti

        ; put chooser at INT 3F
        push    es
        push    cs
        pop     es
        mov     bx, offset chooser
        mov     al, 03fh
        call    changeISR
        pop     es

        ; check files, load image
        call    process_cmdline         ; grab filenames, switches, etc
        call    open_file               ; open file if exists
        jnc     open_ok
        jmp     exit
open_ok:
        call    get_disk_params         ; return disk image Spt/H/T info
        call    load_image              ; load diskette image
        call    close_file              ; close 


reboot:
        call    put512high              ; copy DOS area high in memory

        ; prepare for boot              

        call    change_base_size        ; set BDA memory size to 512k
        call    copy_code               ; load flopper support above 512k
        nop
        call    reset_vectors           ; load virgin vector table
     ;   call    relocateIrqs            ; relocate IRQ 0-7 -->50-57h



        ; figure out starting location of new INT service
        ; move this to a subroutine too.
        mov     si, offset flopper_top  ; point to start of flopper routines
        mov     bx, offset int13        ; point to start of new INT13
        sub     bx, si                  ; from offset of flopper_top
        mov     dx, offset realInt13    ; point to storage for old INT13
        inc     dx                      ; add 1 for "db EA" instruction.
        sub     dx, si
        mov     al, 13h
        call    changeISR

        mov     si, offset flopper_top  ; point to start of flopper routines
        mov     bx, offset int15        ; point to start of new INT15
        sub     bx, si                  ; from offset of flopper_top
        mov     dx, offset realInt15    ; point to storage for old INT15
        inc     dx                      ; 
        inc     dx
        sub     dx, si
        mov     al, 15h
        call    changeISR


        mov     si, offset flopper_top  ; point to start of flopper routines
        mov     bx, offset int5         ; point to start of new INT5
        sub     bx, si                  ; from offset of flopper_top
        mov     dx, offset realInt5     ; point to storage for old INT5
        inc     dx                      ; add 1 for "db EA" instruction.
        sub     dx, si
        mov     al, 5
        call    changeISR
                                        
        call    disable_cache           ; turn off L1 Cache if 486+   


   ;     mov     si, offset flopper_top
   ;     mov     bx, offset int70
   ;     sub     bx, si
   ;     mov     al, 70h
   ;     call    changeISR
   
   ;     call   slowdown_cpu             ; throttle back to 4.77MHz
                                         ; can't start this until INT 70
                                         ; vector is in place cuz Int70 will
                                         ; start immediately after this call.
        



        ; "load" disk!
        
        xor     ax, ax
        mov     es, ax                  ; load 1st sector to 0:7c00
        mov     bx, 7c00h
        mov     ah, 2                   ; read
        mov     al, 1                   ; 1 sector
        mov     ch, 0                   ; track 0
        mov     cl, 1                   ; sector 1
        mov     dh, 0                   ; head 0
        mov     dl, 0                   ; drive 0 (a:)
        int     13h                     

        xor     ax, ax
        mov     bp, ax                  ; set up registers like they would
        mov     ds, ax                  ; be for "booting"
        mov     ss, ax
        mov     sp, 400h

        push 0                          ; jump to 0:7c00 to "boot" diskette
        push 7c00h
        retf
        

;様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様
;                          CHOOSER STARTING POINT
;様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様様

chooser_msg     db      "Welcome to chooser!",CR,LF
                db      "Current Image is:$"

chooser_msg2    db      CR,LF,CR,LF,"Select:",CR,LF
                db      " 1. load image",CR,LF
                db      " 2. save image",CR,LF
                db      " 3. Write $"




chooser_msg3    db      " disk",CR,LF
                db      " 4. Boot current image",CR,LF
                db      " 5. Return to image",CR,LF
                db      "ESC Exit to DOS$"


prot_msg        db      "protect$"
enab_msg        db      "enable$"

ss_val          dw      0       ; storage for Stack segment
ss_ret          dw      0
flags           db      0
fname           db      76 dup(0)
newfilestr      db      CR,LF,CR,LF,'Enter new image filename: $'
warning_msg     db      CR,LF,"Warning! Disk image was written!",CR,LF
                db      "Changes will be lost!  Press ESC again to exit$"        
cga_reg         dw      ?       ; storage for 3d8, 3d9 register
mode_page       dw      ?       ; storage for video mode and page
chooser:

        cli
        mov     cs:[ss_ret], ss              ; save game SS
        mov     ss, cs:[ss_val]              ; restore flopper SS
        sti



        pusha
        push    ds
        push    es


        push    cs
        push    cs
        pop     ds
        pop     es


        ; signal end of interrupt
        push    ax
        mov     al, 20h
        out     20h, al
        out     0a0h, al
        out     20h, al
        pop     ax
        int     9
        
      ;

        









        mov     cs:[flags], al                  ; save flopper flags
        mov     cs:[mode_page], bx              ; save video info

        test    al, SCREENSHOT
        jz      chooser_menu

        call    do_screenshot
        jmp     exit_chooser



chooser_menu:

        call    savescreen
        mov     dx, CGA_CONTROL_REGISTER
        in      ax, dx
        mov     [cga_reg], ax
getselect:
        mov     bx, 0
        mov     ax, 3
        int     10h
        lea     dx, chooser_msg
        mov     ah, 9
        int     21h


        ;print current image filename

        lea     di, fname
        mov     ax, 1212h
        int     2Fh

        add     di, cx
        mov     byte ptr [di],"$"

        lea     dx, fname
        mov     ah, 9
        int     21h
        mov     byte ptr [di],0                 ; restore name to asciiz

        lea     dx, chooser_msg2
        int     21h


        test    byte ptr flags, DISK_PROTECTED
        jz      wpenabled

        lea     dx, enab_msg
        int     21h
        jmp     msg3

wpenabled:
        
        lea     dx, prot_msg
        int     21h

msg3:
        lea     dx, chooser_msg3
        int     21h
        mov     ax, word ptr gs:[41ch]          ; clear keyboard buffer
        mov     word ptr gs:[41ah],ax
	
        xor     ax, ax
        int     16h
        cmp     al, ESCAPE
        jz      check_written

        cmp     al, "1"                         ; load new image
        jz      load_disk

        cmp     al, "2"                         ; save current image to HDD
        jz      save_disk

        cmp     al, "3"                         ; write protect current image
        jz      wp_toggle

        cmp     al, "4"                         ; reboot current image
        jz      reboot

        cmp     al, "5"                         ; nothing.
        jz      restoreandexit

        cmp     al, CR
        jz      restoreandexit

        jmp     getselect

save_disk:
        lea     dx, fname
        call    save_image
        and     flags, NOT DISK_WRITTEN         ; update image written flag
        jmp     getselect

wp_toggle:

        xor     flags, DISK_PROTECTED
        jmp     getselect

check_written:
        test    flags, DISK_WRITTEN
        jz      exit

        mov     ah, 9
        lea     dx, warning_msg
        int     21h

        xor     ax, ax
        int     16h
        cmp     al,ESCAPE
        jnz     getselect
        jmp     exit


load_disk:
        mov     ah, 9
        lea     dx, newfilestr
        int     21h

        lea     di, fname       ;Filename buffer

newkey:
        xor     ax,ax
        int     16h
        cmp     al,ESCAPE
        jz      Exit
        cmp     al,13           ;Enter
        jz      NewFile
        cmp     al,8            ;Backspace
        je      Erase
        cmp     al,32           ;Space+
        jb      newkey

        cmp     di,offset FName+75     ;Not too long??
        ja      newkey
        stosb                   ;Store character
        mov     ah,0eh
        mov     bx,7
        int     10h             ;Show character entered
        jmp     newkey

Erase:
        cmp     di,Offset FName
        jbe     NewKey          ;Check length
        mov     ah,3
        mov     bh,0
        int     10h             ;Get cursor pos
        dec     dl
        push    dx
        mov     ah,2
        int     10h             ;Move one step left
        mov     ax,0e20h
        mov     bx,7
        int     10h             ;Erase current char
        pop     dx
        mov     ah,2
        int     10h             ;Restore cursor pos
        dec     di              ;Remove last char from buffer
        jmp     NewKey

NewFile:
        cmp     di,Offset FName
        jbe     Exit_chooser            ; Nothing entered

        mov     al, 0                   ; null terminate
        stosb

        lea     dx, fname


        call    open_file               ; open file if exists
        jc      exit

        call    get_disk_params         ; return disk image Spt/H/T info
        call    load_image              ; load diskette image
        call    close_file              ; close
        or      flags,DISK_CHANGE       ; set diskchange flag
        jmp     getselect               
                



restoreandexit:

        mov     ax, mode_page
        xor     ah, ah
        int     10h

        mov     ax, mode_page
        xchg    al, ah
        mov     ah, 05
        int     10h


        call    restorescreen           ; restore video data

        mov     dx, CGA_CONTROL_REGISTER
        mov     ax, [cga_reg]
        out     dx, ax
  

exit_chooser:

        ; signal end of interrupt again?
        push    ax
        mov     al, 20h
        out     20h, al
        out     0a0h, al
        out     20h, al
        pop     ax
        int     9

        pop     es
        pop     ds
        popa

        cli
        mov     ss, cs:[ss_ret]
        sti

        mov     al, cs:[flags]
        iret


exit:
        call    restore_cache           ; re-enable L1 cache if need be
        call    rtc_off
        ; signal end of interrupt
        push    ax
        mov     al, 20h
        out     20h, al
        out     0a0h, al
        out     20h, al
        pop     ax

        mov     ah, 4ch
        int     21h

endflag:
CODE ENDS
End Start

