GophHub - zajo/appler/src/FLOPPY.INC


Raw File

;  _____________________________________________
; |                                             |
; |  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

Generated by GNU Enscript 1.6.6, and GophHub 1.3.