Category : Utilities for DOS and Windows Machines
Archive   : FMTA100.ZIP
Filename : FMT.ASM

 
Output of file : FMT.ASM contained in archive : FMTA100.ZIP
;***********************************************************************
;* *
;* Fmt.asm 23-JAN-1990 *
;* *
;* Format Floppy Disk - version 1.00 - IBM(R) DOS 4.0 style format *
;* *
;* Designed for use with IBM AT compatible sytems (including PS/2s) *
;* *
;* Syntax: FMT d: size [v] [s] [n] *
;* *
;* where: d = drive (A or B), size = floppy size in Kb, *
;* *
;* the optional v enables format verification, *
;* *
;* the optional s copies the system files, *
;* *
;* and the optional n bypasses the `insert floppy' prompt *
;* *
;* supported sizes are: *
;* *
;* 360 for a 360 Kb floppy in a 360 Kb or 1.2 Mb drive *
;* 720 for a 720 Kb floppy in a 720 Kb or 1.44 Mb drive *
;* 1200 for a 1.2 Mb floppy in a 1.2 Mb drive *
;* 1440 for a 1.44 Mb floppy in a 1.44 Mb drive *
;* *
;* Exit codes: *
;* *
;* 0 = successful format *
;* 1 = failure during format, verify, or write *
;* 2 = disk size / drive type combination is not supported *
;* 3 = requested drive does not exist *
;* 4 = invalid or null command line *
;* 5 = system files not found or error writing system files *
;* 6 = computer is not AT compatible *
;* 7 = insufficient memory for file copy buffer (system transfer) *
;* *
;* In order to use the system transfer option, the following files *
;* *
;* must be in the root diectory of the default drive: *
;* *
;* 1: IBMBIO.COM (normally a hidden file) *
;* *
;* 2: IBMDOS.COM (normally a hidden file) *
;* *
;* 3: COMMAND.COM *
;* *
;* Compile with Borland Turbo Assembler(R) version 1.0 or greater *
;* *
;* tasm /t fmt tasm /t /zi fmt *
;* or *
;* tlink /t /x fmt tlink /v /x fmt *
;* *
;* tdstrip -c -s fmt *
;* *
;* for use with Turbo Debugger(R) *
;* or *
;* *
;* Compile with Microsoft(R) Macro Assembler version 5.1 or greater *
;* *
;* masm /t fmt; *
;* *
;* link fmt; *
;* *
;* exe2bin fmt fmt.com *
;* *
;* del fmt.exe *
;* *
;* Copyright (C) 1990 by: *
;* *
;* Clair Alan Hardesty *
;* IBM-PC Hardware/Software Consultant *
;* 10301 Johnson Av *
;* Cupertino, CA 95014 *
;* (408) 446-0550 *
;* CompuServe 75350,16 *
;* *
;* Microsoft(R) is a registered trademark of Microsoft Corporation *
;* *
;* IBM(R) and PS/2 are registered trademarks of International *
;* *
;* Business Machines Corporation *
;* *
;* Turbo Assembler(R) and Turbo Debugger(R) are registered trademarks *
;* *
;* of Borland International *
;* *
;***********************************************************************

;***********************************************************************

; set-up for the far jump used in the boot record code

;***********************************************************************

ibmbio segment at 0070h

assume cs:ibmbio

org 0000h

program_loader label far

ibmbio ends

;***********************************************************************

; set-up for system identification

;***********************************************************************

rom_bios segment at 0f000h

assume ds:rom_bios

org 0fffeh

system_id label byte

rom_bios ends

;***********************************************************************

; main program code

;***********************************************************************

cseg segment

assume cs:cseg,ds:cseg,es:cseg,ss:cseg

org 0100h
entry_point:
jmp start ; skip over data area

;***********************************************************************

; format data area

;***********************************************************************

; format sector tables
sector_table_0:
db 000h,000h,001h,002h
db 000h,000h,002h,002h
db 000h,000h,003h,002h
db 000h,000h,004h,002h
db 000h,000h,005h,002h
db 000h,000h,006h,002h
db 000h,000h,007h,002h
db 000h,000h,008h,002h
db 000h,000h,009h,002h
db 000h,000h,00Ah,002h
db 000h,000h,00Bh,002h
db 000h,000h,00Ch,002h
db 000h,000h,00Dh,002h
db 000h,000h,00Eh,002h
db 000h,000h,00Fh,002h
db 000h,000h,010h,002h
db 000h,000h,011h,002h
db 000h,000h,012h,002h

sector_table_1:
db 000h,001h,001h,002h
db 000h,001h,002h,002h
db 000h,001h,003h,002h
db 000h,001h,004h,002h
db 000h,001h,005h,002h
db 000h,001h,006h,002h
db 000h,001h,007h,002h
db 000h,001h,008h,002h
db 000h,001h,009h,002h
db 000h,001h,00Ah,002h
db 000h,001h,00Bh,002h
db 000h,001h,00Ch,002h
db 000h,001h,00Dh,002h
db 000h,001h,00Eh,002h
db 000h,001h,00Fh,002h
db 000h,001h,010h,002h
db 000h,001h,011h,002h
db 000h,001h,012h,002h

;***********************************************************************

temp_size: db 4 dup (?)
binary_size: dw ?
verify: db 0 ; default is no verification
system: db 0 ; default is no system file transfer
prompt: db 1 ; default is prompt for floppy
drive_number: db ?
disk_drive: dw ?
max_track: db ?
retry_count: db ?
write_track: dw ?
write_head: db ?
write_sector: db ?
cursor: dw ?
stack_size: dw 2048 ; used in buffer size calculation
minimum_buffer: dw 4096 ; minimum file copy buffer size
buffer_size: dw ? ; actual file copy buffer size

;***********************************************************************

disk_size: db ?

; 1 = 360kb
; 2 = 1.2Mb
; 3 = 720kb
; 4 = 1.44Mb

drive_type: db ?

; 0 = no drive
; 1 = 360kb
; 2 = 1.2Mb
; 3 = 720kb
; 4 = 1.44Mb

;***********************************************************************

parameter_pointer:

dd ? ; storage for the original disk parameter table pointer

;***********************************************************************

floppy_table:
; 360 Kb

db 0FDh ; media descriptor
db 40 ; number of tracks
dw 9 ; sectors per track
dw 112 ; entries per root directory
db 7 ; sectors per root directory
db 2 ; sectors per cluster
dw 2 ; sectors per FAT

; 1.2 Mb

db 0F9h ; media descriptor
db 80 ; number of tracks
dw 15 ; sectors per track
dw 224 ; entries per root directory
db 14 ; sectors per root directory
db 1 ; sectors per cluster
dw 7 ; sectors per FAT

; 720 Kb

db 0F9h ; media descriptor
db 80 ; number of tracks
dw 9 ; sectors per track
dw 112 ; entries per root directory
db 7 ; sectors per root directory
db 2 ; sectors per cluster
dw 3 ; sectors per FAT

; 1.44 Mb

db 0F0h ; media descriptor
db 80 ; number of tracks
dw 18 ; sectors per track
dw 224 ; entries per root directory
db 14 ; sectors per root directory
db 1 ; sectors per cluster
dw 9 ; sectors per FAT

;***********************************************************************

parameter_table:

; 360 Kb

db 0D2h,002h,009h,002h,009h,02Ah,0FFh,050h,0F6h,001h,001h

; 1.2 Mb

db 082h,002h,009h,002h,00Fh,01Bh,0FFh,054h,0F6h,001h,001h

; 720 Kb

db 012h,002h,009h,002h,009h,02Ah,0FFh,050h,0F6h,001h,001h

; 1.44 Mb

db 012h,002h,009h,002h,012h,01Bh,0FFh,06Ch,0F6h,001h,001h

;***********************************************************************

; informational messages

;***********************************************************************

cr_lf:
db 00Dh,00Ah
db "$"

insert_floppy:

db "Put desired floppy in drive "

insert_drive:

db ?
db ": and press any key"
db "$"

clear_line:

db 50 dup (008h)
db 50 dup (020h)
db 50 dup (008h)
db "$"

format_display:

db 26 dup (008h)
db "Formatting track "

format_track_number:

db 2 dup (?)
db " head "

format_head_number:

db ?
db "$"

verify_display:

db 26 dup (008h)
db "Verifying track "

verify_track_number:

db 2 dup (?)
db " head "

verify_head_number:

db ?
db "$"

boot_message:

db 26 dup (008h)
db 26 dup (020h)
db 26 dup (008h)
db "Writing boot record"
db "$"

fat_message:

db 19 dup (008h)
db 19 dup (020h)
db 19 dup (008h)
db "Writing FATs"
db "$"

dir_message:

db 12 dup (008h)
db 12 dup (020h)
db 12 dup (008h)
db "Writing root directory"
db "$"

file_copy_message:

db 22 dup (008h)
db 22 dup (020h)
db 22 dup (008h)
db "Copying system files"
db "$"

exit_message:

db 22 dup (008h)
db 22 dup (020h)
db 22 dup (008h)
db "Format complete"
db 00Dh,00Ah
db "$"

;***********************************************************************

; error messages

;***********************************************************************

computer_message:

db 00Dh,00Ah,"IBM AT or compatible computer required",00Dh,00Ah
db "$"

no_drive_error:

db 00Dh,00Ah,"No such drive in system",00Dh,00Ah
db "$"

reset_error:

db 00Dh,00Ah,"Disk controller reset error",00Dh,00Ah
db "$"

set_drive_error:

db 00Dh,00Ah,"Disk drive type not supported by BIOS",00Dh,00Ah
db "$"

no_floppy_error:

db 00Dh,00Ah,"No floppy in drive",00Dh,00Ah
db "$"

set_disk_error:

db 00Dh,00Ah,"Disk / Drive combination not supported",00Dh,00Ah
db "$"

write_boot_error:

db 00Dh,00Ah,"Error writing boot record",00Dh,00Ah
db "$"

write_fat_error:

db 00Dh,00Ah,"Error writing FAT",00Dh,00Ah
db "$"

write_dir_error:

db 00Dh,00Ah,"Error writing directory",00Dh,00Ah
db "$"

write_protect_error:

db 00Dh,00Ah,"Disk is write protected",00Dh,00Ah
db "$"

error_during_format:

db 00Dh,00Ah,"Error during format",00Dh,00Ah
db "$"

disk_type_error:

db 00Dh,00Ah,"Probably wrong floppy type",00Dh,00Ah
db "$"

verify_error:

db 00Dh,00Ah,"Verification error",00Dh,00Ah
db "$"

buffer_space_error:

db 00Dh,00Ah,"No room for file copy buffer",00Dh,00Ah
db "$"

help_message:

db 00Dh,00Ah,"FMT version 1.00, Copyright (C) 1990 Clair Alan Hardesty"
db 00Dh,00Ah
db 00Dh,00Ah," syntax: fmt d: size [v] [s] [n]"
db 00Dh,00Ah
db 00Dh,00Ah," where: d = drive (A or B), size = floppy size in Kb,"
db 00Dh,00Ah
db 00Dh,00Ah," the optional v enables format verification,"
db 00Dh,00Ah
db 00Dh,00Ah," the optional s copies the system files,"
db 00Dh,00Ah
db 00Dh,00Ah," and the optional n bypasses the `insert floppy' prompt"
db 00Dh,00Ah
db 00Dh,00Ah," supported sizes are:"
db 00Dh,00Ah
db 00Dh,00Ah," 360 for a 360 Kb floppy in a 360 Kb or 1.2 Mb drive"
db 00Dh,00Ah," 720 for a 720 Kb floppy in a 720 Kb or 1.44 Mb drive"
db 00Dh,00Ah," 1200 for a 1.2 Mb floppy in a 1.2 Mb drive"
db 00Dh,00Ah," 1440 for a 1.44 Mb floppy in a 1.44 Mb drive"
db 00Dh,00Ah
db "$"

;***********************************************************************

; check cpu and computer type

;***********************************************************************

start:
; check CPU for 80286 or above

xor ax,ax
push ax
popf
pushf
pop ax
and ax,08000h
cmp ax,08000h

jnz two_eighty_six

mov dx,offset computer_message
mov ah,09h

int 21h

; exit

jmp short not_an_at
two_eighty_six:
; check the model byte in ROM

push ds
mov ax,rom_bios
mov ds,ax

assume ds:rom_bios

cmp system_id,0fch ; AT or compatible

je at_or_better

cmp system_id,0fah ; most P/S-2 (80286) models

je at_or_better

cmp system_id,0f8h ; P/S-2 model 80

je at_or_better

; computer is not AT compatible

pop ds

assume ds:cseg

mov dx,offset computer_message
mov ah,09h

int 21h
not_an_at:
; set exit code to 6 (not an AT or compatible)

mov ax,4c06h

int 21h

at_or_better:

;***********************************************************************

.286 ; enable the 80286 instruction set

;***********************************************************************

pop ds

assume ds:cseg

; initialize some variables

mov cl,0 ; parameter counter
mov dl,0 ; disk size digit counter
mov di,offset temp_size ; temporary disk size storage
mov bx,0080h ; pointer to command line

;***********************************************************************

; parse the command line

;***********************************************************************

parse_loop:
inc bx
cmp byte ptr [bx],0dh ; carriage return

jne not_finished

jmp got_command
not_finished:
cmp byte ptr [bx],' ' ; space

je parse_loop

cmp byte ptr [bx],09h ; tab

je parse_loop

cmp cl,0

jg number_check

and byte ptr [bx],5fh ; capitalize drive letter
cmp byte ptr [bx],'A'

jnl check_for_b

jmp help ; invalid drive
check_for_b:
cmp byte ptr [bx],'B'

jng store_drive

jmp help ; invalid drive
store_drive:
mov al,byte ptr [bx]
sub al,'A'
mov byte ptr [drive_number],al
colon_check:
cmp byte ptr [bx+1],':'

je found_colon

jmp help ; no colon after drive letter
found_colon:
inc bx ; skip over the colon
inc cl ; increment parameter count

jmp parse_loop
number_check:
cmp cl,1

jg check_option

cmp byte ptr [bx],'0'

jnl maybe_a_number

jmp help ; not a number
maybe_a_number:
cmp byte ptr [bx],'9'

jng is_a_number

jmp help ; not a number
is_a_number:
cmp byte ptr [bx+1],0Dh ; next character is a return

je last_digit

cmp byte ptr [bx+1],' ' ; next character is a space

je last_digit

cmp byte ptr [bx+1],09h ; next character is a tab

jne store_digit
last_digit:
inc cl ; increment parameter count
store_digit:
mov al,byte ptr [bx]
sub al,'0' ; convert ASCII to BCD
mov byte ptr [di],al
inc di
inc dl
cmp dl,4

jle jump_to_parse

jmp help ; too many digits in disk size
jump_to_parse:
jmp parse_loop
check_option:
cmp cl,5

jng parse_option

jmp help ; too many parameters
parse_option:
and byte ptr [bx],5fh
cmp byte ptr [bx],'V'

je set_verify

cmp byte ptr [bx],'S'

je set_system

cmp byte ptr [bx],'N'

je clear_prompt

jmp help ; invalid option
set_verify:
mov byte ptr [verify],1 ; set format verify true
inc cl

jmp parse_loop
set_system:
mov byte ptr [system],1 ; set transfer system true
inc cl

jmp parse_loop
clear_prompt:
mov byte ptr [prompt],0 ; set transfer system true
inc cl

jmp parse_loop
got_command:
cmp cl,2

jnl two_parameters

jmp help ; too few parameters
two_parameters:
cmp dl,3

jl help ; too few digits in disk size

; convert the size parameter from BCD to binary

mov cl,dl
dec di
xor ah,ah
mov al,byte ptr [di]
mov word ptr [binary_size],ax
dec di
dec cl
xor ah,ah
mov al,byte ptr [di]
imul ax,10
add word ptr [binary_size],ax
dec di
dec cl
xor ah,ah
mov al,byte ptr [di]
imul ax,100
add word ptr [binary_size],ax
dec di
dec cl

jz test_size_360

xor ah,ah
mov al,byte ptr [di]
imul ax,1000
add word ptr [binary_size],ax
test_size_360:
cmp word ptr [binary_size],360

jne test_size_1200 ; not 360 Kb

mov byte ptr [disk_size],1

jmp short set_up ; command line is valid
test_size_1200:
cmp word ptr [binary_size],1200

jne test_size_720 ; not 1.2 Mb

mov byte ptr [disk_size],2

jmp short set_up ; command line is valid
test_size_720:
cmp word ptr [binary_size],720

jne test_size_1440 ; not 720 Kb

mov byte ptr [disk_size],3

jmp short set_up ; command line is valid
test_size_1440:
cmp word ptr [binary_size],1440

jne help ; not 1.44 Mb

mov byte ptr [disk_size],4

jmp short set_up ; command line is valid
help:
; command line is invalid or null

mov dx,offset help_message
mov ah,09h

int 21h

; set exit code to 4 (null or invalid command line)

mov ax,4c04h

int 21h

;***********************************************************************

; set up the drive parameters and the parameter table

;***********************************************************************

set_up:
; if transfering system, check file copy buffer space

cmp byte ptr [system],1

jne cursor_off

; calculate copy buffer size

mov ax,sp
cmp ax,offset file_buffer

jc no_buffer

sub ax,offset file_buffer
sbb ax,word ptr [stack_size]

jc no_buffer

cmp ax,word ptr [minimum_buffer]

jnc buffer_ok
no_buffer:
mov dx,offset buffer_space_error
mov ah,09h

int 21h

; set exit code to 7 (no room for file copy buffer)

mov ax,4c07h

int 21h
buffer_ok:
mov word ptr [buffer_size],ax
cursor_off:
; save the current cursor and then turn the cursor off

mov ah,03h

int 10h

mov word ptr [cursor],cx
or cx,2000h
mov ah,01h

int 10h

; issue a carrriage-return / line-feed to stdout

mov dx,offset cr_lf
mov ah,09h

int 21h

; check for prompt bypass

cmp byte ptr [prompt],1

jne no_prompt

; prompt for a floppy

mov dx,offset insert_floppy
mov ah,09h
mov al,byte ptr [drive_number]
add al,41h
mov byte ptr [insert_drive],al

int 21h

; wait for a key press

xor ah,ah

int 16h

; clear the message line

mov dx,offset clear_line
mov ah,09h
int 21h
no_prompt:
; get disk drive information

push es
push di
push si
mov ah,08h
mov dl,byte ptr [drive_number]

int 13h

cmp bl,0

jne drive_exists

mov dx,offset no_drive_error
mov ah,09h

int 21h

; set exit code to 3 (drive does not exist)

pop ax
pop ax
pop ax
mov ax,4c03h

int 21h
drive_exists:
mov byte ptr [max_track],ch
mov byte ptr [sectors_track],cl
mov byte ptr [drive_type],bl
mov ah,byte ptr [disk_size]
mov al,bl
mov word ptr [disk_drive],ax

; check for floppy size less than drive maximum capacity

; check for a 360 Kb floppy in a 1.2 Mb drive

cmp word ptr [disk_drive],0102h

je forty_tracks

; check for a 720 Kb floppy in a 1.44 Mb drive

cmp word ptr [disk_drive],0304h

je nine_sectors

; check for improper disk / drive cominations

cmp word ptr [disk_drive],0201h

je bad_size ; 1.2 Mb in 360 Kb

cmp word ptr [disk_drive],0301h

je bad_size ; 720 Kb in 360 Kb

cmp word ptr [disk_drive],0401h

je bad_size ; 1.44 Mb in 360 Kb

cmp word ptr [disk_drive],0302h

je bad_size ; 720 Kb in 1.2 Mb

cmp word ptr [disk_drive],0402h

je bad_size ; 1.44 Mb in 1.2 Mb

cmp word ptr [disk_drive],0103h

je bad_size ; 360 Kb in 720 Kb

cmp word ptr [disk_drive],0203h

je bad_size ; 1.2 Mb in 720 Kb

cmp word ptr [disk_drive],0403h

je bad_size ; 1.44 Mb in 720 Kb

cmp word ptr [disk_drive],0104h

je bad_size ; 360 Kb in 1.44 Mb

cmp word ptr [disk_drive],0204h

je bad_size ; 1.2 Mb in 1.44 Mb

jmp short size_ok
bad_size:
mov dx,offset set_disk_error
mov ah,09h

int 21h

; set exit code to 2 (disk / drive comination error)

pop ax
pop ax
pop ax
mov ax,4c02h

int 21h
forty_tracks:
mov byte ptr [max_track],39
nine_sectors:
mov byte ptr [sectors_track],9
size_ok:
; save the original disk parameter table pointer

xor ax,ax
mov es,ax
mov ax,word ptr es:[0078h]
mov dx,word ptr es:[007ah]
mov word ptr [parameter_pointer],ax
mov word ptr [parameter_pointer+2],dx

; set the disk parameter table pointer for formatting

xor ah,ah
mov al,byte ptr [disk_size]
dec ax
imul ax,11
add ax,offset parameter_table
cli
mov word ptr es:[0078h],ax
mov word ptr es:[007ah],cs
sti

; put the parameter table in the boot record

push cs
pop es
mov si,ax
mov di,offset disk_table
mov cx,11
cld

rep movsb

pop si
pop di
pop es

;***********************************************************************

; store the disk parameters in the boot record and FAT

;***********************************************************************

push si

; calculate the offset to the parameters in floppy_table

xor ah,ah
mov al,byte ptr [disk_size]
dec ax
imul ax,10
mov bx,ax
mov si,offset floppy_table

; set the media descriptor byte

mov al,byte ptr [si+bx]
mov byte ptr [descriptor],al
mov byte ptr [fat_record],al ; first byte of FAT

; set the number of root directory entries


mov ax,word ptr [si+bx+4]
mov word ptr [directory_size],ax

; set the number of sectors per directory

mov al,byte ptr [si+bx+6]
mov byte ptr [sectors_directory],al

; set the number of sectors per cluster

mov al,byte ptr [si+bx+7]
mov byte ptr [sectors_cluster],al

; set the number of sectors per FAT

mov ax,word ptr [si+bx+8]
mov word ptr [sectors_fat],ax

; set the total number of sectors per disk

xor dx,dx
xor ah,ah
mov al,byte ptr [max_track]
inc ax
mul word ptr [sectors_track]
xor bh,bh
mov bl,byte ptr [heads]
mul bx
mov word ptr [small_total],ax

; calculate the location of the first directory sector

xor dx,dx
xor ah,ah
mov al,byte ptr [fats]
mul word ptr [sectors_fat]
add ax,word ptr [hidden_sectors]
adc dx,word ptr [hidden_sectors+2]
add ax,word ptr [reserved_sectors]
adc dx,0

; store directory start sector (absolute sector number)

mov word ptr [dir_start],ax
mov word ptr [dir_start+2],dx

; calculate the location of the first data sector

xor bh,bh
mov bl,byte ptr [sectors_directory]
add ax,bx
adc dx,0

; store data start sector (absolute sector number)

mov word ptr [data_start],ax
mov word ptr [data_start+2],dx

pop si

;***********************************************************************

; reset the disk controller

;***********************************************************************

reset:
mov byte ptr [retry_count],3
reset_retry:
xor ah,ah
mov dl,byte ptr [drive_number]

int 13h

jnc short set_drive

dec byte ptr [retry_count]

jnz reset_retry

mov dx,offset reset_error

jmp write_error

;***********************************************************************

; set the drive type for format

;***********************************************************************

set_drive:
mov byte ptr [retry_count],3
drive_retry:
mov al,byte ptr [drive_type]
cmp al,3

jl five_inch

mov al,4

jmp short set_type
five_inch:
cmp al,2

jne low_density

cmp byte ptr [disk_size],1

jg high_density

mov al,2

jmp short set_type
high_density:
mov al,3

jmp short set_type
low_density:
mov al,1
set_type:
mov ah,17h

int 13h

jnc short set_disk

cmp ah,80h

jne floppy_exists

mov dx,offset no_floppy_error

jmp write_error
floppy_exists:
dec byte ptr [retry_count]

jnz drive_retry

mov dx,offset set_drive_error

jmp write_error

;***********************************************************************

; set the disk type for format

;***********************************************************************

set_disk:
mov byte ptr [retry_count],3
disk_retry:
push es
push di
mov ah,18h
mov ch,byte ptr [max_track]
mov cl,byte ptr [sectors_track]
mov dl,byte ptr [drive_number]

int 13h

pop di
pop es

jnc format_disk

dec byte ptr [retry_count]

jnz disk_retry

mov dx,offset set_disk_error

jmp write_error

;***********************************************************************

; format the disk

;***********************************************************************

format_disk:
; set up the loop counter

xor ch,ch
mov cl,byte ptr [max_track]
inc cx
format_loop:
push cx

call format_track

jnc continue

pop cx

jmp write_error
continue:
call next_track

pop cx

loop format_loop

;***********************************************************************

; set up the volume serial number in the boot record

;***********************************************************************

serial_number:
; get the time

mov ah,2ch

int 21h

; fiddle the serial number bytes (similar to DOS 4.0)
;
; I don't know why IBM does this. It may be done to
; hide the fact that the serial number is derived
; from the system clock.
;
; I am not sure that the numbers that I have chosen are
; the same as IBM's, but they are close.
;
; a more reasonable approach might be to simply add one
; to each byte to avoid zero bytes in the serial number

add cx,07c7h
add dx,0707h

; store the serial number in the boot record

mov word ptr [sn_low],cx
mov word ptr [sn_high],dx

;***********************************************************************

; write the boot record and FAT1

;***********************************************************************

write_boot:
mov dx,offset boot_message
mov ah,09h

int 21h

mov byte ptr [retry_count],3
boot_retry:
mov ax,0302h
mov bx,offset boot_record
mov cx,0001h
xor dh,dh
mov dl,byte ptr [drive_number]

int 13h

jnc short finish_fat1

dec byte ptr [retry_count]

jnz boot_retry

mov dx,offset write_boot_error

jmp write_error
finish_fat1:
mov dx,offset fat_message
mov ah,09h

int 21h

; set the starting sector (absolute)

mov ax,2
xor dx,dx

; set the number of sectors to write

mov cx,word ptr [sectors_fat]
dec cx
fat1:
push ax
push cx
push dx

call write_ths

jnc fat1_ths_ok

pop ax
pop ax
pop ax

mov dx,offset write_fat_error

jmp write_error
fat1_ths_ok:
mov bx,offset fat_dir_record
mov byte ptr [retry_count],3
fat1_retry:
call write_disk

jnc fat1_write_ok

dec byte ptr [retry_count]

jnz fat1_retry

pop ax
pop ax
pop ax

mov dx,offset write_fat_error

jmp write_error
fat1_write_ok:
pop dx
pop cx
pop ax

; increment the absolute sector number

add ax,1
adc dx,0

loop fat1

jnc write_fat

mov dx,offset write_fat_error

jmp write_error

;***********************************************************************

; write FAT2

;***********************************************************************

write_fat:
mov byte ptr [retry_count],3
fat_retry:
mov ax,0301h
mov bx,offset fat_record
xor ch,ch
mov cl,byte ptr [sectors_fat]
add cl,2
xor dh,dh
mov dl,byte ptr [drive_number]

int 13h

jnc finish_fat2

dec byte ptr [retry_count]

jnz fat_retry

mov dx,offset write_fat_error

jmp write_error
finish_fat2:
; set the starting sector (absolute)

mov ax,2
xor dx,dx
add ax,word ptr [sectors_fat]
adc dx,0

; set the number of sectors to write

mov cx,word ptr [sectors_fat]
dec cx
fat2:
push ax
push cx
push dx

call write_ths

jnc fat2_ths_ok

pop ax
pop ax
pop ax

mov dx,offset write_fat_error

jmp write_error
fat2_ths_ok:
mov bx,offset fat_dir_record
mov byte ptr [retry_count],3
fat2_retry:
call write_disk

jnc fat2_write_ok

dec byte ptr [retry_count]

jnz fat2_retry

pop ax
pop ax
pop ax

mov dx,offset write_fat_error

jmp short write_error
fat2_write_ok:
pop dx
pop cx
pop ax

; increment the absolute sector number

add ax,1
adc dx,0

loop fat2

jnc write_dir

mov dx,offset write_fat_error

jmp short write_error

;***********************************************************************

; write the directory

;***********************************************************************

write_dir:
mov dx,offset dir_message
mov ah,09h

int 21h

; set the starting sector (absolute)

xor dx,dx
mov ax,word ptr [sectors_fat]
mul byte ptr [fats]
add ax,word ptr [reserved_sectors]
adc dx,0

; set the number of sectors to write

xor ch,ch
mov cl,byte ptr [sectors_directory]
dir:
push ax
push cx
push dx

call write_ths

jnc dir_ths_ok

pop ax
pop ax
pop ax

mov dx,offset write_dir_error

jmp short write_error
dir_ths_ok:
mov bx,offset fat_dir_record
mov byte ptr [retry_count],3
dir_retry:
call write_disk

jnc dir_write_ok

dec byte ptr [retry_count]

jnz dir_retry

pop ax
pop ax
pop ax

mov dx,offset write_dir_error

jmp short write_error
dir_write_ok:
pop dx
pop cx
pop ax

; increment the absolute sector number

add ax,1
adc dx,0

loop dir

jnc transfer

mov dx,offset write_dir_error

jmp short write_error
transfer:
cmp byte ptr [system],1

jne exit

; transfer the system files

call load_system

jnc exit

; set exit code to 5 (error copying system files)

mov ax,4c05h
push ax

jmp short error_exit
write_error:
mov ah,09h

int 21h

; set exit code to 1 (format, verify, or write error)

mov ax,4c01h
push ax

jmp short error_exit

;***********************************************************************

; clean up and exit

;***********************************************************************

exit:
; set exit code to 0 (Success)

mov ax,4c00h
push ax
error_exit:
; restore the original disk parameter table pointer

mov cx,word ptr [parameter_pointer]
mov dx,word ptr [parameter_pointer+2]
push ds
xor ax,ax
mov ds,ax

assume ds:0000h

cli
mov word ptr ds:[0078h],cx
mov word ptr ds:[007ah],dx
sti
pop ds

assume ds:cseg

; park the heads on track 0

mov ah,0ch
xor cl,cl
xor dh,dh
mov dl,byte ptr [drive_number]

int 13h

pop ax
push ax
cmp al,0

jne error_out

; display format complete message

mov dx,offset exit_message
mov ah,09h

int 21h
error_out:
; restore the cursor

mov cx,word ptr [cursor]
mov ah,01h

int 10h

; terminate with exit code (0 = Success, else = Failure)

pop ax

int 21h

;***********************************************************************

; format subroutines

;***********************************************************************

;***********************************************************************

; information display during format

;***********************************************************************

display_format:
xor ah,ah
aam
or ax,3030h
mov byte ptr [format_track_number+1],al
cmp ah,30h

jne format_digit

mov ah,20h
format_digit:
mov byte ptr [format_track_number],ah
mov al,bl
xor ah,ah
aam
or ax,3030h
mov byte ptr [format_head_number],al
mov dx,offset format_display
mov ah,09h

int 21h

ret

;***********************************************************************

; information display during verification

;***********************************************************************

display_verify:
xor ah,ah
aam
or ax,3030h
mov byte ptr [verify_track_number+1],al
cmp ah,30h

jne verify_digit

mov ah,20h
verify_digit:
mov byte ptr [verify_track_number],ah
mov al,bl
xor ah,ah
aam
or ax,3030h
mov byte ptr [verify_head_number],al
mov dx,offset verify_display
mov ah,09h

int 21h

ret

;***********************************************************************

; increment the track number in the sector tables

;***********************************************************************

next_track:
xor ch,ch
mov cl,36
mov bx,offset sector_table_0
track_counter:
inc byte ptr [bx]
add bx,4

loop track_counter

ret

;***********************************************************************

; format (and possibly verify) both heads on one track

;***********************************************************************

format_track:
mov al,byte ptr [sector_table_0]
mov bl,0

; display formatting message

call display_format

mov byte ptr [retry_count],3
head_0_retry:
mov ah,5
mov al,byte ptr [sectors_track]
mov bx,offset sector_table_0
mov ch,byte ptr [bx]
mov cl,byte ptr [bx+2]
mov dh,byte ptr [bx+1]
mov dl,byte ptr [drive_number]

int 13h

jnc short head_0_ok

cmp ah,80h

jne no_timeout

mov dx,offset no_floppy_error
stc
ret
no_timeout:
cmp ah,03h

jne not_protected

mov dx,offset write_protect_error
stc
ret
not_protected:
dec byte ptr [retry_count]

jnz head_0_retry

mov dx,offset error_during_format
stc
ret
head_0_ok:
cmp byte ptr [verify],1

je verify_head_0

; check for proper floppy type
;
; this is done via a verification of tracks 0,
; 59, and 79, for head 0 only, for all 1.2 Mb disks
; not being verified, and on track 0 head 0 only, for
; 360 Kb, 720 Kb and 1.44 Mb disks not being verified.
;
; the following combinations will fail at track 0:
;
; 1: trying to format a 1.2 Mb floppy to 360 Kb
; 2: trying to format a 720 Kb floppy to 1.44 Mb *
; 3: trying to format a 1.44 Mb floppy to 720 Kb * !
;
; the following combination will fail at track 79:
;
; 1: trying to format a 360 Kb floppy to 1.2 Mb (it will
; probably fail sooner, but it is sure to here)
;
; notes:
;
; * - these combinations may not fail if the drive-
; controller combination does not properly detect
; the the floppy type.
;
; ! - this combination may not fail in 720 Kb drives.
;
; While certain non-standard combinations may not fail,
; either the data on the disk may be at risk, or your
; pocketbook may suffer, if you insist on using them.

cmp byte ptr [sector_table_0],0

je verify_type

cmp byte ptr [disk_size],2

je one_point_two

jmp short format_head_1
one_point_two:
cmp byte ptr [sector_table_0],59

je verify_type

cmp byte ptr [sector_table_0],79

je verify_type

jmp short format_head_1
verify_type:
mov ah,04h

int 13h

jnc format_head_1

mov dx,offset disk_type_error
stc
ret
verify_head_0:
pushf
pusha
mov al,byte ptr [sector_table_0]
mov bl,0

; display verifying message

call display_verify

popa
popf
mov ah,04h

int 13h

jnc format_head_1

mov dx,offset verify_error
stc
ret
format_head_1:
pushf
pusha
mov al,byte ptr [sector_table_0]
mov bl,1

; display formatting message

call display_format

popa
popf
mov byte ptr [retry_count],3
head_1_retry:
mov ah,5
mov al,byte ptr [sectors_track]
mov bx,offset sector_table_1
mov ch,byte ptr [bx]
mov cl,byte ptr [bx+2]
mov dh,byte ptr [bx+1]
mov dl,byte ptr [drive_number]

int 13h

jnc short head_1_ok

dec byte ptr [retry_count]

jnz head_1_retry

mov dx,offset error_during_format
stc
ret
head_1_ok:
cmp byte ptr [verify],1

je verify_head_1
format_return:
clc
ret
verify_head_1:
pushf
pusha
mov al,byte ptr [sector_table_0]
mov bl,1

; display verifying message

call display_verify

popa
popf
mov ah,04h

int 13h

jnc format_return

mov dx,offset verify_error
stc
ret

;***********************************************************************

; calculate the track, head, and sector for a disk write

;***********************************************************************

write_ths:
; check for a valid absolute sector number

cmp dx,word ptr [sectors_track]

jb write_ths_ok

stc
ret
write_ths_ok:
; calculate the sector number

div word ptr [sectors_track]
inc dl

; store the sector number

mov byte ptr [write_sector],dl

; calculate the head number and the track number

xor dx,dx
div word ptr [heads]

; store the head number

mov byte ptr [write_head],dl

; store the track number

mov word ptr [write_track],ax

clc
ret

;***********************************************************************

; write one sector to the disk

;***********************************************************************

write_disk:
; get the track number

mov dx,word ptr [write_track]

; shift the upper 2 bits of the track number
; into the upper 2 bits of the sector number

mov cl,06
shl dh,cl

; get the sector number

or dh,byte ptr [write_sector]

mov cx,dx
xchg ch,cl

; get the drive number

mov dl,byte ptr [drive_number]

; get the head number

mov dh,byte ptr [write_head]

; write one sector to the disk

mov ax,0301h

int 13h

ret

;***********************************************************************

; transfer system files

;***********************************************************************

bios_source_path:

db "d:\"

bios_source_filename:

db "IBMBIO.COM",000h,008h
db "$"

bios_destination_path:

db "d:\"

bios_destination_filename:

db "IBMBIO.COM",000h,008h
db "$"

dos_source_path:

db "d:\"

dos_source_filename:

db "IBMDOS.COM",000h,008h
db "$"

dos_destination_path:

db "d:\"

dos_destination_filename:

db "IBMDOS.COM",000h,008h
db "$"

cmd_source_path:

db "d:\"

cmd_source_filename:

db "COMMAND.COM",000h,008h
db "$"

cmd_destination_path:

db "d:\"

cmd_destination_filename:

db "COMMAND.COM",000h,008h
db "$"

load_system:
mov dx,offset file_copy_message
mov ah,09h

int 21h

; get default drive

mov ah,19h

int 21h

; set source drive

add al,41h
mov byte ptr [bios_source_path],al
mov byte ptr [dos_source_path],al
mov byte ptr [cmd_source_path],al

; set destination drive

mov al,byte ptr [drive_number]
add al,41h
mov byte ptr [bios_destination_path],al
mov byte ptr [dos_destination_path],al
mov byte ptr [cmd_destination_path],al

; copy IBMBIOS.COM

mov bx,offset file_buffer
mov cx,word ptr [buffer_size]
mov si,offset bios_source_path
mov di,offset bios_destination_path

call file_copy

jc load_error

; copy IBMDOS.COM

mov bx,offset file_buffer
mov cx,word ptr [buffer_size]
mov si,offset dos_source_path
mov di,offset dos_destination_path

call file_copy

jc load_error

; copy COMMAND.COM

mov bx,offset file_buffer
mov cx,word ptr [buffer_size]
mov si,offset cmd_source_path
mov di,offset cmd_destination_path

call file_copy

jc load_error

clc
ret
load_error:
stc
ret

;***********************************************************************

; copy a file
;
; input:
;
; bx = pointer to copy buffer
; cx = copy buffer size in bytes
; si = pointer to source path\filename
; di = pointer to destination path\filename

;***********************************************************************

source: dw ?
destination: dw ?
read_handle: dw ?
write_handle: dw ?
file_time: dw ?
file_date dw ?
file_attr: dw ?
bytes_read: dw ?
copy_buffer_size: dw ?
copy_buffer: dw ?

; file copy messages

file_not_found:

db " - error opening input file",00Dh,00Ah
db "$"

file_create_error:

db " - error creating output file",00Dh,00Ah
db "$"

file_read_error:

db " - error reading file",00Dh,00Ah
db "$"

file_write_error:

db " - error writing file",00Dh,00Ah
db "$"

file_copy:
mov word ptr [copy_buffer],bx
mov word ptr [copy_buffer_size],cx
mov word ptr [source],si
mov word ptr [destination],di
mov dx,word ptr [source]
mov ah,3dh
xor al,al

int 21h ; open source file

mov word ptr [read_handle],ax

jnc file_open

; display file not found message

mov dx,offset cr_lf

call write_message

mov dx,word ptr [source]

call write_message

mov dx,offset file_not_found

call write_message

jmp load_error
file_open:
mov ax,5700h
mov bx,word ptr [read_handle]

int 21h ; get file time and date

mov word ptr [file_time],cx
mov word ptr [file_date],dx
mov ax,4300h
mov dx,word ptr [source]

int 21h ; get file attributes

mov word ptr [file_attr],cx
mov al,byte ptr [drive_number]
mov cx,0000h
mov dx,word ptr [destination]
mov ah,3ch

int 21h ; create destination file

mov word ptr [write_handle],ax

jnc copy_cmd

; display file not created message

mov dx,offset cr_lf

call write_message

mov dx,word ptr [destination]

call write_message

mov dx,offset file_create_error

call write_message

jmp copy_error
copy_cmd:
call read_file

jnc file_read_ok

; display file read error message

mov dx,offset cr_lf

call write_message

mov dx,word ptr [source]

call write_message

mov dx,offset file_read_error

call write_message

jmp copy_error
file_read_ok:
call write_file

jnc file_write_ok

; display file write error message

mov dx,offset cr_lf

call write_message

mov dx,word ptr [destination]

call write_message

mov dx,offset file_write_error

call write_message

jmp copy_error
file_write_ok:
cmp ax,word ptr [copy_buffer_size]

je copy_cmd

mov bx,word ptr [read_handle]
mov ah,3eh

int 21h ; close read_file

mov ax,5701h
mov bx,word ptr [write_handle]
mov cx,word ptr [file_time]
mov dx,word ptr [file_date]

int 21h ; set file time and date

mov bx,word ptr [write_handle]
mov ah,3eh

int 21h ; close write_file

mov ax,4301h
mov cx,word ptr [file_attr]
mov dx,word ptr [destination]

int 21h ; set file attributes

clc
ret
copy_error:
stc
ret

;***********************************************************************

; issue a file copy error message

;***********************************************************************

write_message:
mov ah,09h

int 21h

ret

;***********************************************************************

; read file block into buffer

;***********************************************************************

read_file:
mov cx,word ptr [copy_buffer_size]
mov bx,word ptr [read_handle]
mov dx,word ptr [copy_buffer]
mov ah,3fh

int 21h

mov word ptr [bytes_read],ax
mov cx,ax
ret

;***********************************************************************

; write file block from buffer

;***********************************************************************

write_file:
mov bx,word ptr [write_handle]
mov dx,word ptr [copy_buffer]
mov ah,40h

int 21h

ret

;***********************************************************************

; boot sector data (track 0, head 0, sector 1)

;***********************************************************************

boot_record:

;***********************************************************************

.8086 ; enable the 8086 instruction set

;***********************************************************************

jmp boot_strap ; skip over data areas

;***********************************************************************

; DOS data area

;***********************************************************************

oem_name: db "FMT 1.00"
bytes_sector: dw 512
sectors_cluster: db ? ; filled in before writing boot
reserved_sectors: dw 1
fats: db 2
directory_size: dw ? ; filled in before writing boot
small_total: dw ? ; filled in before writing boot
descriptor: db ? ; filled in before writing boot
sectors_fat: dw ? ; filled in before writing boot
sectors_track: dw ? ; filled in before writing boot
heads: dw 2
hidden_sectors: dd 0
big_total: dd 0
physical_drive: db 0
reserved: db 0
extended_boot: db 029h
sn_low: dw ? ; filled in before writing boot
sn_high: dw ? ; filled in before writing boot
volume_label: db "NO NAME "
fat_type: db "FAT12 "

;***********************************************************************

; bootstrap program data area

;***********************************************************************

sectors_directory: db ? ; filled in before writing boot
dir_start: dd ? ; filled in before writing boot
data_start: dd ? ; filled in before writing boot
track: dw ? ; boot program variable
head: db ? ; boot program variable
sector: db ? ; boot program variable
disk_table: db 11 dup (?) ; filled in before writing boot

bios_name: db "IBMBIO COM"

dos_name: db "IBMDOS COM"

; boot program messages
reset_message:
db 00Dh,00Ah,00Ah
db "Disk controller error ..."
db 000h

system_message:
db 00Dh,00Ah,00Ah
db "No system on disk or disk read error ..."
db 000h

retry_message:
db 00Dh,00Ah,00Ah
db "Press any key to retry boot."
db 000h

;***********************************************************************

boot_strap:
; temporarily disable interrupts

cli

; set the stack segment and the extra segment to 0000
; DOS loads the boot record at 0000:7c00,
; so put the stack just below it

xor ax,ax
mov es,ax
mov ss,ax
mov sp,7c00h

assume es:0000h,ss:0000h

; set up the parameters used by the BIOS program loader

lds si,es:[0078h]
mov bx,0078h

; save current disk parameter table

push ds
push si
push ss
push bx

; set the data segment to 0000

mov ds,ax

assume ds:0000h

; use the disk parameter table in the floppy boot record

mov word ptr [bx],7c00h+disk_table-boot_record
mov word ptr [bx+02],ax

; enable interrupts

sti

; reset the disk controller

int 13h

jnc reset_ok

; display reset error message

mov si,7c00h+offset reset_message-offset boot_record

call write_string

jmp not_bootable
reset_ok:
; get directory start sector (absolute sector number)

mov ax,word ptr ds:[7c00h+dir_start-boot_record]
mov dx,word ptr ds:[7c00h+dir_start-boot_record+2]

; get track, head, and sector

call calculate_ths

jnc dir_sector_ok

; display system error message

mov si,7c00h+offset system_message-offset boot_record

call write_string

jmp not_bootable
dir_sector_ok:
; set the offset of the disk read buffer

mov bx,0500h

; read the first directory sector

call read_disk

jc not_bootable

; check directory for the BIOS file
; (it must be the first directory entry)

mov di,bx
mov cx,11
mov si,7c00h+offset bios_name-offset boot_record

rep cmpsb

jz dir_read_ok

; display system error message

mov si,7c00h+offset system_message-offset boot_record

call write_string

jmp not_bootable
dir_read_ok:
; check directory for the DOS file
; (it must be the second directory entry)

lea di,[bx+32]
mov si,7c00h+offset dos_name-offset boot_record
mov cx,11

rep cmpsb

; valid directory, attempt to boot from the disk

jz system_found

; display system error message

mov si,7c00h+offset system_message-offset boot_record

call write_string

jmp not_bootable

;***********************************************************************

system_found:
; get the data start sector (absolute sector number)

mov ax,word ptr ds:[7c00h+data_start-boot_record]
mov dx,word ptr ds:[7c00h+data_start-boot_record+2]

; set the offset of the disk read buffer

mov bx,0700h

; read 3 sectors (the length of the BIOS program loader)

mov cx,3
read_next:
push ax
push cx
push dx

; get track, head, and sector

call calculate_ths

jnb ok_to_read

; clean up the stack

pop ax
pop ax
pop ax

; display system error message

mov si,7c00h+offset system_message-offset boot_record

call write_string

jmp not_bootable
ok_to_read:
call read_disk

pop dx
pop cx
pop ax

jnc disk_read_ok

; display system error message

mov si,7c00h+offset system_message-offset boot_record

call write_string

jmp not_bootable
disk_read_ok:
; increment the sector to read

add ax,1
adc dx,0

; bump the offset of the read buffer by the sector size

add bx,word ptr ds:[7c00h+bytes_sector-boot_record]

loop read_next

; set up the parameters for the BIOS program loader

; get the media descriptor

mov ch,byte ptr ds:[7c00h+descriptor-boot_record]

; get the drive number

mov dl,byte ptr ds:[7c00h+physical_drive-boot_record]

; get the data start sector (absolute sector number)

mov ax,word ptr ds:[7c00h+data_start-boot_record+2]
mov bx,word ptr ds:[7c00h+data_start-boot_record]

; execute the BIOS program loader

jmp far ptr program_loader

;***********************************************************************

not_bootable:
; display retry message

mov si,7c00h+offset retry_message-offset boot_record

call write_string

; wait for a key to be pressed

xor ah,ah

int 16h

; clean up the stack

pop si
pop ds
pop [si]
pop [si+2]

; try to boot the system again

int 19h

;***********************************************************************

; bootstrap subroutines

;***********************************************************************

write_string:
; get one character

lodsb

; check for end of ASCIIZ string

or al,al

jnz next_char

ret
next_char:
; write one character to the screen

mov ah,0eh

; use video page 0, normal white

mov bx,0007h

int 10h

jmp write_string

;***********************************************************************

read_disk:
; get the track number

mov dx,word ptr ds:[7c00h+track-boot_record]

; shift the upper 2 bits of the track number
; into the upper 2 bits of the sector number

mov cl,06
shl dh,cl

; get the sector number

or dh,byte ptr ds:[7c00h+sector-boot_record]

mov cx,dx
xchg ch,cl

; get the drive number

mov dl,byte ptr ds:[7c00h+physical_drive-boot_record]

; get the head number

mov dh,byte ptr ds:[7c00h+head-boot_record]

; read one sector from the disk

mov ax,0201h

int 13h

ret

;***********************************************************************

calculate_ths:
; check for valid absolute sector number

cmp dx,word ptr ds:[7c00h+sectors_track-boot_record]

jb ths_ok

stc
ret
ths_ok:
; calculate the sector number

div word ptr ds:[7c00h+sectors_track-boot_record]
inc dl

; store the sector number

mov byte ptr ds:[7c00h+sector-boot_record],dl

; calculate the head number and the track number

xor dx,dx
div word ptr ds:[7c00h+heads-boot_record]

; store the head number

mov byte ptr ds:[7c00h+head-boot_record],dl

; store the track number

mov word ptr ds:[7c00h+track-boot_record],ax

clc
ret

;***********************************************************************

; adjust the boot record size to 512 bytes

;***********************************************************************

fill: db (512-(offset fill-offset boot_record)-2) dup (0)

;***********************************************************************

; boot sector signature

;***********************************************************************

signature: dw 0AA55h

;***********************************************************************

; end of boot sector data

;***********************************************************************

;***********************************************************************

; FAT and directory data

;***********************************************************************

; the first FAT sector has the media descriptor byte
fat_record:
db ? ; filled in before writing FAT
db 0ffh,0ffh
db 509 dup (0)

; other FAT sectors and directory sectors are all zeros
fat_dir_record:
db 512 dup (0)

;***********************************************************************

; copyright information

;***********************************************************************

version: db "FMT version 1.00 23-JAN-1990",000h

copyright: db "Copyright (C) 1990 by Clair Alan Hardesty",000h

;***********************************************************************

; put file copy buffer after code and other data

;***********************************************************************

file_buffer:
; buffer space starts here

cseg ends

end entry_point

;***********************************************************************

; end of Fmt.asm

;***********************************************************************


  3 Responses to “Category : Utilities for DOS and Windows Machines
Archive   : FMTA100.ZIP
Filename : FMT.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/