home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Current Shareware 1994 January
/
SHAR194.ISO
/
dos_util
/
pcmcvt.zip
/
PCMASM.ZIP
/
PCMCVT.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-05-29
|
27KB
|
875 lines
;--------------------------------------------------------------------------
;PCMCVT.ASM
;Version 1.0
;Copyright (c) 1993 Jay Munro
;First published in PC Magazine June 29,1993
;--------------------------------------------------------------------------
;
;Compile and link with Masm 6.x:
; ML /Gc /Zm /W3 PCMCVT.ASM
;
;--------------------------------------------------------------------------
.Model Tiny ;Tiny model with Masm 6.x
.Code ;code segment (et all)
Org 100h ;origin for executable code, 100h
MakeText Proc Near
Begin: ;start here
Jmp SetErrorTrap
Include PCMDATA.INC ;data file for PCMCVT
SetErrorTrap:
Invoke PrintLine, Addr Copyright ;first print our copyright
Call HookInt24 ;set int 24h handler right off the bat!
Mov CS:CritErrFlag,0 ;clear CritErrFlag
Mov AX,CS
Mov ES,AX ;get our segments in line
Mov DS,AX
Mov Byte Ptr TabFlag,0 ;clear some of our variables
Mov Byte Ptr OverWriteFile,0
Cld ;forward moves
Mov SI,80H ;Point to parameter
LodSb
Cmp AL,1 ;any parm length?
Jg GetParms
Call HelpPrint ;give the user a little prod
Jmp Exit ;no parms
GetParms:
Call GetCommandString ;parse out our options
Jc ExitLeap
Cmp SourceFileThere,-1 ;if the file is there...ok
Jz OpenFiles
NoSourceFile:
Invoke PrintLine, Addr SourceRequired ;print message
Jmp Exit ;no parms
OpenFiles:
Invoke OpenFile, Addr SourceFile, 0 ;open source
Mov SHandle,AX ;save handle
Jc ErrorLeap ;quit if error
Invoke Read, SHandle, Addr HeaderBuffer, 256 ;read header
Jc ErrorLeap ;again exit if error
Invoke Seek, SHandle, 0 ;reset to zero on seek
Jc ErrorLeap ;good ol' error trapping
Call HeadCheck ;check header for file type
Jmp Stripper
;---------------------------------------------------------------------------
ErrorLeap:
Call PrintError
ExitLeap: ;mid-way lily pad for short jumps
Jmp Exit
Stripper:
Cmp Word Ptr FileType,-1 ;ok, did we find a file?
Jz ExitLeap ;nope...exit stage left
Cld ;forward direction on our moves
Cmp OverWriteFile,-1
Jz @F ;overwrite all the time
Invoke Exist, Addr DestFile
Jc @F ;not there, create it
Call ExistYes
Jnc @F
Mov AL,2 ;exit code
Jmp Exit ;if carry set, then exit now
@@:
Invoke OpenFile, Addr DestFile, 3C00h ;write - open or create
Jc ErrorLeap
Mov DHandle,AX
;WordPerfect
Lea DI,WriteBuffer ;point DI at Write buffer
Xor BX,BX ;initialize counter for write buffer
Mov AX,FileType
Cmp AX,1 ;1 = WordPerfect
Jnz W4D ;no this ain't it
Call WordPerfectCVT
Jmp ExitLeap
;Word For DOS
W4D:
Cmp AX,2 ;2 = word for dos
Jnz W4W ;no this
Call Word4DosCVT
Jmp ExitLeap
;Word For Windows
W4W:
Cmp AX,3 ;3 = word for dos
Jnz AMI2 ;no this
Call Word4WINCVT
Jmp ExitLeap
;AMIPro
AMI2:
Cmp AX,4 ;4 = AMI Pro
Jnz WinWri ;no this
Call AMIProCVT
Jmp ExitLeap
;Windows Write
WinWri:
Cmp AX,5 ;5 = Windows Write
Jnz ExitLeap ;no this
Call WRICVT
Exit:
Cmp AL,-1
Jnz @F
Xor AX,AX
@@:
Push AX
Cmp Word Ptr SHandle, 0
Jz @F
Invoke Close, SHandle
@@:
Cmp Word Ptr DHandle, 0
Jz @F
Invoke Close, DHandle
@@:
Xor DX,DX
Call UnHookInt24 ;put back int 24h
Pop AX ;retrieve error code
Mov AH,4Ch ;exit here
Int 21h
MakeText EndP
FlushIt Proc Near ;flushes write buffer
Mov AL,-1
Call WriteIt
Ret
FlushIt EndP
;----Write character ES:DI points at buffer
WriteIt Proc Near
Cmp AL,-1 ;are we flushing?
Jz Flush
StoSb
Inc BX ;register a character in buffer
Cmp Word Ptr BufferSize,BX
Jae WriteItExit
Flush:
Push SI ;save counter and source addr
Push CX
Push BX
;Word wrap routine here
Cmp Byte Ptr WordWrapFlag,-1 ;are we doing word wrap?
Jnz NoWrap
Invoke WordWrap, Addr WriteBuffer, BX ;do our word wrap magic
Jmp @F
NoWrap:
Invoke Write, DHandle, Addr WriteBuffer,BX ; BufferSize ;write it
Jc WriteItExit
@@:
Pop BX
Lea DI,WriteBuffer
Xor BX,BX
Pop CX ;retrieve counter & source addr
Pop SI
Mov AL,-1 ;signal a flush
WriteItExit:
RetN
WriteIt EndP
Exist Proc Near, FileName:Word
Mov DX,Offset DTA ;set DTA address
Mov AH,1Ah
Int 21h ;service 1Ah, int 21h
Mov AH,4Eh ;find first, service 4Eh
Xor CX,CX ;normal file attribute
Mov DX,FileName ;file to check for
Int 21h
Ret
Exist EndP
ReadIt Proc Near
Push DX
Push BX
Xor AL,AL ;clear AL for attribute
Invoke Read,SHandle,Addr ReadBuffer, BufferSize ;read beginning
Pop BX
Pop DX
Jnc @F
Jmp ExitReadit
@@:
Or AX,AX ;if AX is 0 then bag out
Jnz @F
Stc
Jmp ExitReadIt
@@:
Mov CX,AX ;CX = number of bytes
Cmp CX,BufferSize ;are we in the ballpark?
Jz @F
Mov BufferSize,CX ;nope reset
Mov EOFFlag,-1 ;set EOF flag
@@:
Clc
Lea SI,ReadBuffer ;point SI at buffer
Mov TopEnd, SI
Add TopEnd,CX
ExitReadit:
RetN
ReadIt EndP
;---Include files
Include SEARCH.INC ;Search module used in AMI module
Include WP51CONV.INC ;WordPerfect conversion module
Include W4DCONV.INC ;Word For Dos conversion module
Include W4WCONV.INC ;Word For Win conversion module
Include AMICONV.INC ;AMI Pro conversion module
Include WriCONV.INC ;Windows Write conversion module
GetCommandString Proc Near ;parses out command string
Mov BX,SI ;save SI (reuse)
CapIt: ;capitalizes the command line
; bet you thought DOS did that?
LodSb ;grab a byte
Or AL,AL ;is it a zero?
Jz CapDone ;all done, retrieve old pointer
Cmp AL,'a' ;is it within the range of a - z ?
Jl CapIt
Cmp AL,'z'
Jg CapIt
Sub AL,32 ;capitalize it
Mov Byte Ptr [SI-1],AL ;put cap'd letter back
Jmp CapIt ;loop back
CapDone:
Mov SI,BX ;put SI back
EatCmdSpace:
LodSb ;get a character
Cmp AL,'/' ;is it a delimiter?
Jz ParseOMatic
Cmp AL,0 ;is it the end of the line?
Jz CMDDoneLily
Cmp AL,32 ;is it a space?
Jz EatCmdSpace ;yes, eatit
Cmp AL,0Dh ;carriage return
Jz CmdDoneLily
Jmp EatCmdSpace
ParseOMatic: ;parse commands
LodSb ;get command letter
;check for dest file
Cmp AL,'D' ;Destfile?
Jnz @F
Mov Byte Ptr DestFileThere, -1 ;set file flag
Invoke ParseFileName, ADDR DestFile
Jc CMDDoneLily
Jmp EatCmdSpace
CMDDoneLily:
Clc ;set carry, were still in
Jmp CmdDone
@@:
Cmp AL,'S' ;source file
Jnz @F
Mov Byte Ptr SourceFileThere, -1 ;set file flag
Invoke ParseFileName, ADDR SourceFile
Jc CmdDoneLily
Jmp EatCmdSpace
@@:
Cmp AL,'W' ;word wrap
Jnz @F
Mov WordWrapFlag,-1
WLoop:
Cmp Byte Ptr [SI],'/' ;if we hit a slash, then we're done
Jz NoWNumber
Cmp Byte Ptr [SI],0Dh ;carriage return
Jz NoWNumber ;also done
Cmp Byte Ptr [SI],32 ;check for a value.
Jnz GetWWValue
Inc SI ;point to next character
Jmp WLoop ;eat spaces
GetWWValue:
Invoke ParseFileName, ADDR MaxWidthText ;parse out the number
Invoke Text2Num, Addr MaxWidthText, Addr MaxWidth ;convert the number
NoWNumber:
Jmp EatCmdSpace
@@:
Cmp AL,'T' ;Tab expansion
Jnz @F
Invoke ParseFileName, ADDR TabWidthText ;parse out the number
Invoke Text2Num, Addr TabWidthText, Addr TabWidth ;convert the number
Mov Byte Ptr TabFlag, -1 ;signal we are doing tabs
Jmp EatCmdSpace
@@:
Cmp AL,'O' ;overwrite file
Jnz @F
Mov OverWriteFile,-1
Jmp EatCmdSpace
@@:
Cmp AL,'?' ;help
Jnz @F
Call HelpPrint
Stc ;Set carry to exit
Jmp HelpDone
@@:
Jmp EatCmdSpace ;loop back til end
CmdDone:
Call CheckDestFile
Clc
HelpDone:
Ret
GetCommandString EndP
ParseFileName Proc Near, FileBuffer:Ptr
;entry DS:SI points toward string
Mov DI,FileBuffer ;point ES:DI at buffer
Xor CX,CX ;clear CX for a counter
PSLoop:
LodSb ;grab a character
Cmp AL,32 ;is it a space?
Jnz @F ;no
Jcxz PSLoop ;nope, then eat leading spaces
Clc ;clear carry and go out
Jmp PFNOut ;bye
@@:
Or AL,AL ;is it a zero?
Jnz @F
Stc
Jmp PFNOut
@@:
Cmp AL,0Dh ;carriage return
Jnz @F
Stc
Jmp PFNOut
@@:
StoSb ;assume it's a character and store it
Inc CX ;character counter
Cmp CX, 66 ;max out at 66
Jle PSLoop
Clc ;bug out
PFNOut:
Mov [DI],CH ;put a zero on the end of the file name
Ret
ParseFileName EndP
;--- Headcheck, identifies file by header.
HeadCheck Proc Near
;---------------------------------------------------------------------------
;-- WordPerfect
Invoke StrCmp, Addr HeaderBuffer, Addr WPerfID,4
Or AX,AX
Jnz @F
Mov AX,1 ;1 = Word Perf
Lea DX,WPerfName ;print name
Jmp HeadOut
@@:
;---------------------------------------------------------------------------
;-- Word For DOS ;
Invoke StrCmp, Addr HeaderBuffer, Addr MSWordDosID, 2
Or AX,AX
Jnz @F
;Check for Write file
Mov BX, Offset HeaderBuffer
Cmp Word Ptr [BX].MSWdwReserve, 0
Jnz WriFile
Mov AX,2 ;2 = Word4DOS
Lea DX,MSW4DName ;print name
Jmp HeadOut
WriFile: ;Windows Write format
Mov AX,5
Lea DX,WRIName ;print name
Jmp HeadOut
;---------------------------------------------------------------------------
;-- Word For Windows
@@:
Invoke StrCmp, Addr HeaderBuffer, Addr MSWordWinID,2
Or AX,AX
Jnz @F
Mov AX,3 ;3 = Word for Windows
Lea DX,MSW4WName ;print name
Jmp HeadOut
@@:
Invoke StrCmp, Addr HeaderBuffer, Addr MSWordWinID1,2
Or AX,AX
Jnz @F
Mov AX,3 ;3 = Word for Windows 1
Lea DX,MSW4WName1 ;print name
Jmp HeadOut
;---------------------------------------------------------------------------
;-- Ami Pro
@@:
Invoke StrCmp, Addr HeaderBuffer, Addr AMIProID,5
Or AX,AX
Jnz @F
Mov AX,4 ;4 = AMIPro 2.0
Lea DX,AmiName ;print name
Jmp HeadOut
;---------------------------------------------------------------------------
@@:
Lea DX,NotKnown ;no idea!
Mov AX,-1
HeadOut: ;print type of file
Mov FileType, AX
Mov AH,09h
Int 21h
Ret
HeadCheck EndP
PrintLine Proc Near, MessagePtr:Word
Mov DX, MessagePtr
Mov AH,09h
Int 21h
Ret
PrintLine EndP
ShowBuffer Proc Near, AddrWriteBuffer:Word, BuffLen:Word ;do it to the screen.
Cld ;forward direction flag
Push CX ;preserve CX & SI for
Push SI
Mov SI,AddrWriteBuffer
Mov CX,BuffLen
CharLoop:
LodSb
Mov AH,0Eh
Xor BX,BX
Int 10h
Loop CharLoop
Pop SI
Pop CX
Ret
ShowBuffer EndP
Text2Num Proc Near Uses DI SI, ValueStr:Word, ValueNum:Word
Cld
Mov SI,ValueStr ;get address of value string
Mov BX,10
Xor DX,DX
Mov AX,DX
FindZero:
LodSb
Or AL,AL ;is it zero?
Jz @F
Xchg AX,DX ;Swap for multiply
Mul BL ;multiply by 10
Xchg DX,AX
Xor AH,AH
Sub AL,'0' ;make it a real number
Add DX,AX ;add it in
Jmp FindZero
@@:
Mov BX,ValueNum ;stick total into return value
Mov [BX],DX
Ret
Text2Num EndP
DoTabs Proc Near Uses CX ;expand tabs
Cmp TabFlag,0 ;check to see if we save a tab
Jnz @F ; or replace with spaces
Mov AL,9h ;put a tab in AL
Call WriteIt ;write just the tab
Jmp TabExit
@@:
Mov CX, TabWidth ;get tab size
Jcxz TabExit
TabLoop:
Mov AL,32 ;put space in AL
Call WriteIt
Loop TabLoop
TabExit:
Ret
DoTabs EndP
Include WordWrap.Inc
;---------------------------------------------------------------------------
;File and error routines
;----------------------------------------------------------------------------
;HookInt24 - redirects critical errors to a more friendly handler.
; On a Critical error, the int 24h is captured and the error
; is returned to the calling routine.
;redirects Int24 to our own error handler
HookInt24 Proc Near
Mov AX,3524h ;get Int24 vector
Int 21h ; into ES:BX
Mov OldInt24IP,BX ; and save.
Mov OldInt24CS,ES
Lea DX,Int24ErrHandler ;DS = CS of CEH
Mov AX,2524h ;revector Int24h
Int 21h
Retn
HookInt24 EndP
;Restores the original Int24 vector that was saved by HookInt24
UnHookInt24 Proc Far
Push DS ;save registers
Push DX
Push AX
Push SS ;set DS = DGROUP
Pop DS
Mov DX,OldInt24IP ;get the original Int24 vector
Mov DS,OldInt24CS
Mov AX,2524h ;restore the vector
Int 21h
Pop AX ;restore registers
Pop DX
Pop DS
Ret
UnHookInt24 EndP
HelpPrint Proc Near ;shows help screen
Mov AH,09h
Mov DX,Offset HelpScreen
Int 21h
Ret
HelpPrint EndP
;Error handler - returns error to interrupt and continues.
; On entry: Error code in DI (provided by DOS)
; On exit: DOSErrCode = Critical error
; AL directs DOS to ignore the error
Int24ErrHandler Proc Near ;our new error handler
Sti ;restore interrupts
Push DI ;save DI
Push DX ;save DX
Push DS ;save DS
Push AX ;save AX
;translate error
Mov AX,99 ;unknown error default
Cmp DI,0h ;write protect
Jnz @F
Mov AX, 13h
@@:
Cmp DI, 02h ;disk not ready
Jnz @F
Mov AX, 15h
@@:
NotDiskIO:
Mov CS:DOSErrCode,AX
CEH_Exit:
Mov CS:CritErrFlag,1 ;verify that a critical error occurred
Pop AX ;restore AX (really just AH)
Mov AL,0 ;tell DOS to ignore the error
Pop DS ;restore DS
Pop DX ;restore DX
Pop DI ;restore DI
Iret ;get back to dos
Int24ErrHandler EndP
;----------------------------------------------------------------------------
;OpenFile - opens a file pointed at by FileName with attribute specified
OpenFile Proc Near, FileName:Word, Attr:Word
;put a zero on the strings
Mov SI,FileName ;get address of file
Mov DX,SI ;save it for use later
Mov CX,66 ;up to 66 characters
;Just in case file is not an ASCIIz
MakeZStr: ;optional, can be commented out
Lodsb
Cmp AL,32
Jz @F
Or AL,AL
Jz @F ;already a zero
Loop MakeZStr
@@:
Mov [SI-1],CH ;put a zero in
Mov AX,Attr ;get attribute (Read/Write)
Cmp AH,3Ch ;are we forcing a create?
Jz @F ;yes
Mov AH,3Dh ;open existing file
@@:
Xor CX,CX ;clear CX for attributes
Mov DX,FileName ;get address of filename
Int 21h ;
Ret
OpenFile EndP
;--- Seek - positions a file pointer
Seek Proc Near, Handle1:Word, Pointer:Dword
Push BX
Mov ErrorNum,0 ;reset error number
Mov AX,4200h ;service 42h, offset from start of file
Mov DX,Word Ptr Pointer ;low value
Mov CX,Word Ptr Pointer[2] ;high value
Mov BX,Handle1 ;file handle to use
Int 21h
Jnc @F
Mov ErrorNum,AX ;save error number
@@:
Pop BX
Ret ;return with new file pointer position in DX:AX
Seek EndP
;---------------------------------------------------------------------------
; Read - Reads BufSize number of characters of file data into buffer
; pointed at by Buffer parameter.
Read Proc Near, Handle2:Word, Buffer:Word, BufSize:Word
Reread2:
Mov ErrorNum,0 ;reset error number
Mov AH,3Fh ;service 3Fh - read file
Mov BX,Handle2 ;file handle
Mov CX,BufSize ;get number of bytes to read
Mov DX,Buffer ;get address of buffer
Int 21h ;do it
Jnc ReadOk ;no errors
Mov ErrorNum,AX
Jmp ReadExit ;we got an error, no need to check anymore
ReadOk:
Clc
ReadExit:
Ret
Read EndP
; Write - Writes BufSize number of characters stored in Buffer to file handle
; supplied
Write Proc Near, Handle3:Word, Buffer:Word, BufSize:Word
ReWrite:
Mov DOSErrCode,0 ;clear the DOS error variable
Mov CritErrFlag,0 ;clear the critical error flag
Mov ErrorNum,0 ;reset error number
Mov AH,40h ;service 40h, write to a file
Mov BX,Handle3 ;file handle
Mov CX,BufSize ;number of bytes to write
Mov DX,Buffer ;address of buffer
Int 21h ;write the buffer
Jnc NoWriteError ;no errors, skip ahead
Jmp WriteExit
NoWriteError:
Cmp AX,BufSize ;disk full?
Jz WriteOk ;nope, exit ok
Stc
Jmp WriteExit
WriteOk:
Clc
WriteExit:
Ret
Write EndP
;--- Close - Closes file specified by Handle4
Close Proc Near, Handle4:Word
Mov ErrorNum,0 ;reset error number
Mov AH,3Eh ;service 3Eh, close file
Mov BX,Handle4 ;file handle
Int 21h ;close the file
Ret
Close EndP
StrCmp Proc Near, SrcString:Ptr, CmpString:Ptr, StrLength:Word
Push SI ;save Regs
Push DI
Push CX
Mov SI,SrcString ;get address of source
Mov DI,CmpString ;and string to compare
Mov CX,StrLength ;do length
RepE CmpSb ;compare them
Mov AX,CX ;result into AX
Pop CX ;restore regs
Pop DI
Pop SI
Ret
StrCmp EndP
CheckDestFile Proc Near
Cmp DestFileThere,-1
Jz CheckDestOk
Cmp SourceFileThere,-1
Jnz CheckDestOk
Mov SI,Offset SourceFile ;get address of source file
Mov DI,Offset DestFile ;get address of dest file
Push DS
Pop ES ;point ES -> DS
Mov CX,67 ;length of file buffer
Cld ;forward moves
FileMoveLoop:
LodSb ;get a character
Or AL,AL ;is it a zero?
Jz PutTXT ;yes, put the .TXT in
Cmp AL,'.' ;ok, how about a period
Jz PutTxt2 ;fine
FMIn:
StoSb
Loop FileMoveLoop
Stc ;error, set carry
Jmp CheckDestOk
PutTxt2:
Cmp Byte Ptr [SI],'\' ;is it a slash?
Jz FMIn ;yes,
Cmp Byte Ptr [SI],'.' ;ok, than is it two dots?
Jz FMIn
PutTxt:
Mov SI,Offset DefaultExtension ;get address of txt extension
Mov CX,4
Rep MovSb ;stuff it in there
FMLOut:
Xor AL,AL ;store an asciiZ
StoSb
Clc ;ok, clear carry
CheckDestOk:
Ret
CheckDestFile EndP
;Error message text
Err02 DB 'File Not Found$'
Err03 DB 'Path Not Found$'
Err05 DB 'Access Denied, may be write protected$'
Err13 DB 'Write Protected$'
Err15 DB 'Drive Not Ready$'
Err00 DB 'Unknown Error$'
PCrLf DB 10,13,'$'
Beep DB 07,'$'
PrintError Proc Near ;incoming AX = error
Cmp CritErrFlag, 0 ;is it a critical error?
Jz @F ;no, use extended error conversion
Mov AX, CS:DOSErrCode ;get real error saved during int 24h
Jmp ErrorDecoder
@@:
Mov AH,59h ;extended error
Int 21h ;decode error
ErrorDecoder:
Cmp AX, 02h ;file not found
Jnz @F
Mov DX,Offset Err02
Mov AX,1
Jmp PError
@@:
Cmp AX, 03h ;path not found
Jnz @F
Mov DX,Offset Err03
Mov AX,1
Jmp PError
@@:
Cmp AX, 05h ;Access denied
Jnz @F
Mov DX,Offset Err05
Mov AX,1
Jmp PError
@@:
Cmp AX, 13h ;write protected
Jnz @F
Mov DX,Offset Err13
Mov AX,3
Jmp PError
@@:
Cmp AX, 15h ;drive not ready
Jnz @F
Mov DX,Offset Err15
Mov AX,3
Jmp PError
@@:
Mov DX,Offset Err00
PError:
Push AX
Invoke PrintLine, DX
Invoke PrintLine, Addr PCRLF
Invoke PrintLine, Addr Beep
Pop AX
Ret
PrintError EndP
IsChar Proc Near ;check AL to see if it's alphanumeric
Cmp AL,'0' ;is it a number?
Jl NoChar
Cmp AL,'9'
Jle YesChar
Cmp AL,'A' ;is it in the alpha range?
Jl NoChar
Cmp AL,'X'
Jle YesChar
Cmp AL,'a'
Jl NoChar
Cmp AL,'z'
Jg NoChar
YesChar: ;yes, clear carry flag
Clc
RetN
NoChar: ;no, set carry (S.O.P. for errors)
Stc
RetN
IsChar EndP
FileExists DB 'Destination file Exists, Overwrite? Y/N $'
ExistYes Proc Near ;asks the user if they want to overwrite?
Invoke PrintLine, Addr FileExists
Xor AX,AX
Int 16h ;wait for a keystroke
Xor AH,AH
Mov CX,AX
Mov AH,02
Mov DL,CL
Int 21h
Invoke PrintLine, Addr PCRLF
Cmp CL,'Y' ;if they said yes, then clear carry
Jz YesNukeIt
Cmp CL,'y'
Jz YesNukeIt
Stc ;if no, then set carry flag
Jmp @F
YesNukeIt:
Clc
@@:
Ret
ExistYes EndP
End Begin ;tell Masm where execution starts