Category : Files from Magazines
Archive   : VOL11N15.ZIP
Filename : REDD.ASM

 
Output of file : REDD.ASM contained in archive : VOL11N15.ZIP
;====================================================================
; REDD - Remote Exec Device Driver
;
; Copyright (c) 1992 Douglas Boling
;====================================================================
page 66,132
;--------------------------------------------------------------------
; BIOS Data segment
;--------------------------------------------------------------------
bios_data segment at 40h
org 17h
shift_state db ? ;State of shift keys
org 1Ah
keybuff_head dw ? ;Start ptr for key buff
keybuff_tail dw ? ;End ptr for key buff

org 4Eh
video_buffoff dw ? ;Offset of video buffer
org 63h
video_ioregs dw ? ;I/O addr of video ctlr
org 80h
keybuff_start dw ? ;Start ptr for keybuff
keybuff_end dw ? ;End ptr for keybuff
video_rows db ? ;Screen rows
bios_data ends

;--------------------------------------------------------------------
; CODE segment
;--------------------------------------------------------------------
code segment
assume cs:code

generic_req struc
Len db ? ;Size of structure
Unit db ?
Function db ? ;Requested function
Status dw ? ;Returned status
Reserved db 8 dup (?)
generic_req ends

init_req struc
irLen db ? ;Size of structure
irUnit db ?
irFunction db ? ;Requested function
irStatus dw ? ;Returned status
irReserved db 8 dup (?)
irUnits db ? ;Number of block drives
irEndAddress dd ? ;End addr of driver
irParmAddress dd ? ;Ptr to cmd line parms
irDriveNumber db ? ;1st drive number
irMessageflag dw ? ;Error word
init_req ends

media_req struc
mrLen db ? ;Size of structure
mrUnit db ?
mrFunction db ? ;Requested function
mrStatus dw ? ;Returned status
mrReserved db 8 dup (?)
mrMediaID db ? ;Media descripter
mrReturn db ? ;return value
mrVolumeID dd ? ;Ptr to volumne ID string
media_req ends

buildbpb_req struc
bbrLen db ? ;Size of structure
bbrUnit db ?
bbrFunction db ? ;Requested function
bbrStatus dw ? ;Returned status
bbrReserved db 8 dup (?)
bbrMediaID db ? ;Media descripter
bbrFATSector dd ? ;Ptr to 1st FAT sector
bbrBPBAddress dd ? ;Ptr to BPB block
buildbpb_req ends

read_req struc
rrLen db ? ;Size of structure
rrUnit db ?
rrFunction db ? ;Requested function
rrStatus dw ? ;Returned status
rrReserved db 8 dup (?)
rrMediaID db ? ;Media descripter
rrBuffer dd ? ;Ptr to data buffer
rrBytesSec dw ? ;Number of sectors to read
rrStartSec dw ? ;Starting sector number
rrVolumeID dd ? ;Ptr to volume ID string
rrHugeStartSec dd ? ;Start sec for >32 Meg drive
read_req ends

;====================================================================
;Device driver header
;====================================================================
org 0 ;Offset 0 for DD

header dd -1 ;Ptr to next driver
dw 0800h ;Attribute word bits
;15 Character device
;14 IOCTL read/write support
;13 (Char) Output till busy
; (Blk) Needs FAT for BPB
;11 Open/Close dev supported
; 7 IOCTL querys supported
; 6 Log drive mapping support
; 4 Fast char input support
; 3 Device is clock device
; 2 Device is NULL device
; 1 (Char) Std out device
; (Blk) 32 bit sector nums
; 0 Device is Std Input dev
dw offset strategy ;Ptr to strategy routine
dw offset interrupt ;Ptr to interrupt routine
db 1,0,0,0,0,0,0,0 ;Num of block devices

program db 10,13,"REDD",10,13
db "Copyright (c) 1992 Douglas Boling",13,10
db "First published in PC Magazine, September 15, 1992"
db 13,10,"$",1Ah
;--------------------------------------------------------------------
;Boot Sector data for our imaginary drive
;--------------------------------------------------------------------
boot_sector = $
jmp short boot_sector_end ;obligitory jmp instruction
nop
db "IBM x.x " ;Stupid IBM tag for DOS 4
BPB_start = $
BytesPerSec dw 200h ;512 bytes per sector
SecPerCluster db 1 ;One sec per cluster
ResSectors dw 1 ;Reserved sectors
NumFATs db 1 ;Number of File Alloc tables
RootDirEntries dw 8 ;Num of entries in root dir
Sectors dw 8 ;Total number of sectors
Media db 0F0h ;Media descriptor byte
FATSectors dw 1 ;Number of sectors per FAT
SecPerTrack dw 8 ;Num sectors per track
Heads dw 1 ;Num of heads
HiddenSectors dd 0 ;Num hidden sectors
HugeSectors dd 0 ;Num of sec if > 32 Meg

DriveNumber db 0 ;Used by DOS
Reserved1 db 0 ;Used by DOS
BootSignature db 29h ;IDs boot sector format
VolumeID dd 12345678h ;Volume ID number
VolumeLabel db "REDD " ;ASCII volume label
FileSysType db "FAT12 " ;FAT system used
boot_sector_end = $
;
;Data needed for the driver
;
req_header_ptr dd 0 ;Ptr to request header
bpb_array dw offset BPB_start ;Array of BPB pointers
keyname db "KEYBOARDIN " ;Name of keyboard file
volume_name db "REDD ",0 ;ASCIIZ string of vol name

cr_flag db 1 ;Append CR to video LFs
even
sys_year db 0 ;Time needed to set
sys_month db 0 ; the time and date for
sys_day db 0 ; screen file.
sys_hours db 0
sys_minutes db 0
sys_seconds db 0
timer_low dw 0 ;Timer ticks since last
timer_high dw 0 ; GetSysTime call.
scrtick_low dw 0 ;Tick count at last screen
scrtick_high dw 0 ; write.


int08_active dw -1 ;Interrupt 8 active flag
int08h dd -1 ;Old Timer Interrupt
int10h dd -1 ;Old Video Interrupt
ScreenHead dd -1 ;Head of screen buffer queue
ScreenTop dw -1 ;Top of screen buffer
ScreenBot dw -1 ;End of screen buffer
ScreenTxtSec dw 2 ;Screen file num of sectors

fileopen_count dw 0 ;Number of opened files

root_update db 0 ;Indicates change in Root dir
paste_flag db 0
pastedata_ptr dw 0
pastedata_end dw 0
fpclust_size dw 0
pastecluster dw 0
pastedirent_ptr dw 0

FATPtr dw 0 ;Ptr to FAT table
FATSize dw 0 ;Sectors * 1.5
RootSize dw 0 ;Root entries * 32
DataPtr dw ? ;Ptr to data sector start

jmptable dw offset init ;0 Initialize driver
dw offset media_check ;1 Block device media check
dw offset build_bpb ;2 Build BIOS parameter blk
dw offset not_implimented ;3 I/O control read
dw offset read ;4 Read
dw offset not_implimented ;5 Non-destructive read
dw offset not_implimented ;6 Get input status
dw offset not_implimented ;7 Flush input
dw offset write ;8 Write
dw offset write ;9 Write with verify
dw offset not_implimented ;A Get output status
dw offset not_implimented ;B Output flush
dw offset not_implimented ;C I/O control write
dw offset open_device ;D Open device
dw offset close_device ;E Close device
dw offset removable_media ;F Removable media check
dw offset not_implimented ;10 Output until busy
dw offset not_implimented ;11 Reserved
dw offset not_implimented ;12 Reserved
dw offset not_implimented ;13 Generic I/O control
dw offset not_implimented ;14 Reserved
dw offset not_implimented ;15 Reserved
dw offset not_implimented ;16 Reserved
dw offset not_implimented ;17 Get logic drive mapping
dw offset not_implimented ;18 Set logic drive mapping
dw offset not_implimented ;19 I/O control query
jmptable_end = $
max_cmd equ (offset jmptable_end - offset jmptable) shr 1
;====================================================================
;STRATEGY - Handles strategy calls from DOS by copying the request
; header pointer into an internal buffer.
;====================================================================
strategy proc far
assume cs:code,ds:nothing,es:nothing
mov word ptr cs:[req_header_ptr],bx
mov word ptr cs:[req_header_ptr+2],es
ret
strategy endp
;====================================================================
;INTERRUPT - Handles interrupt calls from DOS by implimenting the
; device driver functions
;====================================================================
interrupt proc far
assume cs:code,ds:nothing,es:nothing
push ax
push bx
push cx
push dx
push di
push si
push bp
push ds
push es
pushf
cld ;All string operations UP
mov di,cs
mov ds,di
assume ds:code

les di,req_header_ptr ;Get ptr to request header
xor bx,bx
mov bl,es:[di.Function] ;Get requested function
cmp bl,max_cmd
mov ax,8003h ;Load error status
ja interrupt_exit

nop


shl bx,1
call [bx+jmptable] ;Call proper routine
push ax
cmp cs:root_update,0
je interrupt_1
call check_root
interrupt_1:
pop ax
les di,req_header_ptr ;Get ptr to request header
or ax,0100h ;Set done bit
interrupt_exit:
mov es:[di.Status],ax ;Save status in drvr header
popf
pop es
pop ds
pop bp
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
interrupt endp

;--------------------------------------------------------------------
;MEDIA CHECK - Media check function allows DOS to determine if the
; disk type in the drive has changed.
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
media_check proc near
assume cs:code,ds:code,es:nothing
mov es:[di.mrReturn],0 ;Media may have been changed
mov word ptr es:[di.rrVolumeID],offset volume_name
mov word ptr es:[di.rrVolumeID+2],cs
not_implimented:
xor ax,ax ;Clear return code
ret
media_check endp

;--------------------------------------------------------------------
;BUILD BPB - Build BIOS Parameter Block.
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
build_bpb proc near
assume cs:code,ds:code,es:nothing
mov word ptr es:[di.bbrBPBAddress],offset BPB_start
mov word ptr es:[di.bbrBPBAddress+2],cs
xor ax,ax
ret
build_bpb endp

;--------------------------------------------------------------------
;READ - Reads sectors from the block device
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
read proc near
assume cs:code,ds:code,es:nothing
mov bx,es:[di.rrStartSec]
mov cx,es:[di.rrBytesSec]
push cx
push di
push es
les di,es:[di.rrBuffer]



nop



read_1:
call read_sector ;'Read' a sector
inc bx ;Inc starting sector
loop read_1 ;Read again if not done

pop es ;Set output fields and term
pop di
pop cx
mov es:[di.rrBytesSec],cx
mov word ptr es:[di.rrVolumeID],offset volume_name
mov word ptr es:[di.rrVolumeID+2],cs
xor ax,ax
ret
read endp

;--------------------------------------------------------------------
;WRITE - Writes sectors from the block device
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
write proc near
assume cs:code,ds:code,es:nothing
mov bx,es:[di.rrStartSec]
mov cx,es:[di.rrBytesSec]
push cx
push si
push ds
lds si,es:[di.rrBuffer]


nop



write_1:
call write_sector ;'Write' a sector
inc bx ;Inc starting sector
loop write_1 ;Read again if not done

pop ds
pop si
pop cx
mov es:[di.rrBytesSec],cx
mov word ptr es:[di.rrVolumeID],offset volume_name
mov word ptr es:[di.rrVolumeID+2],cs
xor ax,ax
ret
write endp

;--------------------------------------------------------------------
;OPEN DEVICE - Indicates that a file has been opened on the drive
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
open_device proc near
assume cs:code,ds:code,es:nothing
inc cs:fileopen_count
xor ax,ax
ret
open_device endp

;--------------------------------------------------------------------
;CLOSE DEVICE - Indicates that a file has been closed on the drive
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
close_device proc near
assume cs:code,ds:code,es:nothing
dec cs:fileopen_count
xor ax,ax
ret
close_device endp

;--------------------------------------------------------------------
;REMOVABLE MEDIA - Informs DOS whether the drive is removable
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
removable_media proc near
assume cs:code,ds:code,es:nothing
xor ax,ax ;Bit 9 = 0 - drive removable
ret
removable_media endp

;--------------------------------------------------------------------
;READ SECTOR - Simulates a read of a mythical disk sector
;Entry: BX - Starting sector
; ES:DI - Ptr to data buffer to read data
;Exit: ES:DI - Points to byte beyond last data read out to DOS
;--------------------------------------------------------------------
read_sector proc near
assume cs:code,ds:code,es:nothing
push bx
push cx
cmp bx,1 ;Check what sector to read
jb read_boot
je read_FAT
sub bx,3
jb read_root

cmp bx,ScreenTxtSec ;See if reading SCREEN.TXT
jb read_screen

call getdata_ptr ;Compute buff for sector
mov si,bx
mov cx,BytesPerSec
jmp short read_sector_1
read_screen:
mov dx,BytesPerSec
xchg bx,dx
mov si,word ptr ScreenHead ;Read this sector as a
mov ax,bx ; rotating buffer. The
mul dx ; ScreenHead ptr points
add si,ax ; to the start of the
mov cx,ScreenBot ;See if starting past end
cmp si,cx ; of buffer.
jb read_screen_0
sub si,cx ;Yes, wrap ptr to buff start
add si,ScreenTop
read_screen_0:
sub cx,si ;Compute len till end of buff
sub bx,cx ;Sub read len from total
jae read_screen_1 ;If read len more than total,
mov cx,BytesPerSec ; change read len to total
xor bx,bx ;Clear total.
read_screen_1:
rep movsb
mov si,ScreenTop
mov cx,bx
jcxz read_sector_exit
rep movsb
jmp short read_sector_exit
read_boot:
mov si,offset boot_sector
mov cx,offset boot_sector_end - offset boot_sector
jmp short read_sector_1
read_FAT:
mov si,FATPtr
mov cx,FATSize
jmp short read_sector_1
read_root:
mov si,offset root_dir
call set_time ;Set time for screen file
mov cx,RootSize
read_sector_1:
mov dx,BytesPerSec ;Copy data
sub dx,cx ;See how much is left for
rep movsb ; a complete sector
xor al,al
mov cx,dx ;Fill in remainder of
jcxz read_sector_exit ; sector with zeros.
rep stosb
read_sector_exit:
pop cx
pop bx
ret
read_sector endp

;--------------------------------------------------------------------
;WRITE SECTOR - Simulates a write of a mythical disk sector
;Entry: BX - Starting sector
; DS:SI - Ptr to data buffer
;Exit: DS:SI - Points to byte beyond last data read into drive
;--------------------------------------------------------------------
write_sector proc near
assume cs:code,ds:nothing,es:nothing
push bx
push cx
push di
push es
mov ax,cs
mov es,ax
assume es:code

cmp bx,1 ;Check what sector to write
jb write_boot
je write_FAT
sub bx,3
jb write_root

call getdata_ptr ;Compute buff for sector
mov di,bx
mov cx,BytesPerSec
jmp short write_sector_1
write_boot:
mov di,offset boot_sector
mov cx,offset boot_sector_end - offset boot_sector
jmp short write_sector_1
write_FAT:
mov di,cs:FATPtr
mov cx,cs:FATSize
jmp short write_sector_1
write_root:
mov di,offset root_dir
mov cx,cs:RootSize
inc cs:root_update
write_sector_1:
rep movsb
write_sector_exit:
pop es
pop di
pop cx
pop bx
ret
write_sector endp

;--------------------------------------------------------------------
;GETDATA PTR - Returns the offet in RAM for a given data sector
;Entry: BX - Cluster - 2
;Exit: BX - Ptr to data
;--------------------------------------------------------------------
getdata_ptr proc near
assume cs:code,ds:nothing,es:nothing
push ax
push dx
mov ax,bx ;Copy starting data sec
mul cs:BytesPerSec ;Mul by size of data sec
mov bx,ax ;Add starting offset of
add bx,cs:DataPtr ; data buffer.
pop dx
pop ax
ret
getdata_ptr endp

;--------------------------------------------------------------------
;CHECK ROOT - Checks changes in the root directory
;--------------------------------------------------------------------
check_root proc near
assume cs:code,ds:nothing,es:nothing
push ds
push es
mov ax,cs
mov ds,ax
mov es,ax
assume cs:code,ds:code,es:code
mov root_update,0 ;Clear flag
cmp paste_flag,0 ;Don't bother if we are
jne check_root_exit ; already pasting.
mov si,offset root_dir
mov cx,RootDirEntries
mov di,offset keyname
check_root_1:
push cx ;Scan through root looking
push si ; for the name of the
push di ; keyboard file.
mov cx,11
repe cmpsb
pop di
pop si
pop cx
je check_root_2
add si,32
loop check_root_1
jmp short check_root_exit
check_root_2:
xor bx,bx
or bx,[si+1ah] ;See if starting cluster set
je check_root_exit
mov cx,word ptr [si+1ch] ;Get file size
or cx,cx
je check_root_exit ;If 0, exit
mov ax,cx
xor dx,dx
div BytesPerSec ;Compute number of sectors
mov fpclust_size,dx ; and size of last sector.
mov pastedirent_ptr,si
mov pastecluster,bx
call next_pasteclust ;Compute pointers to sector
mov paste_flag,1 ;Allow paste
check_root_exit:
pop es
pop ds
ret
check_root endp

;-------------------------------------------------------------------------
;DELETE FILE - Deletes a file from the driver disk
;Entry: SI - Pointer to directory entry for file
;-------------------------------------------------------------------------
delete_file proc near
assume cs:code,ds:code,es:nothing
push cx
xor ax,ax
mov bx,[si+1ah] ;Get starting cluster
delete_file_1:
mov cx,bx
call get_fat_entry
xchg bx,cx
call set_fat_entry ;Zero entry
mov bx,cx
cmp bx,0fffh ;See if last entry
jne delete_file_1

mov byte ptr [si],0e5h ;Clear name
pop cx
ret
delete_file endp

;-------------------------------------------------------------------------
; GET FAT ENTRY - Returns the contents of a 12 bit FAT entry
; Entry: BX - Entry into FAT table
; Exit: BX - Next entry
;-------------------------------------------------------------------------
get_fat_entry proc near
assume cs:code,ds:code,es:nothing
push ax
push di

mov di,FATPtr
add di,bx
shr bx,1 ;12 bit FAT
mov ax,ds:[bx+di]
jnc get_fat_entry_2
shr ax,1
shr ax,1
shr ax,1
shr ax,1
get_fat_entry_2:
and ah,0fh ;Clear top nibble
get_fat_entry_3:
mov bx,ax ;Copy entry data
pop di
pop ax
ret
get_fat_entry endp

;-------------------------------------------------------------------------
; SET FAT ENTRY - Writes a 12 bit FAT table entry
; Entry: BX - Pointer to fat table entry
; AX - Data to write to FAT table
;-------------------------------------------------------------------------
set_fat_entry proc near
assume cs:code,ds:code,es:nothing
push ax
push bx
push di

mov di,FATPtr
add di,bx
shr bx,1 ;12 bit FAT
pushf
add di,bx
popf
mov bx,ds:[di] ;Get data
jc set_fat_1 ;Jump if odd
and bx,0f000h ;Remove old data
jmp short set_fat_2
set_fat_1:
and bx,000fh ;Remove old data
shl ax,1
shl ax,1
shl ax,1
shl ax,1
set_fat_2:
or ax,bx
mov ds:[di],ax ;Write data
pop di
pop bx
pop ax
ret
set_fat_entry endp

;====================================================================
;TIMER INT - Interrupt 8h timer hook. This routine keeps the time
; and, when necessary, pastes data into the keyboard buff
;====================================================================
timerint proc far
assume cs:code,ds:nothing,es:nothing
pushf
add word ptr cs:timer_low,1
adc word ptr cs:timer_high,0
cmp cs:paste_flag,0
jne timerint_1
timerint_exit:
popf
jmp cs:[int08h] ;Jmp to old interrupt
timerint_1:
inc cs:int08_active
jne timerint_exit2
push ax
push ds
mov ax,cs
mov ds,ax
assume ds:code
timerint_2:
call push_key
jc timerint_exit1
cmp paste_flag,0
jne timerint_2
timerint_exit1:
pop ds
pop ax
timerint_exit2:
dec cs:int08_active
jmp short timerint_exit
timerint endp

;-----------------------------------------------------------------------------
; PUSH KEY Fills the keyboard buffer with data
; Exit: CF - Set if keyboard buffer full
; AX - modified
;-----------------------------------------------------------------------------
push_key proc near
assume ds:nothing,es:nothing
push bx
push di
push si
push es
cld ;String moves UP
mov ax,bios_data
mov es,ax
assume es:bios_data
cli ;No interrupts
mov di,es:[keybuff_tail]
push di
call inckeyptr
cmp di,es:[keybuff_head] ;See if buffer full
pop di
stc
je push_key_exit

mov si,pastedata_ptr
lodsb ;Get character to paste
cmp si,pastedata_end
jb push_key_3
push ax
mov bx,pastecluster ;See if cluster is the last
call get_fat_entry
cmp bx,0fffh
je push_key_1
mov pastecluster,bx
call next_pasteclust ;Compute ptrs for next sector
jmp short push_key_2
push_key_1:
mov paste_flag,0 ;Disable paste
mov si,pastedirent_ptr ;Delete paste file
call delete_file
push_key_2:
pop ax
push_key_3:
mov pastedata_ptr,si
or al,al ;Don't stuff null char
je push_key_5
jns push_key_31
and ax,007fh ;Remove sign bit, clear AH
xchg ah,al ;Place char in scan code
jmp short push_key_4
push_key_31:
cmp al,0ah ;Don't stuff line feeds
je push_key_5
cmp al,1ah ;Don't stuff End Of File char
je push_key_5
xor ah,ah ;Clear scan code
cmp al,0dh ;If CR character, add proper
jne push_key_4 ; scan code for Word Perfect
mov ah,1ch
push_key_4:
mov es:[di],ax ;Don't use STOSW, ptr must
call inckeyptr ; be updated by inckeyptr
mov es:[keybuff_tail],di ;Save keybuff ptr
push_key_5:
clc
push_key_exit:
pop es
pop si
pop di
pop bx
ret
push_key endp

;--------------------------------------------------------------------
;NEXT PASTECLUST - Sets the paste variables for a sector
;Entry: BX - new sector
;--------------------------------------------------------------------
next_pasteclust proc near
push dx
push bx
call get_fat_entry
mov dx,BytesPerSec
cmp bx,0fffh
jne next_pc_1
mov dx,fpclust_size
next_pc_1:
pop bx
sub bx,2
call getdata_ptr
mov pastedata_ptr,bx
add bx,dx
mov pastedata_end,bx
pop dx
ret
next_pasteclust endp

;-----------------------------------------------------------------------------
; INCKEYPTR Incriments the keyboard buffer pointer
; Entry: DI - Current Keyboard tail pointer
;-----------------------------------------------------------------------------
inckeyptr proc near
assume es:bios_data
inc di ;Make room in buffer
inc di
cmp di,es:[keybuff_end] ;Get ptr to end of buffer
jne inckeyptr_1
mov di,es:[keybuff_start] ;Get ptr to buffer offset
inckeyptr_1:
ret
inckeyptr endp

;====================================================================
;VID INT - Interrupt 10h video hook. This routine monitors and
; records any BIOS writes to the screen into the 'file'
; SCREEN.TXT.
;====================================================================
vidint proc far
assume cs:code,ds:nothing,es:nothing
cmp ah,9
jae vidint_1
vidint_exit:
jmp cs:[int10h] ;Jmp to old interrupt
vidint_1:
push cx
push di
push es

cmp ah,09h
je vidint_wrtchr1
cmp ah,0ah
je vidint_wrtchr1
cmp ah,0eh
je vidint_wrtchr
cmp ah,13h
jne vidint_exit1
push ax
push si
push ds
mov si,es
mov ds,si
mov si,bp ;Copy ptr to string

les di,cs:ScreenHead ;Get ptr to buffer
mov ah,al
vidint_2:
jcxz vidint_4
lodsb ;Read character
call save_char ;Store character
cmp ah,2
jb vidint_3
inc si ;Skip past attribute
vidint_3:
loop vidint_2
vidint_4:
pop ds
pop si
pop ax
jmp short vidint_5
vidint_wrtchr:
mov cx,1
vidint_wrtchr1:
les di,cs:ScreenHead ;Get ptr to buffer
jcxz vidint_5
call save_char ;Save character
loop vidint_wrtchr1
vidint_5:
mov word ptr cs:ScreenHead,di
pushf
cli
mov di,cs:timer_low ;Mark last time screen
mov cx,cs:timer_high ; updated.
mov cs:scrtick_low,di
mov cs:scrtick_high,cx
popf
vidint_exit1:
pop es
pop di
pop cx
jmp vidint_exit
vidint endp

;--------------------------------------------------------------------
;SAVE CHAR - Saves a character into the SCREEN.TXT file
;--------------------------------------------------------------------
save_char proc near
assume cs:code,ds:nothing,es:code
cmp al,13 ;See if CR
je save_char_2
cmp al,10
je save_char_3
save_char_0:
stosb
save_char_01:
cmp di,cs:ScreenBot
jae save_char_1
ret
save_char_1:
mov di,cs:ScreenTop
ret
save_char_2:
mov cs:cr_flag,0
jmp short save_char_0
save_char_3:
cmp cs:cr_flag,0
je save_char_0
stosb
mov al,13
stosb
mov al,10
jmp short save_char_01
ret
save_char endp

;--------------------------------------------------------------------
;INIT TIMER - Calls the BIOS to retrieve the system time
;--------------------------------------------------------------------
init_timer proc near
assume cs:code,ds:code,es:nothing
push bx
mov ah,2 ;Get system time
int 1ah
mov al,ch
call un_bcd
mov sys_hours,al
mov al,cl
call un_bcd
mov sys_minutes,al
mov al,dh
call un_bcd
mov sys_seconds,al
mov ah,4 ;Get system time
int 1ah
mov al,cl
call un_bcd
xor ah,ah
cmp ch,19 ;See if next century
je init_timer_1
add ax,100
init_timer_1:
sub ax,80 ;Convert to relative date
mov sys_year,al
mov al,dh
call un_bcd
mov sys_month,al
mov al,dl
call un_bcd
mov sys_day,al
pushf
cli
mov timer_low,0
mov timer_high,0
popf
pop bx
ret
init_timer endp

;--------------------------------------------------------------------
;SET TIME - Sets the time of file in the directory
;Entry: SI - Pointer to the directory entry
;--------------------------------------------------------------------
set_time proc near
assume cs:code,ds:code,es:nothing
mov ax,scrtick_low
mov dx,scrtick_high
call compute_elapsed

add al,sys_seconds
cmp al,60
jb set_time_1
inc cl
sub al,60
set_time_1:
add cl,sys_minutes
cmp cl,60
jb set_time_2
inc ch
sub cl,60
set_time_2:
add ch,sys_hours
cmp ch,24
jb set_time_3
inc dh
sub ch,24
set_time_3:
shr al,1 ;Divide seconds by 2
and ax,1fh
mov bh,cl ;Get minutes
and bx,3f00h
shr bx,1
shr bx,1
shr bx,1
or ax,bx
mov bh,ch ;Get hours
shl bx,1
shl bx,1
shl bx,1
and bx,0f800h
or ax,bx
mov [si+16h],ax ;Save time in dir entry
mov al,sys_day
mov cl,sys_month
mov ch,sys_year
or dh,dh
je set_time_4
call inc_date ;Inc to next day
set_time_4:
and ax,3fh
shl cl,1
shl cl,1
shl cl,1
shl cl,1
shl cx,1
or ax,cx
mov [si+18h],ax ;Save date in dir entry
ret
set_time endp

;--------------------------------------------------------------------
;COMPUTE ELAPSED - Computes the elapsed time from a 32 bit timer tick
; count.
;Entry: AX,DX - Timer tick count
;Exit: DH - Days
; CH - Hours
; CL - Minutes
; DL - Seconds
;--------------------------------------------------------------------
compute_elapsed proc near
assume cs:code,ds:code,es:nothing
push bx
push di
xor bx,bx
mov ch,dl ;Save hours
cmp dl,24 ;If longer than 24 hours,
jb compute_1 ; compute days.
push ax
xor ax,ax
xchg ax,dx
mov di,24
div di
mov bl,al ;Save days
mov dx,ax
mul di
mov ch,al
pop ax
compute_1:
xor dx,dx
mov di,1092 ;Ticks per minute
div di
mov cl,al ;Save minutes
xor ax,ax
xchg ax,dx
mov di,10
mul di
mov di,182
div di
mov dl,al
mov di,ax
mov dh,bl
pop di
pop bx
ret
compute_elapsed endp

;--------------------------------------------------------------------
;INC DATE - Propigates a incrimented date though the month and year.
;Entry: AL - Day
; CL - Month
; CH - Years since 1980
;--------------------------------------------------------------------
inc_date proc near
inc al ;Incriment date
push bx
mov bx,1f1eh ;bh=31,bl=30
cmp cl,7 ;Up till Aug. odd numbered
jbe inc_date_1 ; months have 31 days.
xchg bl,bh ; After, even months have 31
inc_date_1:
test cl,1 ;See if odd month
je inc_date_2 ;No, branch
xchg bl,bh
inc_date_2:
cmp cl,2 ;See if Feb
jne inc_date_3
mov bl,28
test ch,3 ;Leap year if 4 year multiple
jne inc_date_3 ; of 1980. Fails at 2100
mov bl,29 ; since 2100 not a leap year
inc_date_3:
cmp al,bl
jbe inc_date_exit
mov al,1 ;Set to 1st day of the month
inc cl ;Inc month
cmp cl,13 ;See if end of year
jne inc_date_exit
mov cl,1 ;Set to Jan.
inc ch ;Inc year
inc_date_exit:
pop bx
ret
inc_date endp

;--------------------------------------------------------------------
;UN BCD - Returns a binary number for one coded in BCD
;Entry: AL - BCD number
;Exit: AL - Binary number
;--------------------------------------------------------------------
un_bcd proc near
assume cs:code,ds:nothing,es:nothing
push bx
mov bl,al
shr al,1
shr al,1
shr al,1
shr al,1
mov ah,10
mul ah
and bl,0fh
add al,bl
pop bx
ret
un_bcd endp
;--------------------------------------------------------------------
;FINAL INSTALL - Initializes the data structures needed for the drive
;Entry: ES:DI - Point to request header structure
; DX - Size of data sectors
;--------------------------------------------------------------------
final_install proc near
assume cs:code,ds:code,es:nothing
mov di,cs
mov es,di
assume es:code

mov di,offset root_dir + 64
mov cx,RootSize
sub cx,64
xor ax,ax
rep stosb

mov di,FATPtr
mov al,Media ;Initialize FAT
stosb ;First FAT bytes contain
mov ax,-1 ; media descriptor byte
stosw ; followed by FF FF.

mov cx,ScreenTxtSec
mov bx,screen_start
final_install_0:
dec cx
jcxz final_install_01
mov ax,bx
inc ax
call set_fat_entry
mov bx,ax
jmp short final_install_0
final_install_01:
mov ax,-1
call set_fat_entry
final_install_02:
inc bx
cmp bx,Sectors
ja final_install_3
xor ax,ax
call set_fat_entry
jmp short final_install_02
final_install_3:
mov di,DataPtr
mov cx,dx ;Fill 1st data sector for
mov al,' ' ; SCREEN.TXT file. Might
rep stosb ; as well init the rest.

mov ax,3510h ;Get video interrupt vector
int 21h
mov word ptr [int10h],bx
mov word ptr [int10h+2],es
mov ax,2510h ;Set to our handler
mov dx,offset vidint
int 21h
mov ax,3508h ;Get timer interrupt vector
int 21h
mov word ptr [int08h],bx
mov word ptr [int08h+2],es
mov ax,2508h ;Set to our handler
mov dx,offset timerint
int 21h
xor ax,ax ;Clear return code
ret
final_install endp
even ;Keep things on even addrs
;
;Start root directory with entry for screen.txt
;
root_dir db "SCREEN OUT" ;Name
db 1 ;Attribute (Read only)
db 10 dup (0) ;Reserved
screen_time dw 0 ;Time of file
screen_date dw 0 ;Date of file
screen_start dw 2 ;Starting cluster
screen_size dd 0 ;Size of file
volumne_entry db "REDD " ;Name
db 8 ;Attribute (Volume)
db 10 dup (0) ;Reserved
dw 0 ;Time of file
dw 0 ;Date of file
dw 0 ;Starting cluster
dd 0 ;Size of file

end_of_resident = $
;--------------------------------------------------------------------
;Non-resident data
;--------------------------------------------------------------------
initmsg db 13,10,"REDD installed as drive "
initdrv db " :",13,10,10,'$'

;--------------------------------------------------------------------
;INIT - Initializes the device driver
;Entry: ES:DI - Point to request header structure
;--------------------------------------------------------------------
init proc near
assume cs:code,ds:code,es:nothing
mov ah,9 ;Print copyright
mov dx,offset program
int 21h
call init_timer ;Init driver clock

mov bx,offset root_dir
mov ax,32 ;Compute size of root dir
mov dx,RootDirEntries
mul dx
mov RootSize,ax

add bx,ax
mov FATPtr,bx
mov ax,Sectors
mov dx,ax ;Mul sectors by 1.5
shr ax,1
adc ax,dx
mov FATSize,ax
add bx,ax

mov DataPtr,bx
mov word ptr ScreenHead,bx ;Init screen buffer ptrs to
mov word ptr ScreenHead+2,cs ; 1st data sector.
mov ScreenTop,bx
mov ax,ScreenTxtSec
mul BytesPerSec
mov word ptr screen_size,ax
add ax,bx
mov ScreenBot,ax

mov ax,Sectors ;Compute size of data
mul BytesPerSec ; sectors.
mov dx,ax ;Save data sector size
add ax,bx

les di,req_header_ptr ;Get ptr to request header
mov cl,es:[di.irDriveNumber] ; the drive number being
add cl,'A' ; used.
mov initdrv,cl
mov word ptr es:[di.irEndAddress],ax ;Set memory
mov word ptr es:[di.irEndAddress+2],cs ; size
mov word ptr es:[di.irParmAddress],offset BPB_array
mov word ptr es:[di.irParmAddress+2],cs
mov word ptr es:[di.irUnits],1
push dx
mov ah,9 ;Print message indicating
mov dx,offset initmsg ; disk letter.
int 21h
pop dx
jmp final_install
init endp
code ends
end


  3 Responses to “Category : Files from Magazines
Archive   : VOL11N15.ZIP
Filename : REDD.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/