[Floppertalk] Fw: Booting larger Image-formats with flopper
Ulrich Diez
floppertalk@oldskool.org
Sun, 5 May 2002 21:25:16 +0200
Dear FlopperTalk-member,
A few days ago I loaded down the Program "Flopper" (release version 0.2.6 05/02/00) from www.oldskool.org.
I intended to use it in order to boot some DOS-, OS2- and Linux-Bootdisk-Images. For Images of 360k-720k-Floppies it works greatly.
I also have some larger Disk-Images (1.2 MB/1.44 MB).
Therefore I have two questions:
1)
In the PDF-file which comes with flopper, it is mentioned that support for such image-formats can be added easily. Unfortunately I don't know all too much about assembler-programming (I just know how to install TASM, TLINK and how to compile an already-working .asm-file) and therefore am not able to add the support for such image-formats myself.
Could somebody give me some "newbie-advice" on how this is done or drop me a hint on some books/tutorials where one can learn assembler-programming from the grounds up ?
2)
As floppers' ability to change disk-images will be lost after booting DOS- or Linux - boot-images, I intended to put a little program (TurboImage, Author: Pierre J. le Riche) in the image-files themselves. TurboImage is a memory-resident (POP-UP-program for DOS (not Windows) which emulates a virtual disk-drive with a disk-image. (It also has support for larger image-formats, therefore the Assembler-source-code is listed below, might be it helps.)
Does somebody know Turbo-Image ? If so, which problems might occur when using Turbo-Image within a flopper-booted image-file ?
Thank you very much in advance.
Yours sincerely
Ulrich Diez
________________________
Ulrich Diez, stud. rer. nat.
Reply-adress: ulrich.diez@student.uni-tuebingen.de
;****************************************************************************
;****************************************************************************
;**
;** File : TI.ASM (TurboImage Source File)
;**
;** Author : Pierre J. le Riche
;**
;** Purpose : Program to access various disk images as a drive.
;** *FREEWARE* Use freely, but at your own risk. Please share all
;** improvements, updates, etc. May be distributed on CD-ROMs etc.
;** Not to be sold for profit.
;** email: pleriche@firga.sun.ac.za (version 0.01à to 1.00m, 1.01d)
;** s9231498@firga.sun.ac.za
;**
;** A&L Software: alsoft@usa.net (version 1.01c, 1.01e)
;**
;** Created : 15/12/1993 (version 0.01à)
;**
;** Recent Updates : 07/11/1996 (version 1.01c)
;** by A&L Software
;** 20/08/1997 (version 1.01d)
;** by PLR (2.88M Support, now works under '95)
;** 22/08/1997 (version 1.01e)
;** by A&L Software (options /2 and /1, popup bug fixed)
;**
;** Known bugs: 1) Formatting the fake drive to capacities larger than the
;** physical floppy size causes it to have lost clusters.
;** Probably because DOS gets the drive info from the CMOS. Run
;** chkdsk/f after formatting to large non-standard capacities.
;** 2) If TI is uninstalled while a floppy is in the substituted
;** drive, DOS will not report the correct disk particulars
;** until the disk is removed and replaced again. This has to
;** do with the "Changeline" flag in the floppy BIOS - While
;** TI is installed it reports fake disk changes to DOS.
;** After uninstallation DOS still thinks the image is in the
;** drive... A solution (though not a good one) might be to force
;** a disk read just before uninstallation...
;**
;** Notes : Compile with TASM 3 (use /M9 option) and link to a .COM file
;**
;*****************************************************************************
;*****************************************************************************
smart
jumps ;TASM compiler directives
cseg segment ;the code (and only) segment
;ds and es are always assumed to be the same as cs
assume cs:cseg,ds:cseg,es:nothing,ss:nothing
org 100h
start: jmp begin ;jump to initialization code
;****************************************************************************
;****************************************************************************
;** DATA AND PROCEDURES FOR POPUP ROUTINE
;****************************************************************************
;****************************************************************************
indos dd 0 ;pointer to INDOS flag, 0=OK to call DOS
function db 0 ;the function requested with the last INT 16H
wait28h db 0 ;1=popup on next int 28h
inroutine db 0 ;1=already in routine, do not re-enter
scroff dw 0 ;segment offset of video memory
oldmode db 0 ;old display mode
setmode db 0 ;1=set old screen mode on exit
oldpage db 0 ;old screen mode video page
curpage db 0 ;current video page
oldcurpos dw 0 ;old cursor position
maytoggledrive db 1 ;1=drives may be toggled
savetype db 1 ;0=full size, 1=used tracks, 2=used sectors
savetypes db "Full size " ;saves complete image
db "Used tracks" ;saves up to last used track
db "Used sector" ;saves up to last used sector
savesecs dw 0 ;number of sectors to write during save
secsperclust dw 0 ;sectors per cluster (for .DCF saving calcs.)
;The top lines of the popup display
popupbox db "º TurboImage v1.01e - Access a disk image file as a drive - P.J. le Riche 1997 º"
db "ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͹"
db "º [F1]Toggle Status(O ) [F2]Toggle Drive( :) [F3]Toggle Write Protect(O ) º"
db "º [F5]Read Image File [F6]Write Image File [F10]Uninstall TurboImage º"
;Uninstall prompt box
uninstbox db "º Do you want to uninstall TI? º"
db "º [Y]es or [N]o. º"
;Error message if program cannot uninstall
cannotuni db "º Cannot uninstall. Interrupts º"
db "º hooked by other program(s). º"
;File load prompt
loadbox db "ÉÍÍÍÍÍÍÍÍÍÍÍÍ͵LOAD DISK IMAGE:ÆÍÍÍÍÍÍÍÍÍÍÍÍÍ»"
db "º ?:\*.* º"
db "ÇÄÄÄÄDRIVESÄÄÄÄÂÄDIRECTORIESÄÄÂÄFILES(min8K)Ķ"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "º ???????????? ³ ???????????? ³ ???????????? º"
db "ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍÍÏÍÍÍÍÍÍÍÍÍÍÍÍÍͼ"
;Variables used in load box: 3 lists (drive, dir & files)
listents dw ?,?,? ;Number of entries in each of the 3 lists
listoffset dw offset begin,?,? ;Offset of start of data for each list
curent dw 0,0,0 ;currently highlighted entry for each list
curoff dw 0,0,0 ;current list offset for each list
curlist db 2 ;currently selected list
dditype dw 1200h,1e00h ;disk position in diskdupe image file
dw 1200h,2400h
dw 4800h,1000h
;Message display if an attempt is made to load an invalid image file
badimage db "º Not a valid image file. º"
;Message display if insufficient memory to load image file
nomemstr db "º Insufficient memory. º"
;Message displayed during loading of a file
loading db "º Loading file: ?,???,??? OK º"
db "º º"
;CRC related messages
nocrcinfomsg db "No CRC info found in file."
crcokmsg db "CRC check OK, CRC="
crcbadmsg db "Warning! CRC check failed!"
bytesrewr dd 0 ;number of bytes read/written so far
loadfile db 44 dup (0) ;filename of file currently being opened
;message box displayed for file save operations
savefile db "ÉÍÍÍÍÍÍÍÍÍÍÍÍÍ͵SAVE IMAGE FILE:ÆÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»"
db "º ",0,"º"
db "ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ"
db "º [F7]Save mode(???????????) [F8]Save CRC(O ) º"
db "ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ"
editoff dw 0 ;offset in file save edit box
;error during load box
loaderr db "º Error loading image file!? º"
;prompt for overwrite if file exists and save is selected
fileexists db "º File exists. Overwrite? º"
;Progress box for save operations
saving db "º Writing file: ?,???,??? OK º"
db "º º"
nocrcsavmsg db "No CRC info saved to file."
crcsavmsg db "CRC appended, CRC="
;Error during save box
saveerr db "º Error writing image file!? º"
;****************************************************************************
;****************************************************************************
;** MAIN POPUP ROUTINE
;** Pops up box when control-alt-t is pressed
;** Routine called by new int 16h handler, or new int 28h handler,
;** when it is safe to do disk accesses through DOS
;****************************************************************************
;****************************************************************************
popup:push ax bx cx dx si di bp ds es
push cs
pop ds ;set up ds to point to cs: must always be so
mov inroutine,1 ;indicates routine is currently running
mov wait28h,0 ;not waiting anymore
mov setmode,0 ;do not set old screen on exit
;set up new interrupt 24h vector: automatically fail all disk errors
mov ax,3524h
int 21h
mov word ptr oldint24h,bx
mov word ptr oldint24h[2],es
mov dx,offset newint24h
mov ah,25h
int 21h ;new int 24h handler now set up
sti ;enable interrupts
;check display mode: must be in 80x25 or 80x50 text mode
mov ah,0fh
int 10h ;get mode, page in bh
mov oldpage,bh ;save old display page
mov ah,3
push ax
int 10h ;get cursor position
mov oldcurpos,dx ;save old cursor position
pop ax
;check video mode for valid modes
cmp al,7
je modeok
cmp al,2
jb badmode
cmp al,3
jbe modeok
badmode:mov oldmode,al ;invalid mode: save it
mov setmode,1 ;set flag: reset mode on exit
;we'll have to keep the old palette if we change screen mode
mov ax,1017h
xor bx,bx
push cs
pop es
mov dx,offset begin
mov cx,256
int 10h ;read the whole palette
mov si,dx ;palette is at ds:si
mov ax,cs:[xmsdesired] ;copy palette after screen backup
add ax,4 ;(address is (xmsdesired+4)*2)
add ax,ax
call writesector
inc ax
call writesector ;save the palette
mov ax,83h
int 10h ;set 80x25 text mode, don't clear display
xor bh,bh ;video page 0
modeok:mov curpage,bh
mov ah,2
mov dh,50
int 10h ;remove cursor from display
;get offset of video buffer
xor ax,ax
mov es,ax
mov scroff,0b800h
cmp es:[463h],word ptr 3b4h
jne notmono
mov scroff,0b000h
notmono:mov ax,es:[44eh] ;get page size in ax
shr ax,4 ;divide ax by 16 -> convert to segment
add scroff,ax ;offset of current page
;save screen: save display by copying it to xms
mov ds,scroff
xor si,si
mov ax,cs:[xmsdesired] ;copy screen after disk data space
add ax,ax ;(address is (xmsdesired)*2)
mov cx,8 ;4k for the screen
savlp:call writesector ;write screen "sector"
inc ax
loop savlp ;8*512 byte blocks=4k
push cs
pop ds
;check if mode was changed: blank bottom 19 lines
cmp setmode,1
jne notblankbot
mov es,scroff
mov di,6*80*2
mov cx,19*80
mov ax," "+7*256
rep stosw
notblankbot:
push cs
pop es ;set up segment registers
;****************************************************************************
;* Main loop for popup box
;****************************************************************************
updloop:call updatescreen ;update the top 6 lines of the display
;clear load and save box second line
xor al,al
mov di,offset loading+30*1+1
mov cx,28
push cx
rep stosb
pop cx
mov di,offset saving+30*1+1
rep stosb
;clear CRC number (used during load and save operations)
mov word ptr CRC32,0ffffh
mov word ptr CRC32[2],0ffffh
xor ah,ah
int 16h ;read a key from the keyboard
;****************************************************************************
;*check for F1 pressed: toggle drive substitution on/off
;****************************************************************************
cmp ax,3b00h
jne notf1pr
mov ah,0dh
int 21h
mov changelineflag,3
xor activeflag,1
jmp updloop
notf1pr:
;****************************************************************************
;*check for F2 pressed: toggle substituted drive
;****************************************************************************
cmp ax,3c00h
jne notf2pr
cmp maytoggledrive,1
jne updloop
mov ah,0dh
int 21h
mov changelineflag,3
xor substdrive,1
jmp updloop
notf2pr:
;****************************************************************************
;*check for F3 pressed: toggle writeprotect on/off
;****************************************************************************
cmp ax,3d00h
jne notf3pr
xor writeprotect,1
jmp updloop
notf3pr:
;****************************************************************************
;*check for F5 pressed: load image
;****************************************************************************
cmp ax,3f00h ;check for f5
jne notf5
getloadlist:mov di,offset begin ;es:di points to start of buffer
xor bp,bp ;so far no valid drives
;first get the drives
mov ah,19h
int 21h ;get current drive
push ax ;save the current drive
mov dl,2 ;start testing drives at drive c:
testdrive:mov ah,0eh
int 21h ;try to select disk
mov ah,19h
int 21h
cmp al,dl
jne invaliddrive
push ax
mov ax," "
stosw
stosw
stosb
pop ax
add al,"A"
mov ah,":"
stosw
mov ax," "
stosw
stosw
stosb
inc bp ;increase the drive count
invaliddrive:inc dl
cmp dl,25
jna testdrive
pop ax
mov ah,0eh
mov dl,al
int 21h ;reset default drive
mov al," "
mov cx,12*12
rep stosb ;provide 12 blank entries trailing the list
;store the drive count and offset of the directory list
mov listents,bp
mov listoffset[2],di
;save the old DTA address
mov ah,2fh
int 21h
push bx es ;save the old DTA address
push cs
pop es ;restore segment registers
;set the new DTA address
mov ah,1ah
mov dx,80h
int 21h ;set DTA over command tail
;now get the directory list
xor bp,bp ;no directory entries so far
;do a findfirst call with cx=attr of directory
mov ah,4eh
mov cx,12h ;search for directories (incl. hidden dirs)
mov dx,offset loadbox+1*46+2
int 21h
jc gotalldirs
copydirlp:test ds:[95h],byte ptr 10h
jz nextdir ;must be a directory
mov si,9eh
cmp [si],word ptr "."
je nextdir ;don't want current directory listed
mov cx,12
cpchdir:lodsb
or al,al
jz enddir
stosb
loop cpchdir
jmp dirend
enddir:rep stosb
dirend:inc bp ;increase number of dirs
;find next directory
nextdir:mov ah,4fh
int 21h
jnc copydirlp
gotalldirs:mov cx,12*12
mov al," "
rep stosb ;12 blank entries
mov listents[2],bp ;number of dirs
mov listoffset[4],di ;offset of filename list
;now get the list of files
xor bp,bp ;no files so far
;do a findfirst call with cx=attr of files
mov ah,4eh
mov cx,2h ;search for files (including hidden ones)
mov dx,offset loadbox+1*46+2
int 21h
jc gotallfiles
copyfilelp:cmp ds:[9ch],word ptr 0
jnz filebigenough ;files must be > 8k
cmp ds:[9ah],word ptr 8192
jb nextfile
filebigenough:mov si,9eh
mov cx,12
cpchfile:lodsb
or al,al
jz endfile
stosb
loop cpchfile
jmp filend
endfile:rep stosb
filend:inc bp ;increase number of files
cmp di,offset begin+buffersize-512-12*13
ja gotallfiles ;prevent buffer from overflowing,
;reserve 1 sector for workspace
;find next file
nextfile:mov ah,4fh
int 21h
jnc copyfilelp
gotallfiles:mov cx,12*12
mov al," "
rep stosb ;12 blank entries
mov listents[4],bp ;number of files
;reset the DTA to old value
restoredta:pop ds dx
mov ah,1ah
int 21h
push cs
pop ds ;restore segment register
;bubblesort all three lists
mov bx,1 ;start off with list 1: drives unsorted
sortlist:mov bp,bx
shl bp,1 ;bp=list index
mov si,listoffset[bp] ;si=list start
mov dx,si ;lower limit in dx
;get end of list
addsi12:cmp [si+12],byte ptr " "
je nextsortiteration ;si points to end
add si,12
jmp addsi12
nextsortiteration:mov di,si
sub di,12 ;di=next entry
push si di
sortents:cmp si,dx ;check for end of list
jbe sortendlist
push si di
mov cx,12
rep cmpsb
pop di si
ja nosortswap
push si di
mov cx,12
xchglp:lodsb ;exchange entries
mov ah,[di]
stosb
mov [si-1],ah
loop xchglp
pop di si
nosortswap:mov si,di
sub di,12
jmp sortents
sortendlist:pop di si
add dx,12
cmp si,dx
ja nextsortiteration
inc bl
cmp bl,3
jb sortlist ;sort next list
;check that currently selected entries are valid
xor bx,bx ;start with list 0
mov cx,3
chklistent:mov ax,curent[bx]
cmp ax,listents[bx]
jb listok
mov curent[bx],0
mov curoff[bx],0
listok:add bx,2
loop chklistent
;redisplay file list display here
loadfiledisplay: ;update the box display
mov bx,12 ;3 lists, 12 entries each
mov di,offset loadbox+3*46+2
dolist:push di
mov al,bh
xor ah,ah
shl ax,1
mov bp,ax
mov ax,curoff[bp] ;get offset of list
mov cx,12
mul cx
add ax,listoffset[bp]
mov si,ax ;si points to start of current list
xor dl,dl
cplent:mov [di-1],byte ptr " " ;remove highlight
cmp bh,curlist
jne nothighlight
mov ax,curent[bp]
sub ax,curoff[bp]
cmp al,dl
jne nothighlight
mov [di-1],byte ptr 16
mov [di+12],byte ptr 17
nothighlight:mov cx,12
rep movsb
add di,46-12
inc dl
cmp dl,12
jb cplent
pop di
add di,12+3
inc bh
cmp bh,3
jb dolist
;display the load box
mov si,offset loadbox
mov es,scroff
mov di,(7*80+17)*2 ;set position of text box
mov bl,16 ;do all the lines
mov ah,64+15
pruninstlp3:mov cx,46
chlpu3:lodsb
cmp al,16
jne notsthighlight
mov ax," "+96*256
notsthighlight:cmp al,17
jne notendhighlight
mov al," "
stosw
mov ah,64+15
jmp nxtchl
notendhighlight:stosw
nxtchl:loop chlpu3
add di,(80-46)*2
dec bl
jnz pruninstlp3
push cs
pop es ;restore segment registers
;read user's response
mov bl,curlist
shl bl,1
xor bh,bh ;bx=current list*2
xor ah,ah
int 16h ;get a keystroke
cmp ah,50h ;check for down arrow
jne lfnotdnarrow
mov ax,curent[bx]
inc ax
cmp ax,listents[bx]
jnb loadfiledisplay
inc curent[bx]
mov cx,curoff[bx]
add cx,12
cmp ax,cx
jb loadfiledisplay
inc curoff[bx]
jmp loadfiledisplay
lfnotdnarrow:cmp ah,51h
jne notpgdn ;check for page down
mov ax,listents[bx]
sub ax,curent[bx]
dec ax
cmp ax,12
jbe maxpgdn
mov ax,12
maxpgdn:add curent[bx],ax
chkpgdnlp:mov ax,curoff[bx]
add ax,12
cmp ax,curent[bx]
ja loadfiledisplay
inc curoff[bx]
jmp chkpgdnlp
notpgdn:cmp ah,48h
jne lfnotuparrow ;check for up arrow
cmp curent[bx],0
je loadfiledisplay
dec curent[bx]
mov ax,curent[bx]
cmp ax,curoff[bx]
jnb loadfiledisplay
dec curoff[bx]
jmp loadfiledisplay
lfnotuparrow:cmp ah,49h
jne notpgup ;check for page up
mov ax,curent[bx]
sub ax,12
jnc pgupaxok
xor ax,ax
pgupaxok:mov curent[bx],ax
cmp ax,curoff[bx]
jnb loadfiledisplay
mov curoff[bx],ax
jmp loadfiledisplay
notpgup:cmp ah,4bh
jne lfnotleftarrow ;check for left arrow
dec curlist
cmp curlist,2
jna loadfiledisplay
mov curlist,0
jmp loadfiledisplay
lfnotleftarrow:cmp ah,4dh ;check for right arrow
jne lfnotrightarrow
inc curlist
cmp curlist,2
jna loadfiledisplay
mov curlist,2
jmp loadfiledisplay
lfnotrightarrow:cmp al,27 ;check for escape
jne lfnotesc
call lodscrbot
jmp updloop
lfnotesc:cmp al,13 ;check for enter
jne lfnotent
cmp curlist,2
jne entnotfile ;enter pressed on file: load it
;first clear number of bytes read
mov di,offset loading+16
mov cx,12
xor ax,ax
rep stosb
mov word ptr bytesrewr,512
mov word ptr bytesrewr[2],0
;clear filename space
mov di,offset loadfile
mov cx,44
rep stosb
;copy the pathname
mov si,offset loadbox+46*1+2
mov di,offset loadfile
cpchlpfl:lodsb
cmp al,"*"
je stfilnam
stosb
jmp cpchlpfl
stfilnam:;now copy the filename
mov ax,curent[4]
mov bx,12
mul bx
add ax,listoffset[4]
mov si,ax
mov cx,12
rep movsb
xor al,al
stosb
;open the file
mov dx,offset loadfile
mov ax,3d00h
int 21h
jc badfile
mov bx,ax ;handle in bx
;check if the file has CRC info
mov CRCFound,0 ;default to no CRC info
mov ax,4202h ;move file pointer to end -16
mov cx,-1
mov dx,-16
int 21h ;move file pointer
jc badfilec
mov dx,offset begin+buffersize-512
mov cx,16 ;16 bytes in CRC info
mov ah,3fh
int 21h ;read CRC info
jc badfilec
mov si,offset begin+buffersize-512
mov di,offset CRCFootprint
mov cx,12
repe cmpsb ;compare footprints
jne noCRCinfo
;Copy CRC found in file
mov di,offset FileCRC
movsw
movsw
mov CRCFound,1 ;CRC has been found
noCRCinfo:;reset file pointer to start
mov ax,4200h
xor cx,cx
xor dx,dx
int 21h
jc badfilec
;read first block of image
mov ah,3fh
mov cx,512
mov dx,offset begin+buffersize-512
int 21h
jc badfilec
push bx ;verify signature:
mov bx,offset begin+buffersize-512
mov cx,4d49h
cmp [bx],cx
jnz ucopy ;diskdupe
xor ah,ah
mov al,[bx+0ah]
dec al
add ax,ax
mov bx,ax
mov dx,[offset dditype+bx]
jmp readboot
ucopy: ;ultracopy
xor al,al
cmp [bx+1],al
jnz msxdump
mov dx,0bh
jmp readboot
msxdump: ;msxdump
mov al,10
cmp [bx],al
jnb rawformat
mov dx,1
jmp readboot
rawformat: ;other format (raw image files)
xor dx,dx
readboot: ;read boot sector
xor cx,cx
pop bx
mov ax,4200h
int 21h
jc badfilec
mov ah,3fh
mov cx,512
mov dx,offset begin+buffersize-512
int 21h
jc badfilec
cmp ax,cx
jne badfilec
call checkboot ;check that boot sector is valid
or ax,ax
jz badfilec
call checksize ;check if there is sufficient memory
or ax,ax ;to load diskimage
jz nomemory
;seems image is OK: load it
mov sectors,cl
mov totalsecs,ax
xor bp,bp ;current sector
mov cx,1 ;number of sectors to copy into XMS pool
mov si,offset begin+buffersize-512
jmp copyseclp
copysecs:mov si,offset begin
copyseclp:cmp crcfound,1
jne nocrccalcr ;Don't calc CRC if no info in file
push si cx bx
call CalcCRC32 ;update the CRC32 count
pop bx cx si
nocrccalcr:mov ax,bp
call writesector
inc bp
cmp bp,totalsecs
jnb gotfile
loop copyseclp
;clear the buffer (to remove garbage from end of image)
mov di,offset begin
mov cx,buffersize
mov al,246
rep stosb
;attempt to read the next block
mov dx,offset begin
mov cx,buffersize
mov ah,3fh
int 21h
jnc readfileok
mov ah,3eh
int 21h
mov activeflag,0 ;switch off new int 13h
;display error reading file...
mov si,offset loaderr
saveloadbad:call lodscrbot ;restore bottom of the screen
mov di,(12*80+25)*2 ;set position of text box
mov bl,1 ;copy one line
mov ah,31 ;attribute
mov dx,30
call dispbox
call beep
xor ah,ah
int 16h
call lodscrbot
jmp updloop
readfileok:
;display progress
mov si,offset loading
call displayprogress
mov cl,ah
xor ch,ch
shr cx,1 ;cx=ax/512, i.e. number of sectors\
jnz copysecs
;couldn't read the whole disk image,
;blank the rest of the image
clearendlp:mov si,offset begin+7*512
mov ax,bp
call writesector
inc bp
cmp bp,totalsecs
jb clearendlp
gotfile:;default display: no CRC info
mov si,offset nocrcinfomsg
mov di,offset loading+30*1+2
mov cx,26
rep movsb
cmp CRCFound,1
jne nocrcinfofound
mov di,offset FileCRC
mov si,offset CRC32
mov cx,4
repe cmpsb ;compare checksums
je crcmatches
mov si,offset crcbadmsg
copycrcmsg:mov di,offset loading+30*1+2
mov cx,26
rep movsb
xor ax,ax
mov si,offset loading
call displayprogress
call beep ;error beep
jmp closefile
crcmatches:mov si,offset crcokmsg
mov di,offset loading+30*1+2
mov cx,18
rep movsb
;insert the crc-32 number
mov di,offset loading+30*1+20
call insertcrc
nocrcinfofound:xor ax,ax
mov si,offset loading
call displayprogress
closefile:mov ah,3eh
int 21h
mov changelineflag,3
mov activeflag,1 ;automatically switch program on
mov popupbox[265],' ' ;remove modified indicator
;wait for a keypress
xor ah,ah
int 16h
;copy file opened over to savefile: for saving purposes
mov si,offset loadfile
mov di,offset savefile+48*1+2
push di
mov cx,44
rep movsb
;set edit offset to end of filename
pop si
chkeofnlp:lodsb
or al,al
jne chkeofnlp
dec si
mov editoff,si
;restore the screen
call lodscrbot
jmp updloop
nomemory:mov ah,3eh ;if insufficent memory to load diskimage,
int 21h ;close file
mov si,offset nomemstr ;and display error
jmp displerr
badfilec:mov ah,3eh
int 21h
badfile: ;display invalid file message
mov si,offset badimage
displerr:
mov di,(12*80+27)*2 ;set position of text box
mov bl,1 ;copy 1 line
mov ah,31 ;attribute
mov dx,27
call dispbox
call beep
xor ah,ah
int 16h
jmp loadfiledisplay
entnotfile:
;check for directory
cmp curlist,1
jne entnotdir
;update the directory: first find start of "*.*"
mov si,offset loadbox+46*1+2
getast1:lodsb
cmp al,"*"
jne getast1
dec si
mov di,si ;es:di points to start of "*.*"
;point to directory entry
mov ax,curent[2]
mov bx,12
mul bx
add ax,listoffset[2]
mov si,ax
;check for ".." (previous) directory
cmp [si],word ptr ".."
jne notprevdir
cmp [di-2],byte ptr ":"
je loadfiledisplay
mov [di],word ptr " "
mov [di+2],byte ptr " " ;remove the "*.*"
;now back up one dir
remdirlp:dec di
mov [di],byte ptr " "
cmp [di-1],byte ptr "\"
jne remdirlp
placeast:mov ax,".*"
stosw
mov ax,"*"
stosw
;reset directory and file lists
xor ax,ax
mov di,offset curent[2]
stosw
stosw
mov di,offset curoff[2]
stosw
stosw
jmp getloadlist
notprevdir: ;not "..", so copy directory
mov cx,12 ;max 12 characters
copydirlp2:lodsb
or al,al
je eodir
stosb
loop copydirlp2
eodir:mov al,"\"
stosb
jmp placeast
entnotdir:
;so must be enter pressed on drive list
;point to drive entry
;clear line first
mov di,offset loadbox+46*1+2
push di
mov cx,43
xor al,al
rep stosb
pop di
mov ax,curent
mov bx,12
mul bx
add ax,listoffset
add ax,5
mov si,ax
lodsb
mov ah,":"
stosw
mov dl,al
sub dl,"@"
mov al,"\"
stosb
mov si,di
mov ah,47h
int 21h ;got path, now get length
getendlp2:lodsb
or al,al
jnz getendlp2
cmp [si-2],byte ptr "\"
jne nottrailslash2
dec si
nottrailslash2:mov [si-1],byte ptr "\"
mov di,si
jmp placeast
lfnotent: ;other key pressed: do speedsearch
cmp al,"a"
jb notlower2
cmp al,"z"
ja notlower2
sub al," "
notlower2:cmp al," "
jbe loadfiledisplay
mov si,listoffset[bx]
cmp curlist,0
jne notdrivelist
add si,5 ;point to drive letter if drive list
notdrivelist:xor cx,cx ;current entry in cx
chklp:cmp [si],al ;check if first letter matches keystroke
jne notmatchss
mov curent[bx],cx
mov curoff[bx],cx
mov ax,listents[bx]
sub ax,12
cmp curoff[bx],ax
jle loadfiledisplay
or ax,ax
jns axpos
xor ax,ax
axpos:mov curoff[bx],ax
jmp loadfiledisplay
notmatchss:inc cx
add si,12
cmp [si],byte ptr " "
jne chklp
jmp loadfiledisplay
notf5:
;****************************************************************************
;*Check for f6 pressed: Save Image File
;****************************************************************************
cmp ax,4000h
jne notf6
cmp popupbox[3*80+27],byte ptr "-"
je notf6 ;saving not allowed for bad images
dispsaveloop:
;first clear number of bytes written
mov di,offset saving+16
mov cx,12
xor ax,ax
rep stosb
mov di,offset bytesrewr
stosw
stosw
;update display of save file type
mov di,offset savefile[3*48+16]
mov al,savetype
mov ah,11
mul ah
mov si,offset savetypes
add si,ax
mov cx,11
rep movsb
;update saving of CRC
mov di,offset savefile[3*48+43]
mov ax," n"
cmp saveCRC,1
je mustsaveCRC
mov ax,"ff"
mustsaveCRC:stosw
;display box with save message...
mov si,offset savefile
mov di,(11*80+16)*2 ;set position of text box
mov bl,5 ;copy all 5 lines
mov ah,95 ;attribute
mov es,scroff
saveboxmlp:mov cx,48
saveboxsublp:lodsb
stosw
loop saveboxsublp
add di,(80-48)*2
dec bl
jnz saveboxmlp
push cs
pop es
;put cursor in right place
mov dx,editoff
mov si,dx
sub dx,offset savefile+48*1+2-18
mov dh,12
add dl,cl
mov bh,curpage
mov ah,2
int 10h ;set cursor position
rereadkey:xor ah,ah
int 16h ;read the keyboard
cmp al,"a"
jb notlower
cmp al,"z"
ja notlower
sub al," " ;convert key to upper case
notlower:cmp ax,4100h
jne notf7 ;check for F7 pressed
inc savetype ;increment file type
cmp savetype,3
jb dispsaveloop
mov savetype,0
jmp dispsaveloop
notF7:cmp ax,4200h
jne notf8 ;check for F8 pressed
xor saveCRC,1 ;toggle saving of CRC
jmp dispsaveloop
notf8:cmp al,27
jne notexitsave ;esc pressed
mov ah,2
mov bh,curpage
mov dx,50*256
int 10h ;hide cursor again
call lodscrbot
jmp updloop
notexitsave:cmp al,8 ;backspace
jne notbksps
cmp si,offset savefile+48*1+2
jbe rereadkey
dobkspc:mov di,si
dec di
mov editoff,di
mov cx,offset savefile+48*1+2+44
sub cx,di
rep movsb
jmp dispsaveloop
notbksps:cmp ah,53h
jne notdelete ;delete
cmp [si],byte ptr " "
jbe rereadkey
inc si
jmp dobkspc
notdelete:cmp ah,47h
jne nothome ;home key
mov editoff,offset savefile+48*1+2
jmp dispsaveloop
nothome:cmp ah,4fh
jne notend ;end key
getendfnlp:lodsb
or al,al
jne getendfnlp
dec si
mov editoff,si
jmp dispsaveloop
notend:cmp ah,4bh
jne sfnotleftarrow ;check for left arrow
cmp si,offset savefile+48*1+2
jbe rereadkey
dec editoff
jmp dispsaveloop
sfnotleftarrow:cmp ah,4dh ;check for right arrow
jne sfnotrightarrow
cmp [si],byte ptr " "
jbe rereadkey
inc editoff
jmp dispsaveloop
sfnotrightarrow:cmp al,13 ;check for enter
je dosave
cmp al,32
jbe rereadkey
cmp savefile[48*1+2+43],byte ptr " "
ja rereadkey
inc editoff
mov cx,si
mov di,offset savefile+48*1+2+44
mov si,offset savefile+48*1+2+43
neg cx
add cx,di
std
rep movsb ;shift text
cld
inc si
mov [si],al
jmp dispsaveloop
dosave: ;restore display
mov ah,2
mov bh,curpage
mov dx,25*256
int 10h ;hide cursor again
call lodscrbot
;set up number of sectors to write
mov ax,totalsecs
mov savesecs,ax ;number of sectors to save=all
cmp savetype,0
je savemaxsize
;save as DCF or minimum size format, thus determine last used cluster
xor ax,ax
mov di,offset begin
call readsector ;get the boot sector
mov al,byte ptr ds:[offset begin+0dh]
mov byte ptr secsperclust,al ;get sectors per cluster
mov ax,word ptr ds:[offset begin+16h] ;get sectors per FAT in ax
shl ax,1 ;2 FATs
mov savesecs,ax ;save FATs
mov ax,word ptr ds:[offset begin+11h] ;get root directory entries
add ax,15 ;for weird number of dir ents. Can happen.
mov cl,4
shr ax,cl ;32 bytes per dir, 512 bytes per sector
add savesecs,ax ;save DIR as well
mov al,byte ptr ds:[offset begin+0eh] ;get number of reserved sectors
xor ah,ah
add savesecs,ax ;save reserved sectors (BOOT + ?)
;get number of FAT entries in bp
mov bp,totalsecs
sub bp,savesecs ;subtract reserved sectors
mov cl,byte ptr secsperclust
dec cl
shr bp,cl ;for 2 sectors per cluster
;now read first FAT (up to 4096 entries, 12-bit FAT assumed)
mov cx,buffersize/512 ;FAT should fit in 6K buffer
mov di,offset begin
getfatsec:call readsector
inc ax
loop getfatsec ;read the FAT
mov si,offset begin ;si points to start of FAT
xor di,di ;di=last non-zero FAT entry
xor dx,dx ;dx=current FAT entry
checkfatlp:lodsw
mov bx,ax
and ax,0000111111111111b ;keep lower 12 bits
jz zerofatent
mov di,dx
zerofatent:inc dx ;next fat entry
mov ah,bh
and ah,11110000b ;keep LS 4 bits
lodsb ;get MS 8 bits
mov cl,4
rol ax,cl ;rotate bits in position
or ax,ax
jz zerofatent2
mov di,dx
zerofatent2:inc dx ;next fat entry
cmp dx,bp
jb checkfatlp
mov ax,secsperclust
mul di
add savesecs,ax ;save used clusters
cmp savetype,1
jne notdcfformat
;dcf format requires rounding to the next track
mov ax,savesecs
mov bl,sectors
shl bl,1 ;align to head 0
xor bh,bh
push bx
dec bl
add ax,bx ;add spt-1 to total
pop bx
xor dx,dx
div bx ;get number of tracks
mul bx
mov savesecs,ax ;number of sectors to save
notdcfformat:
savemaxsize:
;check if file exists
mov dx,offset savefile+48*1+2
mov ax,3d00h
int 21h ;attempt to open
jc doesnotexist
mov bx,ax
mov ah,3eh
int 21h ;close the file
;prompt for overwrite
mov si,offset fileexists
mov ah,79
mov dx,27
mov bl,1
mov di,(12*80+26)*2
call dispbox
xor ah,ah
int 16h
call lodscrbot
and al,223
cmp al,"Y"
jne updloop
doesnotexist: ;attempt to create the file
mov dx,offset savefile+48*1+2
mov ah,3ch
xor cx,cx
int 21h
jc errorsave
mov bx,ax ;get the file handle in bx
;write the file in "buffersize" blocks
xor bp,bp ;number of sectors copied
getblock:mov cx,buffersize/512 ;max sectors to write per cycle
mov di,offset begin
mov si,di ;for crc updating
copysectlp:mov ax,bp
;read sector from XMS buffer
call readsector
;update the CRC counter if saving CRC
cmp savecrc,1
jne nocrccalc
push bx cx di
call CalcCRC32
pop di cx bx
nocrccalc:inc bp
cmp bp,savesecs
jae gotallsecs
loop copysectlp
gotallsecs:mov cx,di
mov dx,offset begin
sub cx,dx ;cx contains number of bytes to write
mov ah,40h
int 21h
jc errorsavec
cmp ax,cx
jne errorsavec
;display progress
mov si,offset saving
call displayprogress
cmp bp,savesecs
jb getblock
;default to no saving of CRC info
mov si,offset nocrcsavmsg
mov di,offset saving+30*1+2
mov cx,26
rep movsb
xor ax,ax
;check if CRC must be saved
cmp savecrc,1
jne notsavecrc
mov dx,offset CRCFootprint
mov cx,16 ;CRC info is 16 bytes
mov ah,40h
int 21h ;write CRC info
jc errorsavec
cmp ax,cx
jne errorsavec
mov si,offset crcsavmsg
mov di,offset saving+30*1+2
mov cx,18
rep movsb
;insert the crc-32 number
mov di,offset saving+30*1+20
call insertcrc
mov ax,16
notsavecrc:mov si,offset saving
call displayprogress
mov ah,3eh
int 21h ;close file
mov popupbox[265]," " ;indicate no modification to image
xor ah,ah
int 16h ;wait for key
call lodscrbot
jmp updloop
errorsavec:mov ah,3eh
int 21h ;close file
errorsave:mov si,offset saveerr
jmp saveloadbad
notf6:
;****************************************************************************
;*Check for F10 pressed: uninstall TI
;****************************************************************************
cmp ax,4400h
jne notf10pr
;first we have to check that the interrupts are still set
;directly to TI. Otherwise can't uninstall.
;check keyboard interrupt
mov ax,3516h
int 21h
cmp bx,offset newkeyint
jne nouninstall
mov bx,es
mov cx,cs
cmp bx,cx
jne nouninstall
;check int 28h
mov ax,3528h
int 21h
cmp bx,offset newint28h
jne nouninstall
mov bx,es
cmp bx,cx
jne nouninstall
;check int 13h
mov ax,3513h
int 21h
cmp bx,offset newint13h
jne nouninstall
mov bx,es
cmp bx,cx
jne nouninstall
;may uninstall: prompt user
mov si,offset uninstbox
push cs
pop es ;restore es
mov di,(12*80+24)*2 ;set position of text box
mov bl,2 ;do 2 lines
mov ah,47
mov dx,32
call dispbox
;read user's response
xor ah,ah
int 16h
call lodscrbot
and al,223
cmp al,"Y"
jne updloop
call lodscr
;free all the interrupts
;reset the old keyboard vector
mov dx,word ptr oldkeyint
mov ds,word ptr oldkeyint[2]
mov ax,2516h
int 21h
push cs
pop ds
;reset the old int 28h vector
mov dx,word ptr oldint28h
mov ds,word ptr oldint28h[2]
mov ax,2528h
int 21h
push cs
pop ds
;reset the old int 13h vector
mov dx,word ptr oldint13h
mov ds,word ptr oldint13h[2]
mov ax,2513h
int 21h
push cs
pop ds
;free the memory allocated to the program
mov ah,49h
int 21h
;free the xms allocated
call releasexms
mov ah,0dh
int 21h ;reset disk buffers
jmp exitpop ;exit the routine
nouninstall:push cs
pop es ;restore es
mov si,offset cannotuni
mov di,(12*80+24)*2 ;set position of text box
mov bl,2 ;do 2 lines
mov ah,79
mov dx,32
call dispbox
call beep
xor ah,ah
int 16h
call lodscrbot
jmp updloop
notf10pr:
;****************************************************************************
;*Check for ESC pressed: exit popup routine
;****************************************************************************
cmp al,27
jne notescpr
call lodscr
exitpop:cmp setmode,1
jne notsetmode
mov al,oldmode
xor ah,ah
or al,80h
int 10h ;set screen mode
;reset the old palette
mov di,offset begin ;palette is copied to es:di
mov dx,di
mov ax,cs:[xmsdesired] ;point to palette sectors
add ax,4 ;(address is (xmsdesired+4)*2)
add ax,ax
call readsector
inc ax
call readsector ;read the palette
mov ax,1012h
xor bx,bx
mov cx,256
int 10h ;reset the whole palette
notsetmode:
;reset cursor position
mov dx,oldcurpos
mov bh,oldpage
mov ah,2
int 10h
;reset the old int 24h vector
mov dx,word ptr oldint24h
mov ds,word ptr oldint24h[2]
mov ax,2524h
int 21h
pop es ds bp di si dx cx bx ax
mov cs:inroutine,0 ;ready for next call
ret
notescpr:
jmp updloop
;************************************************************************
;*Miscellaneous routines for POPUP routine
;************************************************************************
;bintodec
;converts number in dx:ax to string at es:di
;return: di points to next character
bintodec:push ax bx cx dx bp
xchg dx,bp
mov bx,10
mov cx,48
bintodec2:mov dh,ch
inc dh
and dh,3
jnz bintodec3
inc ch
mov dl,","
push dx
bintodec3:xchg bp,ax
xor dx,dx
div bx
xchg bp,ax
div bx
or dl,cl
inc ch
push dx
or bp,bp
jnz bintodec2
or ax,ax
jnz bintodec2
bintodec4:pop ax
stosb
dec ch
jnz bintodec4
pop bp dx cx bx ax
ret
;check for valid boot sector: returns spt in cl, total sectors in ax
; assumes boot sector loaded at cs:offset begin+buffersize-512
; returns ax=0 if invalid BS
checkboot:
cmp word ptr [offset begin+buffersize-512+0bh],512
jne badfilec2 ;must be 512 bytes per sector
cmp byte ptr [offset begin+buffersize-512+0dh],2
ja badfilec2 ;no more than 2 sectors per cluster
cmp byte ptr [offset begin+buffersize-512+0dh],0
je badfilec2 ;at least 1 sector per cluster
cmp byte ptr [offset begin+buffersize-512+10h],2
jne badfilec2 ;must have 2 FATs
cmp byte ptr [offset begin+buffersize-512+1ah],2
ja badfilec2 ;must have 2 heads or less
mov cl,byte ptr [offset begin+buffersize-512+18h] ;spt
cmp cl,8 ;sectors per track:
jb badfilec2 ;not less than 8
cmp cl,38
ja badfilec2 ;nor more than 38
mov ax,word ptr [offset begin+buffersize-512+13h] ;total secs per drive
cmp ax,6144 ;no more than 3M
ja badfilec2
cmp ax,320 ;minimum of 160k
jb badfilec2
ret
badfilec2:xor ax,ax
ret
;check for sufficient memory to load diskimage
;returns ax=0 if insufficient memory
checksize:
push bx
mov ax,cs:[xmsdesired]
add ax,ax ;ax contains total allocated memory in sectors
mov bx,word ptr [offset begin+buffersize-512+13h] ;total secs per drive
cmp ax,bx ;bx contains total disk size in sectors
jb checksiz2 ;if disksize>allocated memory,
pop bx
ret
checksiz2:
xor ax,ax ;error
pop bx
ret
;routine to update progress display during load/save
;if ax<256 prints 'OK' after number of bytes
displayprogress:add word ptr bytesrewr,ax
adc word ptr bytesrewr[2],0 ;add total bytes read
push bx ax
mov di,si
add di,16
mov ax,word ptr bytesrewr
mov dx,word ptr bytesrewr[2]
call bintodec
pop ax
push ax
or ah,ah
jnz notfileend
inc di
mov ax,"KO"
stosw
notfileend:mov di,(11*80+25)*2 ;set position of text box
mov bl,2 ;copy 1 line
mov ah,47 ;attribute
mov dx,30
call dispbox
pop ax bx
ret
;routine to display a text box on-screen
; top and bottom lines are automatically drawn
;dx=characters per row
;ah=attribute
;di=destination on-screen
;bl=number of lines (excluding top and bottom lines)
;si=start of box
dispbox:mov es,scroff
mov al,"É"
stosw
mov al,"Í"
mov cx,dx
sub cx,2
rep stosw
mov al,"»"
stosw
add di,160
sub di,dx
sub di,dx
pruninstlps:mov cx,dx
chlpus:lodsb
stosw
loop chlpus
add di,160
sub di,dx
sub di,dx
dec bl
jnz pruninstlps
mov al,"È"
stosw
mov al,"Í"
mov cx,dx
sub cx,2
rep stosw
mov al,"¼"
stosw
push cs
pop es
ret
;************************************************************************
;*Screen update routines for POPUP routine
;************************************************************************
;restore bottom half of display: copy from xms
lodscrbot:push ax
mov es,scroff
cmp setmode,1 ;was a new mode set?
jne oldmodeset
;in that case: keep bottom lines blank
mov di,6*80*2
mov cx,19*80
mov ax," "+7*256
rep stosw
jmp endlod
oldmodeset:mov di,512*2
mov ax,cs:[xmsdesired] ;point to lower 3k of screen backup
add ax,ax ;(address is xmsdesired*2+2)
add ax,2
mov cx,6 ;restore 3k in total
lodlp:call readsector
inc ax
loop lodlp
endlod:push cs
pop es ax
ret
;restore the whole display: copy from xms
lodscr:push ax
mov es,scroff
xor di,di
mov ax,cs:[xmsdesired] ;point to start of screen backup
add ax,ax ;(address is xmsdesired*2)
mov cx,8 ;restore 4k in total
jmp lodlp
;routine to update the popup screen (top 6 lines)
updatescreen:mov di,offset popupbox+181
mov ax," n"
cmp activeflag,1
je progison
mov ax,"ff"
progison:stosw
mov di,offset popupbox+203
mov al,substdrive
add al,"A"
stosb
mov di,offset popupbox+235
mov ax," n"
cmp writeprotect,1
je wpison
mov ax,"ff"
wpison:stosw
;check the boot sector: if OK allow writing of image
mov di,offset begin+buffersize-512
xor ax,ax
call readsector
call checkboot
mov totalsecs,ax
or ax,ax
mov ax,"--"
jz writenotallowed
mov sectors,cl
mov ax,"6F"
writenotallowed:mov di,offset popupbox+3*80+27
stosw
xor di,di
mov si,offset popupbox
mov ah,96+15 ;attribute in ah
mov dx,80
mov bl,4
jmp dispbox ;dispbox will do the 'ret'
;*******************************************************************
;*Audio output routines for popup
;*******************************************************************
;beeps
beep:mov bx,512
call startsound
mov bl,2
call delay
call stopsound
ret
;startsound: starts sound with frequency in bx (lowest allowed is 20)
startsound:cmp bx,20
jb endsstart
push ax
push dx ;save registers
mov al,10110110b ;channel 2, write LSB/MSB
out 43h,al
mov dx,18
mov ax,13532
div bx ;convert frequency to interval (1193180/freq)
out 42h,al ;write lsb of count interval
mov al,ah
out 42h,al ;write msb of count interval
in al,61h ;read 8255 port contents
or al,00000011b ;enable speaker and use channel 2
out 61h,al ;write 8255 port
pop dx
pop ax ;retrieve registers
endsstart:ret ;return to caller
;stopsound: puts speaker off
stopsound:push ax ;save ax
in al,61h ;read 8255 port contents
and al,11111100b ;disable speaker
out 61h,al ;write 8255 port
pop ax ;retrieve ax
ret ;return to caller
;delay: delays for bl clock ticks
delay:push ax cx ds
xor ax,ax
mov ds,ax ;point to BDA
delayloop:mov cl,ds:[46ch] ;get timer LSB
waitforchange:cmp ds:[46ch],cl ;wait for it to change
je waitforchange
dec bl ;decrease delay counter
jnz delayloop ;delay bl timer ticks
pop ds cx ax
ret ;return to caller
;****************************************************************************
;* Routines to calculate and update 32-bit CRC
;****************************************************************************
CRCFound db 0 ;1=CRC found in file being loaded
FileCRC dd 0 ;CRC found in last file loaded
SaveCRC db 1 ;1=Must save CRC info
CRCFootprint db "TImageCRC32=" ;first 12 of 16 byte CRC trailer
CRC32 dd ? ;current CRC value: last 4 bytes of trailer
;CRC Type used for error checking:
; StdCRC32 = "Standard" PC CRC32 algorithm, used by PKZIP, etc.
; MPEG32S = MPEG CRC32. Used in compressed video streams. Small lookup table.
; MPEG32L = MPEG CRC32. As above, but with larger lookup table (faster).
;To keep TI compatible, I strongly suggest keeping the CRC method set
;to StdCRC32.
StdCRC32 = 1 ;1=use CRC type
MPEG32S = 0
MPEG32L = 0
;Standard CRC32 algorithm (used by PKZIP, Ethernet, FDDI, etc.)
if StdCRC32
CRCLookup dd 000000000h,077073096h,0EE0E612Ch,0990951BAh
dd 0076DC419h,0706AF48Fh,0E963A535h,09E6495A3h
dd 00EDB8832h,079DCB8A4h,0E0D5E91Eh,097D2D988h
dd 009B64C2Bh,07EB17CBDh,0E7B82D07h,090BF1D91h
dd 01DB71064h,06AB020F2h,0F3B97148h,084BE41DEh
dd 01ADAD47Dh,06DDDE4EBh,0F4D4B551h,083D385C7h
dd 0136C9856h,0646BA8C0h,0FD62F97Ah,08A65C9ECh
dd 014015C4Fh,063066CD9h,0FA0F3D63h,08D080DF5h
dd 03B6E20C8h,04C69105Eh,0D56041E4h,0A2677172h
dd 03C03E4D1h,04B04D447h,0D20D85FDh,0A50AB56Bh
dd 035B5A8FAh,042B2986Ch,0DBBBC9D6h,0ACBCF940h
dd 032D86CE3h,045DF5C75h,0DCD60DCFh,0ABD13D59h
dd 026D930ACh,051DE003Ah,0C8D75180h,0BFD06116h
dd 021B4F4B5h,056B3C423h,0CFBA9599h,0B8BDA50Fh
dd 02802B89Eh,05F058808h,0C60CD9B2h,0B10BE924h
dd 02F6F7C87h,058684C11h,0C1611DABh,0B6662D3Dh
dd 076DC4190h,001DB7106h,098D220BCh,0EFD5102Ah
dd 071B18589h,006B6B51Fh,09FBFE4A5h,0E8B8D433h
dd 07807C9A2h,00F00F934h,09609A88Eh,0E10E9818h
dd 07F6A0DBBh,0086D3D2Dh,091646C97h,0E6635C01h
dd 06B6B51F4h,01C6C6162h,0856530D8h,0F262004Eh
dd 06C0695EDh,01B01A57Bh,08208F4C1h,0F50FC457h
dd 065B0D9C6h,012B7E950h,08BBEB8EAh,0FCB9887Ch
dd 062DD1DDFh,015DA2D49h,08CD37CF3h,0FBD44C65h
dd 04DB26158h,03AB551CEh,0A3BC0074h,0D4BB30E2h
dd 04ADFA541h,03DD895D7h,0A4D1C46Dh,0D3D6F4FBh
dd 04369E96Ah,0346ED9FCh,0AD678846h,0DA60B8D0h
dd 044042D73h,033031DE5h,0AA0A4C5Fh,0DD0D7CC9h
dd 05005713Ch,0270241AAh,0BE0B1010h,0C90C2086h
dd 05768B525h,0206F85B3h,0B966D409h,0CE61E49Fh
dd 05EDEF90Eh,029D9C998h,0B0D09822h,0C7D7A8B4h
dd 059B33D17h,02EB40D81h,0B7BD5C3Bh,0C0BA6CADh
dd 0EDB88320h,09ABFB3B6h,003B6E20Ch,074B1D29Ah
dd 0EAD54739h,09DD277AFh,004DB2615h,073DC1683h
dd 0E3630B12h,094643B84h,00D6D6A3Eh,07A6A5AA8h
dd 0E40ECF0Bh,09309FF9Dh,00A00AE27h,07D079EB1h
dd 0F00F9344h,08708A3D2h,01E01F268h,06906C2FEh
dd 0F762575Dh,0806567CBh,0196C3671h,06E6B06E7h
dd 0FED41B76h,089D32BE0h,010DA7A5Ah,067DD4ACCh
dd 0F9B9DF6Fh,08EBEEFF9h,017B7BE43h,060B08ED5h
dd 0D6D6A3E8h,0A1D1937Eh,038D8C2C4h,04FDFF252h
dd 0D1BB67F1h,0A6BC5767h,03FB506DDh,048B2364Bh
dd 0D80D2BDAh,0AF0A1B4Ch,036034AF6h,041047A60h
dd 0DF60EFC3h,0A867DF55h,0316E8EEFh,04669BE79h
dd 0CB61B38Ch,0BC66831Ah,0256FD2A0h,05268E236h
dd 0CC0C7795h,0BB0B4703h,0220216B9h,05505262Fh
dd 0C5BA3BBEh,0B2BD0B28h,02BB45A92h,05CB36A04h
dd 0C2D7FFA7h,0B5D0CF31h,02CD99E8Bh,05BDEAE1Dh
dd 09B64C2B0h,0EC63F226h,0756AA39Ch,0026D930Ah
dd 09C0906A9h,0EB0E363Fh,072076785h,005005713h
dd 095BF4A82h,0E2B87A14h,07BB12BAEh,00CB61B38h
dd 092D28E9Bh,0E5D5BE0Dh,07CDCEFB7h,00BDBDF21h
dd 086D3D2D4h,0F1D4E242h,068DDB3F8h,01FDA836Eh
dd 081BE16CDh,0F6B9265Bh,06FB077E1h,018B74777h
dd 088085AE6h,0FF0F6A70h,066063BCAh,011010B5Ch
dd 08F659EFFh,0F862AE69h,0616BFFD3h,0166CCF45h
dd 0A00AE278h,0D70DD2EEh,04E048354h,03903B3C2h
dd 0A7672661h,0D06016F7h,04969474Dh,03E6E77DBh
dd 0AED16A4Ah,0D9D65ADCh,040DF0B66h,037D83BF0h
dd 0A9BCAE53h,0DEBB9EC5h,047B2CF7Fh,030B5FFE9h
dd 0BDBDF21Ch,0CABAC28Ah,053B39330h,024B4A3A6h
dd 0BAD03605h,0CDD70693h,054DE5729h,023D967BFh
dd 0B3667A2Eh,0C4614AB8h,05D681B02h,02A6F2B94h
dd 0B40BBE37h,0C30C8EA1h,05A05DF1Bh,02D02EF8Dh
;Routine to calculate the 32-bit CRC value
;Calculates CRC for 512 byte block at ds:si
;destroys ax bx cx dx di, increments si
CalcCRC32:mov di,256 ;do 256 words
mov dx,word ptr crc32[2]
mov cx,word ptr crc32 ;keep crc32 in dx:cx
CalcCRClp:lodsw
xor al,cl ;lowbyte xor input
mov bl,al
xor bh,bh
shl bx,2 ;convert to entry in table
;shift right 8 bits and xor with value in lookup table
xor dx,word ptr CRCLookup[BX+1]
xor ch,byte ptr CRCLookup[BX]
mov cl,byte ptr CRCLookup[BX+3]
;do next byte
xor ah,ch ;lowbyte xor input
mov bl,ah
xor bh,bh
shl bx,2 ;convert to entry in table
;shift right 8 bits and xor with value in lookup table
xor dx,word ptr CRCLookup[BX]
xor ch,ch
xor cx,word ptr CRCLookup[BX+2]
;words are now swapped, swap them back
xchg cx,dx
dec di
jnz CalcCRClp
mov word ptr crc32[2],dx
mov word ptr crc32,cx
ret
endif
;MPEG32 CRC, using short lookup table (slow, but saves 1K memory)
if MPEG32S
;16 entry table uses almost 1k less memory, but is half as fast
CRCLookup dd 00000000h,04c11db7h,09823b6eh,0d4326d9h,130476dch,17c56b6bh
dd 1a864db2h,1e475005h,2608edb8h,22c9f00fh,2f8ad6d6h,2b4bcb61h
dd 350c9b64h,31cd86d3h,3c8ea00ah,384fbdbdh
;Routine to update 'CRC32' for 512 byte block at DS:SI
; destroys ax bx cx dx, increments si
CalcCRC32:mov cx,512 ;do 512 bytes
CalcCRClp:lodsb
mov dl,al
shr al,4 ;process high nibble
call CalcCRCNibble
mov al,dl
and al,1111b ;keep low nibble
call CalcCRCNibble
loop CalcCRClp
ret
;Routine to do partial update of 'CRC32' from 4-bit nibble in al
; high four bits in al must be 0
; destroys: ax bx
CalcCRCNibble:mov ah,4 ;shift CRC32 left four positions
xor bx,bx ;bx starts off cleared
shllp:shl word ptr CRC32,1
rcl word ptr CRC32[2],1
rcl bl,1
dec ah
jnz shllp
;four bits shifted out will be in bx
xor bl,al ;xor input with top 4 bits of CRC32
shl bl,2 ;multiply by 4
mov ax,word ptr CRCLookup[BX]
xor word ptr CRC32,ax
mov ax,word ptr CRCLookup[BX+2]
xor word ptr CRC32[2],ax ;xor calculated value
ret
endif
;MPEG32 CRC, uses larger lookup table as previous
if MPEG32L
CRCLookup dd 000000000h,004C11DB7h,009823B6Eh,00D4326D9h
dd 0130476DCh,017C56B6Bh,01A864DB2h,01E475005h
dd 02608EDB8h,022C9F00Fh,02F8AD6D6h,02B4BCB61h
dd 0350C9B64h,031CD86D3h,03C8EA00Ah,0384FBDBDh
dd 04C11DB70h,048D0C6C7h,04593E01Eh,04152FDA9h
dd 05F15ADACh,05BD4B01Bh,0569796C2h,052568B75h
dd 06A1936C8h,06ED82B7Fh,0639B0DA6h,0675A1011h
dd 0791D4014h,07DDC5DA3h,0709F7B7Ah,0745E66CDh
dd 09823B6E0h,09CE2AB57h,091A18D8Eh,095609039h
dd 08B27C03Ch,08FE6DD8Bh,082A5FB52h,08664E6E5h
dd 0BE2B5B58h,0BAEA46EFh,0B7A96036h,0B3687D81h
dd 0AD2F2D84h,0A9EE3033h,0A4AD16EAh,0A06C0B5Dh
dd 0D4326D90h,0D0F37027h,0DDB056FEh,0D9714B49h
dd 0C7361B4Ch,0C3F706FBh,0CEB42022h,0CA753D95h
dd 0F23A8028h,0F6FB9D9Fh,0FBB8BB46h,0FF79A6F1h
dd 0E13EF6F4h,0E5FFEB43h,0E8BCCD9Ah,0EC7DD02Dh
dd 034867077h,030476DC0h,03D044B19h,039C556AEh
dd 0278206ABh,023431B1Ch,02E003DC5h,02AC12072h
dd 0128E9DCFh,0164F8078h,01B0CA6A1h,01FCDBB16h
dd 0018AEB13h,0054BF6A4h,00808D07Dh,00CC9CDCAh
dd 07897AB07h,07C56B6B0h,071159069h,075D48DDEh
dd 06B93DDDBh,06F52C06Ch,06211E6B5h,066D0FB02h
dd 05E9F46BFh,05A5E5B08h,0571D7DD1h,053DC6066h
dd 04D9B3063h,0495A2DD4h,044190B0Dh,040D816BAh
dd 0ACA5C697h,0A864DB20h,0A527FDF9h,0A1E6E04Eh
dd 0BFA1B04Bh,0BB60ADFCh,0B6238B25h,0B2E29692h
dd 08AAD2B2Fh,08E6C3698h,0832F1041h,087EE0DF6h
dd 099A95DF3h,09D684044h,0902B669Dh,094EA7B2Ah
dd 0E0B41DE7h,0E4750050h,0E9362689h,0EDF73B3Eh
dd 0F3B06B3Bh,0F771768Ch,0FA325055h,0FEF34DE2h
dd 0C6BCF05Fh,0C27DEDE8h,0CF3ECB31h,0CBFFD686h
dd 0D5B88683h,0D1799B34h,0DC3ABDEDh,0D8FBA05Ah
dd 0690CE0EEh,06DCDFD59h,0608EDB80h,0644FC637h
dd 07A089632h,07EC98B85h,0738AAD5Ch,0774BB0EBh
dd 04F040D56h,04BC510E1h,046863638h,042472B8Fh
dd 05C007B8Ah,058C1663Dh,0558240E4h,051435D53h
dd 0251D3B9Eh,021DC2629h,02C9F00F0h,0285E1D47h
dd 036194D42h,032D850F5h,03F9B762Ch,03B5A6B9Bh
dd 00315D626h,007D4CB91h,00A97ED48h,00E56F0FFh
dd 01011A0FAh,014D0BD4Dh,019939B94h,01D528623h
dd 0F12F560Eh,0F5EE4BB9h,0F8AD6D60h,0FC6C70D7h
dd 0E22B20D2h,0E6EA3D65h,0EBA91BBCh,0EF68060Bh
dd 0D727BBB6h,0D3E6A601h,0DEA580D8h,0DA649D6Fh
dd 0C423CD6Ah,0C0E2D0DDh,0CDA1F604h,0C960EBB3h
dd 0BD3E8D7Eh,0B9FF90C9h,0B4BCB610h,0B07DABA7h
dd 0AE3AFBA2h,0AAFBE615h,0A7B8C0CCh,0A379DD7Bh
dd 09B3660C6h,09FF77D71h,092B45BA8h,09675461Fh
dd 08832161Ah,08CF30BADh,081B02D74h,0857130C3h
dd 05D8A9099h,0594B8D2Eh,05408ABF7h,050C9B640h
dd 04E8EE645h,04A4FFBF2h,0470CDD2Bh,043CDC09Ch
dd 07B827D21h,07F436096h,07200464Fh,076C15BF8h
dd 068860BFDh,06C47164Ah,061043093h,065C52D24h
dd 0119B4BE9h,0155A565Eh,018197087h,01CD86D30h
dd 0029F3D35h,0065E2082h,00B1D065Bh,00FDC1BECh
dd 03793A651h,03352BBE6h,03E119D3Fh,03AD08088h
dd 02497D08Dh,02056CD3Ah,02D15EBE3h,029D4F654h
dd 0C5A92679h,0C1683BCEh,0CC2B1D17h,0C8EA00A0h
dd 0D6AD50A5h,0D26C4D12h,0DF2F6BCBh,0DBEE767Ch
dd 0E3A1CBC1h,0E760D676h,0EA23F0AFh,0EEE2ED18h
dd 0F0A5BD1Dh,0F464A0AAh,0F9278673h,0FDE69BC4h
dd 089B8FD09h,08D79E0BEh,0803AC667h,084FBDBD0h
dd 09ABC8BD5h,09E7D9662h,0933EB0BBh,097FFAD0Ch
dd 0AFB010B1h,0AB710D06h,0A6322BDFh,0A2F33668h
dd 0BCB4666Dh,0B8757BDAh,0B5365D03h,0B1F740B4h
;Routine to calculate the 32-bit CRC value
;Calculates CRC for 512 byte block at ds:si
;destroys ax bx cx, increments si
CalcCRC32:mov cx,512 ;do 512 bytes
CalcCRClp:mov bl,[si]
xor bh,bh
inc si
xor bl,byte ptr crc32[3]
shl bx,2 ;convert to entry in table
mov ax,word ptr crc32[1]
xor ax,word ptr CRCLookup[BX+2]
mov word ptr crc32[2],ax
mov ah,byte ptr crc32
xor al,al
xor ax,word ptr CRCLookup[BX]
mov word ptr crc32,ax
loop CalcCRClp
ret
endif
;inserts the CRC string at es:di: converts CRC32 into 8-digit hex string
InsertCRC:mov si,offset crc32[3]
mov cx,4+4*256 ;do four bytes
insertlp:mov al,[si]
dec si
xor ah,ah
ror ax,cl
ror ah,cl ;separate digits
add ax,"00"
cmp al,"9"
jna alokhex
add al,"A"-"0"-10
alokhex:cmp ah,"9"
jna ahokhex
add ah,"A"-"0"-10
ahokhex:stosw ;store 2 digits
dec ch
jnz insertlp ;do next digit
ret
;****************************************************************************
;****************************************************************************
;* New interrupt handlers
;****************************************************************************
;****************************************************************************
;ds not assumed to point to cs anymore
assume cs:cseg,ds:nothing,es:nothing,ss:nothing
;*****************************************************************************
;*new BIOS keyboard interrupt 16H: checks for ctrl-alt-t pressed
;*****************************************************************************
oldkeyint dd 0 ;dword pointer to old BIOS keyboard int.
newkeyint:cmp inroutine,1
je nonewkey
mov function,ah
cmp ah,1
jbe newkey
cmp ah,10h
je newkey
cmp ah,11h
je newkey
nonewkey:jmp oldkeyint
newkey:pushf
call oldkeyint
pushf
cmp ax,1400h
jne notaltt
test function,1
jz notcheckkey
pop ax
test al,1000000b
push ax
jnz notaltt ;is ctrl-alt-t available in buffer?
mov ah,function
dec ah
pushf
call oldkeyint ;read the key
notcheckkey:push ds si
lds si,indos
cmp [si],word ptr 0 ;DOS must not be busy & no critical error
pop si ds
jnz isaltt_indos
call popup
;redo call
popf
mov ah,function
jmp oldkeyint
isaltt_indos: ;control-alt-t pressed, but still in DOS
mov wait28h,1 ;wait for int 28h
popf
mov ah,function
test ah,1
jnz nonewkey
xor ax,ax ;character with scancode 0, ascii 0 pressed
iret
notaltt:popf
retf 2 ;return to caller and clear stack
;*****************************************************************************
;*new int 24h: DOS critical error handler -> set during pop-up routine
;* Prevents program from aborting on disk not ready errors, etc.
;*****************************************************************************
oldint24h dd 0 ;dword pointer to old critical error handler
newint24h:
;force fail on all errors
mov al,3
iret
;*****************************************************************************
;*new int 28h: DOS idle interrupt
;*****************************************************************************
oldint28h dd 0 ;dword pointer to old int 28h handler
newint28h:cmp wait28h,1
jne notaltpp ;must be waiting for interrupt
cmp inroutine,1
je notaltpp ;must not be in routine already
call popup
notaltpp:jmp oldint28h
;*****************************************************************************
;*New interrupt 13h handler
;*****************************************************************************
buffersize = 12*512 ;buffer size for read and write functions,
;as well as other miscellaneous functions
;(MINIMUM is 6K, since this is the max size of
; a 12-bit FAT - required for .DCF saving)
sectors db 0 ;sectors per track of last image
totalsecs dw 0 ;total number of sectors on disk
oldint13h dd 0 ;vector to old int 13h
changelineflag db 00000000b ;bit 0=1, chg A:; bit 1=1, chg B:
writeprotect db 0 ;1=image is write protected
;NB!! NOTE!! drive has to be reset by DOS if 2 vars below are changed: changeline problems
substdrive db 0 ;floppy drive number to use for substitution, either 0 or 1
activeflag db 0 ;1=floppy is ignored and image is used for drive
;Below is the 11 byte DBT that is returned for INT 13h, service 18h
dbtsteprate db 0afh
dbtheadload db 2
dbtmotor db 25
dbtsecsize db 2
dbtspt db 0 ;sectors per track set by routine
dbtigap db 1bh
dbtdata db 0ffh
dbtgap db 06ch
dbtfill db 0f6h
dbtheadtime db 0fh
dbtmotor2 db 8
;The new interrupt 13h handler
newint13h:
cmp inroutine,1
jne mayaccess ;accessing floppies during pop-up not allowed
cmp dl,2
jae mayaccess ;non-floppy access OK
cmp ah,1ah
ja mayaccess ;functions above 1ah OK
cmp ah,1
je mayaccess ;function 1 ok
mov ax,8000h ;not ready error
sti
stc ;set carry flag
retf 2
mayaccess:
;check for install request
cmp ax,0ffffh
jne notinstreq
cmp dx,"TI"
jne notinstreq
mov ax,"TI" ;ID string in ax
mov bx,101h ;major version in bh, minor in bl
iret
notinstreq:
;handle a 'get changeline status' request
;sometimes a disk change have to be reported even though
;the program is not active -> after a switch from on to off for example
cmp ah,16h
jne notchangeline
push ax cx
mov ah,1
mov cl,dl
shl ah,cl
test changelineflag,ah
jz nochgfake
xor changelineflag,ah
pop cx ax
mov ah,1 ;report a fake disk change
sti
stc
retf 2
nochgfake:pop cx ax
cmp dl,substdrive
jne nonewint
cmp activeflag,1
jne nonewint
xor ah,ah ;no disk change
sti
clc
retf 2
notchangeline:
cmp activeflag,1
jne nonewint ;program must be active for other functions
;handle drive status request
cmp ah,1
jne notstatus
xor al,al ;status is all OK
sti
retf 2
notstatus:
;all subsequent functions have dl as the drive number
cmp dl,substdrive
jne nonewint
;handle drive reset request
or ah,ah
jnz notdrivereset
xor ah,ah ;reset went OK
sti
retf 2
notdrivereset:
;handle a sector read request
cmp ah,2
jne notreadreq
pushf
push ax bx cx dx di
cld
mov di,bx ;es:di points to buffer
mov bl,al ;bl contains number of sectors to read
shl ch,1 ;2 heads per cylinder
add ch,dh ;add head number
mov al,sectors ;sectors per track
mul ch
xor ch,ch
dec cl
add ax,cx ;ax contains sector number
readlp13:or bl,bl
jz endofread
call readsector
inc ax
dec bl
jmp readlp13
endofread:pop di dx cx bx ax
popf
sti
xor ah,ah
retf 2
notreadreq:
;handle a sector write request
cmp ah,3
jne notwritereq
cmp writeprotect,1
jne okwrite
wperr:mov ax,0300h ;write protect error
sti
stc ;set carry flag
retf 2
okwrite:
pushf
push ax bx cx dx si ds
cld
mov si,bx
push es
pop ds ;ds:si points to buffer
mov bl,al ;bl contains number of sectors to read
shl ch,1 ;2 heads per cylinder
add ch,dh ;add head number
mov al,sectors ;sectors per track
mul ch
xor ch,ch
dec cl
add ax,cx ;ax contains sector number
writelp13:or bl,bl
jz endofwrite
call writesector
inc ax
dec bl
jmp writelp13
endofwrite:
mov popupbox[265],"*" ;indicate modification to image
pop ds si dx cx bx ax
popf
xor ah,ah
sti
retf 2
notwritereq:
;handle a sector verify request
cmp ah,4
jne notverifysecs
returnok:xor ah,ah ;everything went OK
sti
retf 2
notverifysecs:
cmp ah,17h ;set media type request
je returnok
;handle format request
cmp ah,7
ja notformat
cmp writeprotect,1
je wperr ;write protect?
mov ah,dbtspt
mov sectors,ah ;set spt equal to that set by service 18h
mov popupbox[265],"*" ;indicate modification to image
xor ah,ah
sti
retf 2
notformat:
;handle 'set media type for format' request
cmp ah,18h
jne notformtype
mov dbtspt,cl
mov di,offset dbtsteprate
push cs
pop es
jmp returnok
notformtype:
;handle a 'is drive ready?' & recalibrate requests
cmp ah,10h
jb notdrivreadyrecal
cmp ah,11h
ja notdrivreadyrecal
xor ah,ah ;drive is ready/recalibrated
sti
retf 2
notdrivreadyrecal:
nonewint:jmp oldint13h
;****************************************************************************
;****************************************************************************
;* XMS MEMORY HANDLING ROUTINES: RESIDENT PART
;****************************************************************************
;****************************************************************************
xmskbytes dw 0 ;kilobytes of extended memory
xmshandle dw 0
xmscontrol dd 0
xmsdesired dw 3067 ;desired allocated memory in kbytes
emread dd 512 ;number of bytes to move
emr2 dw 0 ;copy xmshandle here
emr3 dd 0 ;32-bit offset
emr4 dw 0
emr5 dd 0
;extended memory write structure
emwrite dd 512 ;number of bytes to move
emw2 dw 0
emw3 dd 0
emw4 dw 0 ;copy xmshandle here
emw5 dd 0 ;32-bit offset
;*******************************************************************************
;*readsector: reads sector from image (number in ax) to es:di and advances di
;*******************************************************************************
readsector:push bx ax ds si cs
pop ds
mov si,offset emread
shl ax,1
mov word ptr ds:[offset emr3+1],ax
mov word ptr ds:[offset emr5],di
mov word ptr ds:[offset emr5+2],es
mov ah,0bh
call xmscontrol
;check for error
pop si ds ax bx
add di,512
ret
;*******************************************************************************
;*writesector: writes sector to image (number in ax) from ds:si and advances si
;*******************************************************************************
writesector:push ax ds si bx
shl ax,1
mov word ptr cs:[offset emw5+1],ax
mov word ptr cs:[offset emw3],si
mov word ptr cs:[offset emw3+2],ds
mov ah,0bh
mov si,offset emwrite
push cs
pop ds
call xmscontrol
;check for error
pop bx si ds ax
add si,512
ret
;*******************************************************************************
;*routine to free XMS memory
;*******************************************************************************
releasexms:cmp xmskbytes,0
je skipxmsdealloc
mov ah,0ah
mov dx,xmshandle
call xmscontrol
skipxmsdealloc:ret
;****************************************************************************
;****************************************************************************
;*Start of installation procedure, this part does not go resident
;****************************************************************************
;****************************************************************************
;ds and es always assumed to be same as cs
assume cs:cseg,ds:cseg,es:nothing,ss:nothing
begin:cld ;clear direction flag
;display entry message
mov dx,offset mainmsg
mov ah,9
int 21h
;check command line
cmp ds:[80h],byte ptr 0
je nothelp
mov ax,'1/' ;if option /1
cmp ax,ds:[82h]
jne commln2
mov ax,1019 ;allocate 1M XMS
mov bx,' 1'
jmp setpointer
commln2:
mov ax,'2/' ;if option /2
cmp ax,ds:[82h]
jne help
mov ax,2043 ;allocate 2M XMS
mov bx,'s2'
setpointer:
mov cs:[xmsdesired],ax ;set total memory to allocate
mov [totmem],bl ;set total memory on instalation message
mov [restmem],bh
jmp nothelp
help:
mov dx,offset helpmsg ;display help if command line option not /1
mov ah,9 ;or /2
int 21h
mov dx,offset bottom
mov ah,9
int 21h
mov ax,4c03h
int 21h
nothelp:
;get current path
mov di,offset loadbox+1*46+2
mov ah,19h
int 21h
add al,"A"
cmp al,"C"
jnb notfloppydrive
mov al,"C"
notfloppydrive:mov ah,":"
stosw
mov dl,al
sub dl,"@"
mov al,"\"
stosb
mov si,di
mov ah,47h
int 21h ;got path, now get length
getendlp:lodsb
or al,al
jnz getendlp
cmp [si-2],byte ptr "\"
jne nottrailslash
dec si
nottrailslash:mov [si-1],word ptr "*\"
mov [si+1],word ptr "*."
xor al,al
mov [si+3],al
;copy path to save file box
mov cx,si
mov si,offset loadbox+1*46+2
sub cx,si
mov di,offset savefile+1*48+2
rep movsb
mov editoff,di ;set edit offset
stosb
mov savefile[1*48+2+44],al ;ensure max string length is 44
;Drive B: may only be accessed if it is a physical drive
int 11h
test al,11000000b ;check number of FDDs
jnz bexists
mov maytoggledrive,0
mov word ptr popupbox[80*2+27],"--"
bexists:
;set up current floppy drive (mainly for single FDD systems)
xor ax,ax
mov es,ax
mov al,es:[504]
and al,1 ;in case DOS is confused
mov substdrive,al
push cs
pop es
;check if TI is already installed
mov ax,0ffffh
mov dx,"TI"
int 13h
cmp ax,"TI"
jne notinstyet
mov dx,offset alrinst
mov ah,9
int 21h
mov dx,offset bottom
int 21h
call beep
mov ax,4c02h
int 21h
notinstyet:
;attempt to allocate nM+5K XMS (n is defined by command line: 1M,2M or 3M)
call allocmem
mov ax,xmskbytes
mov bx,cs:[xmsdesired]
add bx,5
cmp ax,bx
jnb enoughmem
mov ah,9
mov dx,offset memerr
int 21h
mov dx,offset bottom
int 21h
call beep
error:call releasexms
mov ax,4c01h
int 21h
enoughmem:
;clear first 32k of XMS: make sure boot & fat is wiped
mov di,offset mainmsg
mov cx,512
mov al,246
rep stosb
xor ax,ax
clearseclp:mov si,offset mainmsg
call writesector
inc ax
cmp ax,64
jb clearseclp
;set up new keyboard interrupt
mov ax,3516h
int 21h
mov word ptr oldkeyint,bx
mov word ptr oldkeyint[2],es
mov dx,offset newkeyint
mov ah,25h
int 21h
;set up new int 28h
mov ax,3528h
int 21h
mov word ptr oldint28h,bx
mov word ptr oldint28h[2],es
mov dx,offset newint28h
mov ah,25h
int 21h
;set up interrupt 13h vector
mov ax,3513h
int 21h
mov word ptr oldint13h,bx
mov word ptr oldint13h[2],es
mov dx,offset newint13h
mov ah,25h
int 21h
;get pointer to "INDOS" flag
mov ah,34h
int 21h
dec bx ;point to critical flag
mov word ptr indos,bx
mov word ptr indos[2],es
;release memory owned by the program's copy of the environment strings
mov ax,ds:[2ch] ;get segment of environment
mov es,ax
mov ah,49h
int 21h
;reset disks
mov ah,0dh
int 21h ;reset DOS disk buffers
;display installed message
mov ah,9
mov dx,offset memmsg
int 21h
mov ah,9
mov dx,offset okmsg
int 21h
mov dx,offset bottom
int 21h
;go resident: keep program up to 'begin'+buffersize
mov dx,offset begin+buffersize+15
shr dx,4 ;convert to paragraphs
mov ax,3100h
int 21h ;go resident
;*******************************************************************************
;*routine to allocate nM+5k of XMS:
;* nM for the fake drive
;* 4k for the screen save space
;* 1k for the palette
;*******************************************************************************
allocmem:mov xmskbytes,0
mov ax,4300h
int 2fh
cmp al,80h
jne noxms
mov ax,4310h
int 2fh
mov word ptr [xmscontrol],bx
mov word ptr [xmscontrol+2],es ;got controller address
push cs
pop es
mov ah,8
call xmscontrol
cmp bl,0a0h
je noxms
or ax,ax
jz noxms
;we want nM+5K XMS (n is defined by command line: 1M,2M or 3M)
mov ax,cs:[xmsdesired]
add ax,5
mov dx,ax
mov xmskbytes,ax
mov ah,9
call xmscontrol
cmp ax,1
je xmsalloc
mov xmskbytes,0
jmp noxms
xmsalloc:mov xmshandle,dx
noxms:mov ax,xmshandle
mov emr2,ax
mov emw4,ax
ret
;*******************************************************************************
;*Installation messages
;*******************************************************************************
mainmsg db "ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»",13
db "º TurboImage v1.01e - Access disk image as a drive - Pierre J. le Riche 1997 º",13
db "ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ",13,"$"
helpmsg db "º This program will read DCF,WIMAGE,ULTRACOPY,VGACOPY,DISKDUPE,etc. disk image º",13
db "º files (& many others) and make them available as a 'phantom' floppy drive... º",13
db "º Make disk images of your original install disks, put the disks away, and use º",13
db "º TI to install directly from the images - 'hotswapping' images as the install º",13
db "º program prompts for the next installation disk. It's safe and much faster. º",13,"$"
memerr db "º Insufficient XMS memory available.Try using option /1 or /2 or free 3Mb XMS. º",13,"$"
alrinst db "ºTurboImage is already installed.Press Ctrl-Alt-T to display available options.º",13,"$"
memmsg db "º TurboImage allocated a total of "
totmem db "3Mbyte"
restmem db "s of extended memory to use. º",13,"$"
okmsg db "º TurboImage is now resident. Press Ctrl-Alt-T at any time to access the menu. º",13,"$"
bottom db "ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ$"
cseg ends ;end of code segment
end start ;set code entry point for .com file
----------------------------------------------------------------------
This message was sent to you because you are currently subscribed to
the floppertalk mailing list. To unsubscribe, send mail to
minordomo@oldskool.org with a subject of 'unsubscribe floppertalk'