Category : Files from Magazines
Archive   : VOL6N15.ZIP
Filename : DIRNOTES.ASM

 
Output of file : DIRNOTES.ASM contained in archive : VOL6N15.ZIP
; Dirnotes.asm
; FORMAT: DIRNOTES [d][path][directory]

CODE SEGMENT ;*************************;
ASSUME CS:CODE,DS:CODE ;* *;
ORG 100H ;* REMEMBER TO EXE2BIN *;
;* *;
START: JMP BEGINNING ;*************************;

; DATA AREA
; ---------
COPYRIGHT DB 'Copyright 1987 Ziff-Davis Publishing Co.',10,13
PROGRAMMER DB 'Michael J. Mefford',1AH
DIRNOTES DB 'DIRN----.DAT',0
STAR_DOT_STAR DB '*.*',0

CURRENT_DISK DB ?
STATUS_REG DW ?
VIDEO_SEG DW 0B000H
NORMAL DB 07H
INVERSE DB 70H

CURS_POS DW ?
CUR_OFFSET DW OFFSET BUFFER
END_OFFSET DW ?
PAGE_END DW 403+21*160
COUNT DW 1
LINE DW 403

EOF_FLAG DB 0
UPDATE_FLAG DB 0

NOT_ENOUGH DB 'Not enough memory$'
INVALID DB 'Invalid directory$'
TOO_MANY DB 'Too many files$'
LOADING DB 'Loading and sorting directory notes.',0
DIRECTORY DB 'Directory of ',0
FILES DB ' Files',0
STATUS_LINE DB 'Press Esc to exit',0
SAVING DB 'Saving ',0

;----------------------------------------------------------------------------;
; Some housekeeping first. Since we will be changing the default drive ;
; and directory to the requested drive and directory, we need to save the ;
; current defaults, so they can be restored. If less than 64K, exit. ;
;----------------------------------------------------------------------------;

; CODE AREA
; ---------
BEGINNING: CLD
MOV AH,19H ;Get current drive.
INT 21H
MOV CURRENT_DISK,AL ;And save.

MOV SI,OFFSET CURRENT_DIR ;Get current directory.
CALL GET_DIR

CMP SP,65500 ;Do we have 64K?
MOV DX,OFFSET NOT_ENOUGH
JA PARSE
JMP ERROR_EXIT ;If no, exit.

;-----------------------------------------------------------;
; Parse the command line for parameters and append the ;
; DIRNOTES filename with the characters of directory name. ;
;-----------------------------------------------------------;

PARSE: CMP BYTE PTR DS:[80H],0 ;Any parameters?
JZ APPEND ;If no, skip parse.

MOV SI,81H ;Else, point to first character.
NEXT_PARSE: LODSB
CMP AL,13 ;Carriage return?
JZ APPEND ;If yes, done here.
CMP AL,32 ;Leading space?
JBE NEXT_PARSE ;If yes, get next byte.
PUSH SI ;Save start.

NEXT_PARA: LODSB
CMP AL,13 ;End of parameter?
JZ END_PARA ;If yes, done here.
CMP AL,':' ;Drive request?
JNZ NEXT_PARA ;If no, get next byte.
MOV DL,BYTE PTR [SI-2] ;Else, retrieve request.
AND DL,5FH ;Capitalize.
SUB DL,'A' ;Convert to DOS format.
MOV AH,0EH ;And change drive.
INT 21H
JMP SHORT NEXT_PARA ;Find end of parameter.

END_PARA: MOV BYTE PTR DS:[SI-1],0 ;Convert parameter to ASCIIZ.
POP DX ;Retrieve start.
DEC DX ;Adjust.
MOV AH,3BH ;Change directory.
INT 21H
MOV DX,OFFSET INVALID ;Exit if invalid parameter.
JNC APPEND
JMP ERROR_EXIT

APPEND: MOV SI,80H ;Get default directory.
CALL GET_DIR
CLD
NEXT_END: LODSB ;Find end.
CMP AL,0
JNZ NEXT_END
DEC SI
STD ;Reverse direction.
NEXT_START: AND BYTE PTR [SI],5FH ;Capitalize.
LODSB
CMP AL,'\' ;Look for last path.
JNZ NEXT_START
CLD ;Back to forward direction.
INC SI
INC SI
MOV DI,OFFSET DIRNOTES+5 ;Insert three characters of path
MOV CX,3 ; into filename, DIRN----.DAT
STORE_PATH: CMP BYTE PTR [SI],0
JZ DISPLAY
MOVSB
LOOP STORE_PATH

;---------------------------------------------------------------------;
; More housekeeping. We will be writing directly to the screen buffer ;
; so we need the display card address and the status register. ;
;---------------------------------------------------------------------;

DISPLAY: MOV AX,40H ;Point to the ROM BIOS data area
MOV DS,AX ; and get base address of active
MOV AX,DS:[63H] ; display card.
ADD AX,6 ;Add six to get status register
PUSH CS ;Done there, so restore data segment.
POP DS
MOV STATUS_REG,AX ;Store status register.
CMP AX,3BAH ;Status port of MONO card is 3BAh.
JZ MESSAGE ;If that's what we got, it's MONO
MOV VIDEO_SEG,0B800H ; else COLOR so add 800h.
XOR BH,BH ;Get current attribute
MOV AH,8 ; of display page zero.
INT 10H
MOV NORMAL,AH ;Store it.
XOR AH,1110111B ;Flip color bits.
MOV INVERSE,AH ;Save it.

MESSAGE: CALL CLS
MOV SI,OFFSET LOADING ;Display loading message.
MOV DX,0C15H
CALL DISPLAY_TEXT

MOV DI,OFFSET BUFFER ;Fill buffer with spaces.
MOV CX,30000
MOV AX,2020H
REP STOSW

;------------------------------------------------------------------;
; Read all the directory filenames and store as records in buffer. ;
;------------------------------------------------------------------;

READ_DIR: MOV DX,OFFSET STAR_DOT_STAR
MOV CX,6
MOV AH,4EH ;Find first matching.
INT 21H
JNC STORE_NAME
JMP EXIT ;If empty directory, exit.

STORE_NAME: MOV DI,OFFSET BUFFER ;Set up pointers and store
MOV BP,60000 ; first filename.
CALL BUFFER_NAME

FIND_NEXT: MOV AH,4FH ;Find next matching.
INT 21H
JC STORE_COUNT ;If carry, no more names.
INC COUNT ;Inc count of names.
CALL BUFFER_NAME
CMP DI,BP ;Are we encroaching stack?
JB FIND_NEXT ;If no, find next.
MOV DX,OFFSET TOO_MANY ;Else, exit with message.
JMP ERROR_EXIT

;---------------------------------------------;
; Store buffer end address and page end, ;
; number of files then alphabetize filenames. ;
;---------------------------------------------;

STORE_COUNT: MOV END_OFFSET,DI ;Store ending offset.
MOV BX,COUNT

MOV AX,BX
MOV CL,10 ;Convert to decimal.
STD ;Reverse direction.
MOV DI,OFFSET FILES+2 ;Point to storage.
NEXT_COUNT: DIV CL
XCHG AL,AH
ADD AL,'0' ;Convert to ASCII.
STOSB ;Store the remainder.
XCHG AL,AH
XOR AH,AH
CMP AX,0 ;Are we done?
JNZ NEXT_COUNT

CLD ;Back to forward direction.
CMP BX,20 ;Enough to file one page?
JA SORT ;If yes, use default setting.
MOV AX,160 ;Else, calculate last record.
MUL BL
ADD AX,403 ;Add bar offset.
MOV PAGE_END,AX
CMP BX,1 ;Skip sort if only one filename.

JZ OPEN_FILE

SORT: MOV DX,END_OFFSET ;End of filenames in DX.
SUB DX,81
NEXT_PASS: MOV BP,0
MOV BX,OFFSET BUFFER ;Point to start of buffer.

NEXT_SORT: MOV SI,BX ;Put in source and destination
MOV DI,BX ; registers.
ADD DI,81
MOV CX,12
REPZ CMPSB ;Compare filenames.
JBE END_SORT ;If already in order, skip.

MOV SI,BX ;Else, recover pointers.
MOV DI,BX
ADD DI,81
MOV CX,40 ;Exchange the records.
NEXT_SWAP: MOV AX,[DI]
MOVSW
MOV [SI-2],AX
LOOP NEXT_SWAP
MOV BP,1 ;Flag that exchange was made.

END_SORT: ADD BX,81 ;Point to next record.
CMP BX,DX ;End of top?
JB NEXT_SORT ;If no, bubble sort next.
CMP BP,0 ;Was there exchange made?
JZ OPEN_FILE ;If no, done here.
SUB DX,81 ;Else, move top down one record.
JMP SHORT NEXT_PASS

;-------------------------------;
; Attempt to read old dirnotes. ;
;-------------------------------;

OPEN_FILE: MOV DX,OFFSET DIRNOTES ;Open DIRNOTES
MOV AX,3D00H ; for reading.
INT 21H
JC READY ;If not found, skip to display.

MOV BX,AX
PUSH BX ;Save filehandle.
READ_FILE: POP BX
PUSH BX
MOV DX,60000 ;Point above directory listing.
MOV CX,37*81 ;Read up to 37 records at a time.
MOV AH,3FH
INT 21H

CMP AX,0 ;End of file?
JZ CLOSE_FILE ;If yes, done here.
ADD DX,AX
MOV DI,DX ;Else, point to end and tack
MOV BYTE PTR [DI],1AH ; on Ctrl Z as end signature.
CMP AX,37*81 ;Was it a full read?
JZ COMPARE ;If yes, compare records.
MOV EOF_FLAG,1 ;Else, flag as end of file.

;-------------------------------------------------------;
; Here we will match old DIRNOTES with new directory ;
; listing. Notes for deleted files will not find match. ;
;-------------------------------------------------------;

COMPARE: MOV BP,OFFSET BUFFER ;Point to first record.
NEXT_FILE: MOV BX,60000 ;Point to read buffer.
NEXT_MATCH: MOV SI,BX ;Set up source and destination.
MOV DI,BP
MOV CX,6 ;Filename with extension.
REPZ CMPSW ;Compare all 12 characters.
JNZ END_NOTE ;Skip if no match.
ADD SI,28 ; else point to note.
ADD DI,28
MOV CX,20
REP MOVSW ;Store note.

SUB SI,67
SUB DI,67
MOV CX,13
REPZ CMPSW ;Has size or date changed?
JNZ END_MATCH
MOV BYTE PTR [BP+39],32 ;If yes, remove "U".
JMP SHORT END_MATCH ;Skip rest and go to next record.

END_NOTE: ADD BX,81 ;Point to next record.
CMP BYTE PTR DS:[BX],1AH ;Are we at the end?
JNZ NEXT_MATCH ;If no, compare.
END_MATCH: ADD BP,81 ;Point to next record.
CMP BYTE PTR DS:[BP],32 ;End of directory listing?
JNZ NEXT_FILE ;If no, check for matches.
CMP EOF_FLAG,1 ;Else, end of file?
JNZ READ_FILE ;If no, read more.

CLOSE_FILE: POP BX
MOV AH,3EH ;Close file.
INT 21H

;--------------------------------------------;
; Now, we are ready to initialize the screen ;
;--------------------------------------------;

READY: MOV AX,VIDEO_SEG ;Initialize video segment.
MOV ES,AX
MOV DX,4 ;Row 0; column 3.
MOV SI,OFFSET DIRECTORY ;Display "Directory ".
CALL DISPLAY_TEXT
MOV AH,19H
INT 21H ;Get drive.
ADD AL,'A' ;Convert to ASCII.
CALL WRITE_TEXT ;Display it.
MOV AL,':' ;Add colon.
CALL WRITE_TEXT
MOV SI,80H ;Get directory.
CALL GET_DIR
DEC SI
CALL GET_TEXT ;Write it as well.
MOV DX,180EH ;Row 24; column 13.
MOV SI,OFFSET FILES ;Display file count.
CALL DISPLAY_TEXT
MOV DX,1833H ;Row 24; column 50.
MOV SI,OFFSET STATUS_LINE ;Display "Press Esc to exit".
CALL DISPLAY_TEXT
MOV BL,INVERSE ;Put up cursor bar.
CALL BAR
CALL UPDATE_SCREEN ;Display directory listing.
MOV CURS_POS,229H ;Initialize cursor position.

;-----------------------------------------;
; We are ready for business now. We will ;
; loop here, waiting for user keystrokes. ;
;-----------------------------------------;

GET_KEY: CALL SET_CURSOR ;Update cursor position.
MOV AH,0 ;Wait for
INT 16H ; keystroke.

ASCII: CMP AL,32 ;Is it space or above?
JB CR ;If no, skip.
CMP BYTE PTR CURS_POS,79 ;End of line?
JZ GET_KEY ;If yes, skip.
CALL STORE_CHAR ;Else, store the ASCII character.
INC BYTE PTR CURS_POS ;Update cursor.
JMP SHORT GET_KEY

CR: CMP AH,1CH ;Is it carriage return?
JNZ BS
MOV BYTE PTR CURS_POS,41 ;Cursor to beginning of line.
JMP SHORT SCROLL_DOWN ; and scroll down.

BS: CMP AH,0EH ;Backspace?
JNZ LEFT_ARROW
CMP BYTE PTR CURS_POS,41 ;Are we already at beginning?
JZ GET_KEY ;If yes, skip.
DEC BYTE PTR CURS_POS ;Else, cursor left one.
MOV AL,32 ;And replace with space.
CALL STORE_CHAR
JMP SHORT GET_KEY

LEFT_ARROW: CMP AH,4BH ;Left arrow?
JNZ RIGHT_ARROW
CMP BYTE PTR CURS_POS,41 ;Are we already home position?
JZ GET_KEY
DEC BYTE PTR CURS_POS ;If no, back cursor up one.
JMP SHORT GET_KEY

RIGHT_ARROW: CMP AH,4DH ;Right arrow?
JNZ UP_ARROW
CMP BYTE PTR CURS_POS,79 ;Are we already end of line?
JZ GET_KEY
INC BYTE PTR CURS_POS ;Cursor right one.
JMP SHORT GET_KEY

UP_ARROW: CMP AH,48H ;Up arrow?
JNZ DN_ARROW
MOV BP,-160 ;If yes, move bar up one line.
MOV DX,0FF00H ;And also the cursor.
CALL SCROLL_BAR
JMP SHORT GET_KEY

DN_ARROW: CMP AH,50H ;Down arrow?
JNZ PG_UP
SCROLL_DOWN: MOV BP,160 ;If yes, move cursor and bar down.
MOV DX,100H
CALL SCROLL_BAR
JMP GET_KEY

PG_UP: CMP AH,49H ;Page up?
JNZ PG_DN
MOV BP,-81*21 ;If yes, move up 21 lines.
CALL SCROLL
JMP SHORT BOTTOM_BAR ;And move bar to bottom.

PG_DN: CMP AH,51H ;Page down?
JNZ CTRL_PG_UP
MOV BP,81*21 ;If yes, move down 21 lines.
CALL SCROLL
JMP SHORT TOP_BAR ;And move bar to top.

CTRL_PG_UP: CMP AH,84H ;Ctrl PgUp?
JNZ CTRL_PG_DN
TOP_BAR: MOV SI,403 ;If yes, move bar to top.
MOV CURS_POS,229H
JMP SHORT UPDATE_BAR

CTRL_PG_DN: CMP AH,76H ;Ctrl PgDn?
JNZ HOME
BOTTOM_BAR: MOV SI,PAGE_END ;If yes, move bar to bottom.
MOV AX,SI ;Divide page end by 160
SUB SI,160 ; to get cursor row position.
SUB AX,403-160
XOR DX,DX
MOV BX,160
DIV BX
MOV DH,AL
MOV DL,29H
MOV CURS_POS,DX
UPDATE_BAR: CALL MOVE_BAR ;Display updates.
CALL SET_CURSOR
CALL UPDATE_SCREEN
JMP SHORT NEXT_KEY

HOME: CMP AH,47H ;Home?
JNZ END_KEY
MOV CUR_OFFSET,OFFSET BUFFER ;If yes, move listing and
JMP SHORT TOP_BAR ; bar to top.

END_KEY: CMP AH,4FH ;End?
JNZ ESC
MOV BX,END_OFFSET ;If yes, move listing and
SUB BX,81*21 ; bar to bottom.
CMP BX,OFFSET BUFFER
JBE BOTTOM_BAR
MOV CUR_OFFSET,BX
JMP SHORT BOTTOM_BAR

ESC: CMP AH,1 ;Esc?
JNZ NEXT_KEY
JMP EXIT ;If yes, exit.

NEXT_KEY: JMP GET_KEY

;*************;
; SUBROUTINES ;
;*************;

;-------------------------------------;
; This subroutine scrolls the screen. ;
;-------------------------------------;

SCROLL: MOV SI,CUR_OFFSET ;Get current offset.
ADD SI,BP ;Add requested direction.
JNS CK_LOWER ;If signed and PgUp request
CMP BP,-81*21 ; then below start.
JZ LOWER_LIMIT
CK_LOWER: CMP SI,OFFSET BUFFER ;If above start check upper limit.
JAE UPPER_LIMIT
LOWER_LIMIT: MOV CUR_OFFSET,OFFSET BUFFER ;Else, make it start.
JMP SHORT UPDATE ;And update screen.

UPPER_LIMIT: MOV BX,END_OFFSET ;See if beyond end of
CMP BX,OFFSET BUFFER+21*81 ; directory listing as well.
JA CK_UPPER
MOV CUR_OFFSET,OFFSET BUFFER
JMP SHORT UPDATE

CK_UPPER: SUB BX,21*81
CMP SI,BX
JBE END_SCROLL
MOV SI,BX

END_SCROLL: MOV CUR_OFFSET,SI ;Update current offset.
UPDATE: CALL UPDATE_SCREEN
RET

;--------------------------------------------------;
; This subroutine scrolls the bar if between start ;
; and end of page. Otherwise the page is scrolled. ;
;--------------------------------------------------;

SCROLL_BAR: MOV SI,LINE ;Get current line.
ADD SI,BP ;Add requested line.
MOV BP,-81 ;Assume below beginning.
CMP SI,403 ;Is it?
JB SCROLL_PAGE ;If yes, scroll page instead.
MOV BP,81 ;Do the same for end of page.
CMP SI,PAGE_END
JAE SCROLL_PAGE
ADD CURS_POS,DX ;If in range, update cursor
CALL MOVE_BAR ; and bar position.
RET

SCROLL_PAGE: CALL SCROLL
RET

;----------------------------------------------------;
; This subroutine does the actual moving of the bar. ;
;----------------------------------------------------;

MOVE_BAR: MOV BL,NORMAL ;Remove old bar.
CALL BAR
MOV LINE,SI ;And move bar to new line.
MOV BL,INVERSE
CALL BAR
RET

BAR: MOV DI,LINE ;Retrieve line.
MOV BH,38 ;Bar length 39.
MOV DX,STATUS_REG
NEXT_BAR: MOV CX,1 ;Write one character at a time.
CALL HORZ_RET
DEC BH
JNZ NEXT_BAR
RET

;----------------------------------------------;
; This subroutine stores the ASCII characters. ;
;----------------------------------------------;

STORE_CHAR: PUSH AX ;Save character.
MOV SI,CUR_OFFSET ;Retrieve current starting offset.
MOV AX,CURS_POS ;Retrieve cursor position.
MOV CX,AX ;Save it.
MOV AL,AH
XOR AH,AH ;Isolate row.
DEC AX ;Adjust for offset.
DEC AX
ADD SI,AX ;Add to source.
MOV DL,80 ;Multiply by 80.
MUL DL
ADD SI,AX ;Add to source.
MOV DI,AX ;DI is screen offset.
SHL DI,1 ;Adjust for attribute.
ADD DI,2*160 ;Adjust for starting in row 3.
XOR CH,CH ;Isolate column.
ADD SI,CX ;Add column to offset.
SHL CX,1 ;Double for screen offset.
ADD DI,CX ;Add it.
POP AX ;Retrieve character.
MOV [SI],AL ;Store it.

MOV CX,1
CALL WRITE_SCREEN ;Display by updating screen.
MOV UPDATE_FLAG,1 ;Flag as updated so file will
RET ; be written upon Esc.

;---------------------------------------------------;
; This subroutine writes the listing to the screen. ;
;---------------------------------------------------;

UPDATE_SCREEN: MOV SI,CUR_OFFSET ;Retrieve starting offset.
MOV DI,2*160 ;Point to row three of screen.
MOV BH,21 ;21 lines to write.
NEXT_WRITE: MOV CX,79 ;79 characters per line.
CALL WRITE_SCREEN ;Write them.
ADD SI,2 ;Bump pointer past cr/lf.
ADD DI,2 ;Bump pointer to next line.
DEC BH ;Do all 21 lines.
JNZ NEXT_WRITE
RET

;------------------------------------------------------------;
; This subroutine displays the directory by writing directly ;
; to the screen buffer. To avoid screen noise (snow) on the ;
; color card, the horizontal retrace has to be monitored. ;
;------------------------------------------------------------;

WRITE_SCREEN: MOV DX,STATUS_REG ;Get status register.
NEXT_BYTE: LODSB ;Get a byte.
MOV BL,AL ;Save it in BL.

HORZ_RET: IN AL,DX ;Get status.
TEST AL,1 ;Is it low?
JNZ HORZ_RET ;If not, wait until it
CLI ;No more interrupts.

WAIT: IN AL,DX ;Get status.
TEST AL,1 ;Is it high?
JZ WAIT ;If no, wait until it is.
MOV AL,BL ;Retrieve character; now it's OK
STOSB ; to write to screen buffer.
STI ;Interrupts back on.
INC DI ;Bump pointer past attribute.
LOOP NEXT_BYTE ;Get next byte.
RET ;Return

;------------------------------------;
; This subroutine clears the screen. ;
;------------------------------------;

CLS: MOV BH,NORMAL ;Clear with original attribute.
XOR CX,CX
MOV DX,184FH ;Entire screen.
MOV AX,600H ;Scroll active page.
INT 10H
RET ;Return.

;-----------------------------------------;
; These subroutines display the messages. ;
;-----------------------------------------;

DISPLAY_TEXT: MOV CURS_POS,DX ;Store requested cursor position.
CALL SET_CURSOR ;Move cursor.
GET_TEXT: LODSB
CMP AL,0 ;Zero marks end of string.
JZ END_TEXT
CALL WRITE_TEXT
JMP SHORT GET_TEXT
END_TEXT: RET

WRITE_TEXT: PUSH SI ;BIOS does not save SI.
MOV AH,0EH ;Write teletype
INT 10H
POP SI
RET

;----------------------------------------------------------------------;
; These two subroutines move the cursor and get the current directory. ;
;----------------------------------------------------------------------;

SET_CURSOR: PUSH SI ;Save SI pointer; BIOS doesn't.
MOV DX,CURS_POS ;Get requested cursor position.
XOR BH,BH ;Page zero.
MOV AH,2
INT 10H
POP SI
RET

GET_DIR: MOV BYTE PTR [SI],'\' ;DOS doesn't preface directory
INC SI ; with slash so we must.
XOR DL,DL
MOV AH,47H ;Retrieve default directory.
INT 21H
RET

;--------------------------------------------------;
; This long subroutine stores the filename in DIR ;
; format. That is, filename, bytes, date and time. ;
;--------------------------------------------------;

BUFFER_NAME: MOV SI,158 ;Point to filename.
MOV CX,12 ;Store 12 bytes of filename.
NEXT_STORE: LODSB ;Get a byte.
CMP AL,0 ;End of filename?
JZ END_STORE ;If yes, finish with blanks.
CMP AL,'.' ;Is it the period?
JNZ STORE_BYTE ;If no, store.
SUB CX,3 ;Else store 3 spaces.
MOV AL,32
REP STOSB
ADD CX,3
JMP SHORT NEXT_STORE ;Get next byte.

STORE_BYTE: STOSB ;Store byte.
LOOP NEXT_STORE ;Get next byte.
END_STORE: MOV AL,32 ;Pad balance with spaces.
REP STOSB

FILE_SIZE: PUSH DI ;Save pointer.
ADD DI,8 ;Move to end of bytes field.
MOV DX,DS:[154] ;Retrieve high and low words
MOV AX,DS:[156] ; of bytes.
MOV BX,10 ;Convert to decimal; divide by 10.
STD ;Reverse direction.

NEXT_SIZE: MOV CX,DX ;Low word in CX.
XOR DX,DX ;Zero in high half.
DIV BX ;Convert to decimal.
XCHG AX,CX ;Retrieve low word.
DIV BX
XCHG AX,DX ;Retrieve remainder.
ADD AL,'0' ;Convert to ASCII.
STOSB ;Store it.
MOV AX,CX ;Are we done?
OR CX,DX
JNZ NEXT_SIZE ;If no, divide again.

CLD ;Back to forward direction.
POP DI ;Retrieve pointer.
ADD DI,11 ;Move to date field.
DATE: MOV DX,DS:[152] ;Retrieve date.
MOV AX,DX
MOV CL,5 ;Shift to lowest bits.
ROR AX,CL
AND AX,0FH ;Mask off all but month.
MOV CL,0FFH ;Flag as no leading zeros.
MOV CH,'-' ;Delimiting character.
CALL STORE_WORD ;Store it.

MOV AX,DX ;Retrieve date.
AND AX,1FH ;Mask off all but day.
MOV CL,0 ;Flag include leading zeros.
MOV CH,'-'
CALL STORE_WORD ;Store it.

MOV AX,DX ;Retrieve date for last time.
MOV CL,9
ROR AX,CL
AND AX,7FH ;Mask off all but year.
ADD AX,80 ;Adjust to ASCII.
CMP AX,100 ;Past year 2000?
JB DISPLAY_DATE ;If no, display. Else, adjust for
SUB AX,100 ; next century. (Planning ahead!)
DISPLAY_DATE: MOV CL,0 ;Display leading zeros.
MOV CH,32
CALL STORE_WORD ;Store it.

TIME: INC DI ;Move to time field.
MOV DX,DS:[150] ;Retrieve time.
MOV AX,DX
MOV CL,11 ;Shift to hours bits.
ROR AX,CL
AND AX,1FH ;Mask off all but hours.
PUSH AX
CMP AX,12 ;Past noon?
JBE MERIDIAN
SUB AX,12 ;If yes, adjust.
MERIDIAN: CMP AX,0 ;Midnight?
JNZ NOT_MIDNIGHT
MOV AX,12 ;If yes, adjust.
NOT_MIDNIGHT: MOV CL,0FFH ;Suppress leading zeros.
MOV CH,':'
CALL STORE_WORD ;Store it.

MOV AX,DX ;Retrieve time.
MOV CL,5 ;Shift to minutes bits.
ROR AX,CL
AND AX,3FH ;Mask off all but minutes.
MOV CL,0
POP DX ;Retrieve hours.
MOV CH,'p' ;Assume PM.
CMP DX,12 ;Is it PM?
JAE PM
MOV CH,'a' ;If no, AM.

PM: CALL STORE_WORD ;Store it.
MOV BYTE PTR [DI],'U' ;Assume for now updated.
MOV BYTE PTR [DI+40],13 ;Tack on carriage return linefeed.
MOV BYTE PTR [DI+41],10
ADD DI,42 ;Move pointer past note field
RET ; to start of next record.

STORE_WORD: DIV BL ;Divide by ten.
ADD AX,'00' ;Convert to ASCII.
CMP CL,0 ;Are we to display leading zero?
JZ STORE_IT ;If yes, store as is.
CMP AL,'0' ;Is it a leading zero?
JNZ STORE_IT ;If no, store it.
MOV AL,32 ;Else, store a space.
STORE_IT: STOSW
MOV AL,CH ;Store delimiter character also.
STOSB
RET

;-----------------------------------------------------------------;
; This is the exit routines. Check if notes have been updated. ;
; If yes, write the file. Return to original drive and directory. ;
;-----------------------------------------------------------------;

ERROR_EXIT: MOV AH,9 ;Display error message.
INT 21H
CALL RESTORE_PATH ;Restore path.
INT 20H ;Exit.

EXIT: MOV CURS_POS,1700H ;Row 22; column 0.
CALL SET_CURSOR
CMP BYTE PTR UPDATE_FLAG,1 ;Did we update notes?
JNZ NO_WRITE ;If no, skip write
MOV SI,OFFSET SAVING ;Display "Saving DIRN----.DAT.
CALL GET_TEXT
MOV SI,OFFSET DIRNOTES
CALL GET_TEXT
MOV DX,OFFSET DIRNOTES ; else point to DIRNOTES
MOV CX,20H ; create the file.
MOV AH,3CH
INT 21H
MOV BX,AX ;Filehandle.
MOV DX,OFFSET BUFFER ;Point to the buffer
MOV CX,END_OFFSET
SUB CX,DX ;File size.
MOV AH,40H ;Write it.
INT 21H

NO_WRITE: CALL RESTORE_PATH ;Restore default directory.
MOV CURS_POS,0 ;Home the cursor.
CALL SET_CURSOR
CALL CLS ;Clear the screen.
INT 20H ; and exit.

RESTORE_PATH: MOV DL,CURRENT_DISK ;Reset the drive.
MOV AH,0EH
INT 21H
MOV DX,OFFSET CURRENT_DIR ;Reset the directory.
MOV AH,3BH
INT 21H
RET

;-------------------------------------------------;
; Approximate 700 filename buffer at end of code. ;
;-------------------------------------------------;

CURRENT_DIR:
BUFFER EQU CURRENT_DIR+66

CODE ENDS
END START


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