; _____________________________________________
; | |
; | Project: APPLER |
; | File: FLOPPY.INC |
; | Compiler: 16-bit TASM (2.5) |
; | |
; | Subject: Floppy Disk Emulation |
; | |
; | Author: Alexander Patalenski |
; |_____________________________________________|
; This file is included in EMULATE.ASM
;-------------- Floppy emulation entries ---------------------------------------
assume CS:Emulate,DS:Apple,ES:Video,SS:Data
UseNextFreeSpace
C0E0r:
C0E1r:
C0E2r:
C0E3r:
C0E4r:
C0E5r:
C0E6r:
C0E7r: push cs
push di
jmp StepMotor
C0E0w:
C0E1w:
C0E2w:
C0E3w:
C0E4w:
C0E5w:
C0E6w:
C0E7w: Save ax
call StepMotor
Restore ax
sahf
DoNext
C0E8r: push cs
push di
jmp StopMotors
C0E8w: Save ax
call StopMotors
Restore ax
sahf
DoNext
C0E9r: push cs
push di
jmp StartMotors
C0E9w: Save ax
call StartMotors
Restore ax
sahf
DoNext
C0EAr:
C0EBr: push cs
push di
jmp DeviceSelect
C0EAw:
C0EBw: Save ax
call DeviceSelect
Restore ax
sahf
DoNext
CheckAddress
UseNextFreeSpace
C0ECr: push cs
push di
jmp ReadWriteBuf
C0ECw: Save ax
call ReadWriteBuf
Restore ax
sahf
DoNext
C0EDr: mov al,0FFh
mov bl,ch
jmp di
C0EDw: Save ax
mov al,bh
call WriteDataReg
Restore ax
sahf
DoNext
C0EEr: push cs
push di
call ReadMode
jmp WriteProtection
C0EEw: Save ax
call ReadMode
Restore ax
sahf
DoNext
C0EFr: push di
call WriteMode
mov al,0FFh
ret
C0EFw: Save ax
call WriteMode
Restore ax
sahf
DoNext
CheckAddress
;-------------- Floppy emulation subroutines -----------------------------------
Peripher segment public
assume CS:Peripher,DS:Nothing,ES:Nothing
FLAGS db 00000010b
even
BufferPTR dw 0 ; Byte pointer in the R/W buffer
WriteCNT dw 0 ; Written bytes between two reads
WriteREG db 0 ; Temporal write register
even
CurrentDrive Drive_S <0> ; Active Drive Attributes
OtherDrive Drive_S <1>
; Entry:
; bx - file handle
; ds:si - header ptr
; Action:
; load track buffer
; Exit:
; CF: 0-ok, 1-error (don't close file)
FloppyLoad proc far
push ax cx dx ds
mov ax,seg Buffer1000h
mov ds,ax
mov dx,offset Buffer1000h
mov cx,1000h
mov ah,3Fh
int 21h
cmp ax,cx
pop ds dx cx ax
ret
FloppyLoad endp
; Entry:
; bx - file handle
; es:di - header ptr
; Action:
; save track buffer
; Exit:
; CF: 0-ok, 1-error (don't close file)
FloppySave proc far
push ax cx dx ds
mov ax,seg Buffer1000h
mov ds,ax
mov dx,offset Buffer1000h
mov cx,1000h
mov ah,40h
int 21h
cmp ax,cx
pop ds dx cx ax
ret
FloppySave endp
assume ds:Nothing
FloppyINIT Proc near
call OpenDiskFile1
call OpenDiskFile2
ret
FloppyINIT Endp
FloppyTINI Proc near
call CloseDiskFile1
call CloseDiskFile2
ret
FloppyTINI Endp
ResetFloppy Proc near
call ReadMode
mov al,0
call DeviceSelect
call StopMotors
ret
ResetFloppy Endp
even
StartMotors Proc far
or FLAGS,00000011b
mov bl,ch
ret
StartMotors Endp
even
StopMotors Proc far
test FLAGS,00000010b
jz StopMotors5
and FLAGS,11111101b
mov bl,ch
ret
StopMotorsC: test FLAGS,00000010b
jnz StopMotors5
call WriteTrack
and FLAGS,11111100b
StopMotors5: mov bl,ch
ret
StopMotors Endp
even
DeviceSelect Proc far
and al,1b
xor al,CurrentDrive.ID
jz DeviceSelect20
call WriteTrack
Save si cx
mov si,offset CurrentDrive
mov cx,size Drive_S
DeviceSelect10: lods byte ptr CS:[SI]
xchg CS:OtherDrive.ID[SI-1]-CurrentDrive.ID,al
mov CS:[SI-1],al
loop DeviceSelect10
Restore si cx
DeviceSelect20: mov bl,ch
ret
DeviceSelect Endp
even
StepMotor Proc far
test FLAGS,00000001b
jz StepMotor8
Save cx
mov cl,al
and cl,00000110b
mov ah,CurrentDrive.Phase
ror ah,cl
ror ax,1
xor cl,00000111b
ror ah,cl
mov CurrentDrive.Phase,ah
mov cl,CurrentDrive.PhasePTR
ror ah,cl
mov ch,ah
mov bl,CurrentDrive.StepCounter
mov bh,bl
StepMotor5: mov ah,ch
xor al,al
shr ah,1
shr ah,1
rcl al,1
shr ah,1
rcl al,1
shr ah,1
rcl al,1
shr ah,1
cmp ah,al
je StepMotor20
ja StepMotor10
inc cl
ror ch,1
inc bl
jmp StepMotor5
StepMotor8: mov bl,ch
ret
StepMotor10: dec cl
rol ch,1
dec bl
jmp StepMotor5
StepMotor20: and cl,00000111b
mov CurrentDrive.PhasePTR,cl
xor bh,bl
and bh,11111100b
jz StepMotor25
call WriteTrack
StepMotor25: cmp bl,0F8h
jb StepMotor27
and bl,111b
StepMotor27: mov CurrentDrive.StepCounter,bl
shr bl,1
shr bl,1
mov CurrentDrive.Track,bl
StepMotor30: Restore cx
mov bl,ch
ret
StepMotor Endp
even
ReadMode Proc far
and FLAGS,10111111b
mov bx,BufferPTR
add bx,ReadAdd
cmp bx,TrackBufferLen
jb ReadMode10
sub bx,TrackBufferLen
ReadMode10: mov BufferPTR,bx
mov WriteCNT,0
mov bl,ch
ret
ReadMode Endp
even
WriteMode Proc far
or FLAGS,01000000b
mov bx,BufferPTR
add bx,WriteAdd
cmp bx,TrackBufferLen
jb WriteMode10
sub bx,TrackBufferLen
WriteMode10: mov BufferPTR,bx
test FLAGS,00000100b
jnz WriteMode20
mov BufferPTR,0
or FLAGS,00010100b
WriteMode20: or FLAGS,00001000b
mov bl,ch
ret
WriteMode Endp
even
ReadWriteBuf Proc far
mov ah,FLAGS
test ah,01000000b
jnz WriteBuff10
test ah,00000100b
jnz ReadBuff10
call ReadTrack
mov BufferPTR,0
or FLAGS,00000100b
and FLAGS,11100111b
mov ah,FLAGS
ReadBuff10: mov bx,BufferPTR
mov al,TrackBuffer[bx]
test ah,00000001b
jz ReadBuff30
inc bx
cmp bx,TrackBufferLen
jb ReadBuff20
xor bx,bx
ReadBuff20: mov BufferPTR,bx
ReadBuff30: mov bl,ch
ret
WriteBuff10: test ah,00000001b
jz Writebuff30
mov bx,BufferPTR
mov al,WriteREG
mov TrackBuffer[bx],al
inc bx
cmp bx,TrackBufferLen
jb WriteBuff20
xor bx,bx
WriteBuff20: mov BufferPTR,bx
mov bx,WriteCNT
inc bx
mov WriteCNT,bx
cmp bx,FormatLimit
jb WriteBuff30
or FLAGS,00010000b
Writebuff30: mov bl,ch
ret
ReadWriteBuf Endp
even
WriteDataReg Proc far
mov WriteREG,al
mov bl,ch
ret
WriteDataReg Endp
even
WriteProtection Proc far
mov al,CurrentDrive.WriteProtect
mov bl,ch
ret
WriteProtection Endp
;-------------------------------------------------------------------------------
ReadTrack Proc far ; Saves all registers
SaveAll
cmp CurrentDrive.DiskType,0
mov ax,cs
mov ds,ax
mov si,offset TrackBuffer
mov di,TrackBufferLen
je ReadTrack10
mov ax,seg Buffer1000h
mov ds,ax
mov si,offset Buffer1000h
mov di,1000h
ReadTrack10: mov al,CurrentDrive.Track
cbw
mul di
mov cx,dx
mov dx,ax
mov bx,CurrentDrive.FileHandle
mov ax,4200h
int 21h
jc ReadTrack20
mov dx,si
mov cx,di
mov ah,3Fh
int 21h
jnc ReadTrack30
cmp ax,cx
je ReadTrack30
ReadTrack20: mov ax,cs
mov es,ax
mov di,offset TrackBuffer
mov cx,TrackBufferLen/2
mov ax,Gap1
rep stosw
jmp ReadTrack40
ReadTrack30: cmp CurrentDrive.DiskType,0
je ReadTrack40
call EncodeTrack
ReadTrack40: RestoreAll
ret
ReadTrack Endp
EncodeTrack Proc near ; Destroys all registers
cld
mov ax,cs
mov ds,ax
mov es,ax
assume ds:Peripher,es:Peripher
mov di,offset TrackBuffer
mov dl,0
mov ax,Gap1
mov cx,Gap1Len/2
Encode10: rep stosw
mov si,offset SectorImage.AddressProlog
movsb
movsw
lodsb
mov dh,al
mov al,CurrentDrive.Volume
xor dh,al
mov ah,al
shr al,1
or ax,0AAAAh
stosw
mov al,CurrentDrive.Track
xor dh,al
mov ah,al
shr al,1
or ax,0AAAAh
stosw
xor bx,bx
mov bl,dl
mov bl,PosToLogNumber[BX]
mov al,LogToPhisNumber[BX]
xor dh,al
mov ah,al
shr al,1
or ax,0AAAAh
stosw
mov al,dh
mov ah,al
shr al,1
or ax,0AAAAh
stosw
movsw
movsb
mov ax,Gap2
mov cx,Gap2Len/2
rep stosw
movsw
movsb
lodsb
mov dh,al
xchg bh,bl
add bx,offset Buffer1000h
mov si,bx
mov ax,seg Buffer1000h
mov ds,ax
assume ds:seg Buffer1000h
mov bx,offset EncodeTable
mov cx,56h
Encode15: xor ah,ah
mov al,DS:[SI+2*56h]
shr al,1
rcl ah,1
shr al,1
rcl ah,1
mov ES:[DI+3*56h],al
mov al,DS:[SI+56h]
shr al,1
rcl ah,1
shr al,1
rcl ah,1
mov ES:[DI+2*56h],al
lodsb
shr al,1
rcl ah,1
shr al,1
rcl ah,1
mov ES:[DI+56h],al
mov al,ah
xor al,dh
xor dh,al
xlat CS:[BX]
stosb
loop Encode15
mov si,di
mov ax,cs
mov ds,ax
assume ds:Peripher
mov cx,100h
Encode20: lodsb
xor al,dh
xor dh,al
xlat
stosb
loop Encode20
mov al,dh
xlat
stosb
mov si,offset SectorImage.DataEpilog
movsw
movsw
mov ax,Gap3
mov cx,Gap3Len/2
inc dl
cmp dl,10h
jnb Encode30
jmp Encode10
Encode30: mov ax,Gap1
mov cx,offset TrackBuffer2
sub cx,di
shr cx,1
rep stosw
adc cx,0
rep stosb
ret
assume ds:Nothing,es:Nothing
EncodeTrack Endp
FlushBuffer Proc far ; External entry
call WriteTrack ; (from Disk Manager)
ret
FlushBuffer Endp
WriteTrack Proc near ; Saves all registers
test FLAGS,00011000b
jz WriteTrack30
cmp CurrentDrive.WriteProtect,0
jne WriteTrack30
SaveAll
cmp CurrentDrive.DiskType,0
mov ax,cs
mov ds,ax
mov si,offset TrackBuffer
mov di,TrackBufferLen
je WriteTrack10
call DecodeTrackM
mov ax,seg Buffer1000h
mov ds,ax
mov si,offset Buffer1000h
mov di,1000h
WriteTrack10:
and FLAGS,11100111b
mov al,CurrentDrive.Track
cbw
mul di
mov cx,dx
mov dx,ax
mov bx,CurrentDrive.FileHandle
mov ax,4200h
int 21h
jc WriteTrack20
mov dx,si
mov cx,di
mov ah,40h
int 21h
WriteTrack20: RestoreAll
WriteTrack30: and FLAGS,11111011b
ret
WriteTrack Endp
DecodeTrackM Proc near
DecodeTrackM10: call DecodeTrack
jnc DecodeTrackM20
Save ax bx cx dx
mov bl,DecodedSector
and bx,0Fh
mov dl,PhisToLogNumber[BX]
pushf
pushf
pop cx
and cx,not(11b shl 8)
push cx
popf
call DMentry
lahf
popf
sahf
Restore ax bx cx dx
jnc DecodeTrackM10
DecodeTrackM20: ret
DecodeTrackM Endp
DecodeTrack Proc near ; Destroys all registers
assume ds:Peripher,es:Peripher
cld
mov ax,cs
mov ds,ax
mov es,ax
mov si,offset TrackBuffer
mov di,offset TrackBuffer2
FastMovs TrackBuffer2Len
mov di,offset SectorFlags
mov al,1
FastStos 10h
mov di,offset TrackBuffer
jmp Decode10
DecodeTrkErr_J: jmp DecodeTrackErr
DecodeTrkEnd_J: jmp DecodeTrackEnd
Decode10: mov cx,offset TrackBuffer2
sub cx,di
jbe DecodeTrkEnd_J
mov al,SectorImage.AddressProlog
repne scasb
jne DecodeTrkEnd_J
mov ax,ES:[DI]
xor ax,word ptr SectorImage .AddressProlog+1
and ax,word ptr SectorImageF.AddressProlog+1
jnz Decode10
lea si,[di+2]
mov dh,SectorImage .AddressCheckSum
call DecodeAdrField
and al,SectorImageF.AddressCheckSum
mov ah,e_BadAdrCheckSum
jnz DecodeTrkErr_J ; Bad Address CheckSum
lodsw
xor ax,word ptr SectorImage .AddressEpilog
and ax,word ptr SectorImageF.AddressEpilog
jnz Decode15
lodsb
xor al,SectorImage .AddressEpilog+2
and al,SectorImageF.AddressEpilog+2
Decode15: mov ah,e_BadAdrEpilog
jnz DecodeTrkErr_J ; Bad Address Epilog
mov al,DecodedTrack
cmp al,CurrentDrive.Track
mov ah,e_BadTrackNumber
jne DecodeTrkErr_J ; Bad Track Number
mov al,DecodedSector
cmp al,0Fh
mov ah,e_BadSectorNumber
ja DecodeTrkErr_J ; Bad Sector Number
mov di,si
mov cx,DataSearchLen
Decode20: mov al,SectorImage.DataProlog
repne scasb
mov ah,e_MissingDataField
jne DecodeTrkErr_J ; Data Field is Missing
mov ax,ES:[DI]
xor ax,word ptr SectorImage .DataProlog+1
and ax,word ptr SectorImageF.DataProlog+1
jnz Decode20
lea si,[di+2]
mov bl,DecodedSector
and bx,0Fh
mov bl,PhisToLogNumber[BX]
dec SectorFlags[BX]
mov al,bl
mov ah,e_DuplicateSector
jnz DecodeTrackErr ; Duplicate Sector
xchg bh,bl
add bx,offset Buffer1000h
mov di,bx
mov dh,SectorImage .DataCheckSum
call DecodeDataField
and al,SectorImageF.DataCheckSum
and al,3Fh
mov ah,e_BadDataCheckSum
jnz DecodeTrackErr ; Bad Data CheckSum
or bp,bp
mov ah,e_BadDataImage
jnz DecodeTrackErr ; Bad Data Image
lodsw
xor ax,word ptr SectorImage .DataEpilog
and ax,word ptr SectorImageF.DataEpilog
jnz Decode70
lodsb
xor al,SectorImage .DataEpilog+2
and al,SectorImageF.DataEpilog+2
Decode70: mov ah,e_BadDataEpilog
jnz DecodeTrackErr ; Bad Data Epilog
lodsb
mov ah,al
xor ah,SectorImage .EndByte
and ah,SectorImageF.EndByte
mov ah,e_BadEndByte
jnz DecodeTrackErr ; Bad End Byte
mov di,si
jmp Decode10
DecodeTrackErr: stc
jmp DecodeTrackExt
DecodeTrackEnd: mov bx,0Fh
mov ah,e_MissingSector
Decode80: mov al,bl
cmp SectorFlags[BX],0
jne DecodeTrackErr ; Sector is Missing
dec bx
jns Decode80
mov al,DecodedVolume
mov CurrentDrive.Volume,al
clc
DecodeTrackExt: ret
DecodeAdrField Proc near ; DS:SI - Source
lodsw ; DH - CheckSum Seed
rol al,1
and al,ah
mov DecodedVolume,al
xor dh,al
lodsw
rol al,1
and al,ah
mov DecodedTrack,al
xor dh,al
lodsw
rol al,1
and al,ah
mov DecodedSector,al
xor dh,al
lodsw
rol al,1
and al,ah
xor al,dh
ret
DecodeAdrField Endp ; AL - CheckSum Result
DecodeDataField Proc near ; SI,DI - Source,Destination
Save es ; DH - CheckSum Seed
mov ax,seg Buffer1000h
mov es,ax
assume es:seg Buffer1000h
Save di
mov bx,offset DecodeTable - 80h
shl dh,1
shl dh,1
xor bp,bp
mov cx,56h-2
DDF10: lodsb
xlat
shl al,1
adc bp,0
xor dh,al
mov al,dh
xor ah,ah
shl al,1
rcr ah,1
shl ax,1
rcl ah,1
mov ES:[DI+2*56h],ah
xor ah,ah
shl al,1
rcr ah,1
shl ax,1
rcl ah,1
mov ES:[DI+1*56h],ah
shl al,1
rcr ah,1
rol al,1
rol ax,1
stosb
loop DDF10
mov cx,2
DDF20: lodsb
xlat
shl al,1
adc bp,0
xor dh,al
mov al,dh
xor ah,ah
shl al,1
shl al,1
shl al,1
rcr ah,1
shl ax,1
rcl ah,1
mov ES:[DI+1*56h],ah
shl al,1
rcr ah,1
rol al,1
rol ax,1
stosb
loop DDF20
Restore di
mov cx,100h
DDF30: lodsb
xlat
shl al,1
adc bp,0
xor dh,al
or ES:[DI],dh
inc di
loop DDF30
lodsb
xlat
shl al,1
adc bp,0
xor al,dh
shr al,1
shr al,1
Restore es
assume es:Peripher
ret ; AL - CheckSum Result
DecodeDataField Endp ; BP - Bad Data Image flag
assume ds:Nothing,es:Nothing
DecodeTrack Endp ; Error: CF=1, AH-Code, AL-Data
;-------------------------------------------------------------------------------
even
SectorImage SectorImage_S <>
SectorImageF SectorImageF_S <>
DecodedVolume db 0
DecodedTrack db 0
DecodedSector db 0
SectorFlags db 10h dup(0)
PosToLogNumber db 0Fh,0Eh,0Dh,0Ch,0Bh,0Ah,09h,08h ; Position-to-Logical
db 07h,06h,05h,04h,03h,02h,01h,00h ; number convert table
LogToPhisNumber db 00h,0Dh,0Bh,09h,07h,05h,03h,01h ; Logical-to-Phisical
db 0Eh,0Ch,0Ah,08h,06h,04h,02h,0Fh ; number convert table
PhisToLogNumber db 00h,07h,0Eh,06h,0Dh,05h,0Ch,04h ; Phisical-to-Logical
db 0Bh,03h,0Ah,02h,09h,01h,08h,0Fh ; number convert table
EncodeTable label byte ; 6&2 Encode Table
T1 = 80h
REPT 80h
T3 = (T1 and (T1 shl 1)) and 01111110b
T4 = not(T1 or (T1 shl 1)) and 01111110b
T4 = T4 and (T4 - 1)
IF (T3 GT 0) and (T4 EQ 0)
db T1
ENDIF
T1 = T1 + 1
ENDM
DecodeTable label byte ; 6&2 Decode Table
T1 = 80h
T2 = 0
REPT 80h
T3 = (T1 and (T1 shl 1)) and 01111110b
T4 = not(T1 or (T1 shl 1)) and 01111110b
T4 = T4 and (T4 - 1)
IF (T3 GT 0) and (T4 EQ 0)
db T2 shl 1
T2 = T2 + 1
ELSE
db 80h
ENDIF
T1 = T1 + 1
ENDM
TrackBuffer db TrackBufferLen dup(0)
TrackBuffer2 db TrackBuffer2Len dup(0)
Peripher ends