; ; ; ; ;============================================ IF1 .PRINTX! ZSCAN3.MAC, glen ellis ! .printx! read/alter/writeback ! .PRINTX! packed version ! .PRINTX! for Stewart Software ! .PRINTX! Memphis, Tennessee ! .PRINTX! v.0122pm,sun,01.jun.86 ! ELSE .PRINTX! +++ Pass Two +++ ! ENDIF ;---- List Flags .SFCOND ; skip false conditionals .XALL ; not expand unused macro .XLIST ; not list following source text .LIST ; list following source text ;----------------------------------------------- ;;; ORIGIN ASEG ; absolute code address ORG 100H .Z80 ORIGIN: jp scan$init ;----------------------------------------------- ;;; LIBRARY ; ASSEMBLY METHODS. ; Author used MicroSoft A.L.D.S. ; (Assembly Language Development System) ; from Micro-Soft, which is a Macro/Linker system, ; which is similar to D.R.I. MAC.COM. ; This source contains very little code ; which is not compatible with with Public Domain ZASM.COM. ; user may use Word Star to bring in the library. ; cut out un-used portions of library. ; cut out any conditional notation. ; make minor modifications. ; use ZASM.COM. ; Apple CP/M will handle the large source file. INCLUDE B:SCAN.LIB ; Author used drive B: ;******************************************** ;;; INITIAL SCAN$INIT: ld hl,00H ; store sys sp to hl add hl,sp ld (scan$stk),hl ; store sp to mem ld sp,(scan$stk) ; point sp to local-stack ;**************************************** ;;; MAIN MODULE SCAN$MAIN: SIGN$LOOP: ; sign-on message call sign$it ; main menu ; installs scan$mod CHECK$LOOP: ; check if valid file call check$it ; cpm$dma$buff --> fcb MENU$LOOP: call menu$it ; main menu, installs scan$mod INPUT$LOOP: call input$it ; input user characters ; if required READ$LOOP: call read$it ; read a sector ; will exit at eof SCAN$LOOP: call scan$it ; specific function ; executed on sector ; includes echo WRIT$LOOP: call check$key ; allow exit from pgm ; prior to each back/write call back$it ; re-position for write call write$it ; re-write the sector jp read$loop ; loop for scan ;******************************** ;;; SUBROUTINES ;------------------------------- ;;; SIGN-ON MESSAGE SIGN$IT: call l$co$clear call l$co$str$sp .xlist db cr,lf db '********************************************************',cr,lf db '* ____ ____ ____ . . . ___ *',cr,lf db '* / (___ / /_\ |\ | __) *',cr,lf db '* / ____) \____ / \ | \| ___) *',cr,lf db '* /___ .......................................... *',cr,lf db '* *',cr,lf db '* ZSCAN3.COM *',cr,lf db '* v.0100pm,sun,01.jun.86, by Glen Ellis *',cr,lf db '* released as Public Domain *',cr,lf db '* *',cr,lf db '********************************************************',cr,lf db 00 .list ret ;-------------------------------- ;;; MENU MAIN MENU$IT: ld a,00h ; clear controlling registers ld (echo$reg),a ld (scan$mod),a MENU$IT$LP: call l$co$str$sp db '--------------------------------------------------------',cr,lf db '| onvert old -> new cho elp uit |',cr,lf db '| base Alph/Num

ass character |',cr,lf db '| |',cr,lf db '| Logical Hex Conversion: Fh EOR |',cr,lf db '| and or eor ordStar strip |',cr,lf db '--------------------------------------------------------',cr,lf db 00 .list call l$co$str$sp .xlist db ' Enter : ',0 .list call l$ci$chr cp 03h ; CP/M Exit jp z,scan$exit and 5fh ; upper case. ld (scan$mod),a ; save the last command ; on way out of parse ... cp 'Q' ; Quit jp z,scan$exit MENU$IT$04: cp 'E' ; ECHO jp nz,menu$it$06 ; parse for next command push af ld a,(echo$reg) cp 00h jr nz,menu$it$05 ; already contains a char pop af ld (echo$reg),a ; load char call l$co$str$sp .xlist db 'cho is ON',cr,lf,0 .list jp menu$it$lp ; echo switched on ; loop for more ... MENU$IT$05: call l$co$str$sp .xlist db 'cho is OFF',cr,lf,0 .list pop af ld a,00h ld (echo$reg),a ; echo switched off jp menu$it$lp ; loop for more ... MENU$IT$06: cp 'H' ; HELP jp nz,menu$it$08 ; check for next command call l$co$str$sp .xlist db 'elp Coming !',cr,lf,0 .list call l$co$clear call l$co$str$sp .xlist db '+=+=+=++=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=',cr,lf db ' SCAN.COM written by Glen Ellis ',cr,lf db ' Rehab.Engineering, University of Tennessee ',cr,lf db ' 682 Court, Memphis, Tn, 38163 ',cr,lf db '+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+',cr,lf db ' Reads / Alters / Writes ',cr,lf db ' Each File Sector Directly on Disk ! ! ! ',cr,lf db '+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+',cr,lf db ' cho : useful for debugging user mod. ',cr,lf db ' Convert old/New : Alpha or Hex. ',cr,lf db ' for converting specific characters. ',cr,lf db ' WordStar to MacIntosh, for example. ',cr,lf db ' base Alpn/Num clears bad characters ',cr,lf db ' from dBASE command files. Life Saver ! ',cr,lf db ' leaves <0Dh> <0Ah> as required. ',cr,lf db ' ',cr,lf db ' ordStar 7Fh AND to clear hi bit ascii. ',cr,lf db ' leaves hi/lo bit form as is. ',cr,lf db '...............................................',cr,lf db ' for next screen ' db 00 .list call scan$wait ; wait for user response call l$co$clear call l$co$str$sp .xlist db '+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+',cr,lf db ' Reads / Alters / Writes ',cr,lf db ' Each File Sector Directly on Disk ! ! ! ',cr,lf db '+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+',cr,lf db ' ',cr,lf db '

ass character Exclusive OR function: ',cr,lf db ' ',cr,lf db ' Prompts for ascii/hex characer to be used ',cr,lf db ' in the user selected logical function. ',cr,lf db ' ',cr,lf db ' Logical Mask Functions : ',cr,lf db ' Prompts for HEX byte to become logical mask. ',cr,lf db ' ',cr,lf db ' 7F will make Word Star ',cr,lf db ' into a hard , locking ^reform. ',cr,lf db ' ',cr,lf db ' Fh EOR simple scramble. ',cr,lf db '...............................................',cr,lf db ' to menu, previous entries are 00H ' db 00 .list call scan$wait ; wait for user response call l$co$clear jp menu$it$lp ; loop for more ... MENU$IT$08: ; check for next command MENU$IT$EX: call l$co$crlf ; exit parse ............ ; check user entry during "INPUT" RET ;-------------------------------- ;;; CHECK FILENAME CHECK$IT: call l$sp$msg .xlist db '+++ Checking Filename.Typ +++',00 .list M$CPM l$openf,l$fcb ; open the file inc a ;OK? 00H+1=01H=OK jp z,check$it$err ; no, exit call l$sp$msg .xlist db ' +++ File Found +++',cr,lf,00 .list ret CHECK$IT$ERR: call l$sp$msg .xlist db ' +++ No Such File +++',cr,lf,00 .list jp scan$exit ;------------------------------- ;;; INPUT USER CHAR .comment! db '| onvert old -> new cho elp uit |',cr,lf db '| base Alph/Num

ass char |',cr,lf db '| HEX logical functions: Fh EOR |',cr,lf db '| and or eor ordStar 7F AND |',cr,lf requires user input character C P A O X blind run D F W .comment! INPUT$IT: ; parse scan$mod ld a,(scan$mod) cp 'C' call z,input$conv cp 'P' call z,input$pas cp 'A' call z,input$log cp 'O' call z,input$log cp 'X' call z,input$log jp input$it$ex ; other choices ; print user selection and allow check/exit call l$co$clear call l$co$str$sp .xlist db '-------------------------------------------',cr,lf,00 .list call l$co$str$sp .xlist db ' User Entry was : ',0 .list ld a,(scan$mod) call l$co$chr call l$co$crlf call scan$wait ; allow exit INPUT$IT$EX: ret ; back to caller. ;------------------------------------ ;;; INPUT CONVERT CHAR INPUT$CONV: call l$co$clear call l$sp$msg db cr,lf db '-------------------------------------------',cr,lf db 'Mode of Conversion: ',cr,lf db 'ex / scii / (^C) exit :',0 call l$ci$chr and 5Fh ; to upper cp 03h jp z,scan$exit ; allow exit from pgm cp 'H' jp z,input$hex cp 'A' jp z,input$asc jp input$conv ; loop for valid INPUT$ASC: call l$sp$msg .xlist db cr,lf db '--------------------------------------',cr,lf db 'Ascii OLD Character to be converted : ',0 .list call l$ci$chr ld (conv$old),a call l$sp$msg .xlist db ' = ',0 .list ld a,(conv$old) call l$co$chr$bit call l$sp$msg .xlist db cr,lf db 'Ascii NEW Character to be installed : ',0 .list call l$ci$chr ld (conv$new),a call l$sp$msg .xlist db ' = ',0 .list ld a,(conv$new) call l$co$chr$bit jp input$conv$ex INPUT$HEX: call l$sp$msg .xlist db cr,lf db '---------------------------------------',cr,lf db 'Hex OLD Character to be converted : ',0 .list call l$ci$chr call l$ahexbin4 ; res in l$ahb4$res (hi/lo) call l$ci$chr call l$ahexbin4 ; res in l$ahb4$res (hi/lo) ld a,(l$ahb4$res) ld (conv$old),a call l$sp$msg .xlist db ' = ',0 .list ld a,(conv$old) call echo ; display only ascii call l$sp$msg .xlist db ' = ',0 .list ld a,(conv$old) call l$co$chr$bit ; display bit pattern call l$co$2crlf call l$sp$msg .xlist db cr,lf,'Hex NEW Character to be installed : ',0 .list call l$ci$chr call l$ahexbin4 ; res in l$ahb4$res (hi/lo) call l$ci$chr call l$ahexbin4 ; res in l$ahb4$res (hi/lo) ld a,(l$ahb4$res) ld (conv$new),a call l$sp$msg .xlist db ' = ',0 .list ld a,(conv$new) call echo ; display only ascii call l$sp$msg .xlist db ' = ',0 .list ld a,(conv$new) call l$co$chr$bit ; display bit pattern call l$co$2crlf INPUT$CONV$EX: call scan$wait ; allow exit ret ;----------------------------------- ;;; INPUT LOGIC CHAR INPUT$LOG: call l$sp$msg .xlist db cr,lf db '--------------------------------------',cr,lf db 'Logical Operation on Each Byte. ',cr,lf db 'HEX Character for AND/OR/XOR mask : ',0 .list call l$ci$chr call l$ahexbin4 ; res in l$ahb4$res (hi/lo) call l$ci$chr call l$ahexbin4 ; res in l$ahb4$res (hi/lo) ld a,(l$ahb4$res) ld (conv$mask),a call l$sp$msg .xlist db ' = ',0 .list ld a,(conv$mask) call l$co$chr$bit ; display bit pattern call scan$wait ; allow exit RET ;----------------------------------- ;;; INPUT PASS CHAR INPUT$PAS: call l$co$clear call l$sp$msg .xlist db '-----------------------------------------',cr,lf db 'Pass Character Exclusive OR : ',cr,lf db '( = FFH), ( = exit) ',cr,lf db 'Enter Keybboard Pass Character : ',00 .list INPUT$PAS$00: call l$ci$chr ; develop limit to "A"->"Z" push af call l$co$crlf pop af cp 20h ; jp z,input$pas$01 ; default cp 0dh ; jp z,input$pas$07 ; exit jp input$pas$09 ; good char INPUT$PAS$01: call l$sp$msg .xlist db cr,lf db 'default is XOR FFh',cr,lf,00 .list ld a,0ffh ; substitute default character jp input$pas$09 ; return INPUT$PAS$07: call l$sp$msg .xlist db cr,lf,'+++ No Function Selected +++',cr,lf,00 .list jp scan$exit INPUT$PAS$09: ld (conv$pass),a INPUT$PAS$EX: call scan$wait ; allow exit RET ;--------------------------------------- ;;; READ SECTOR from DISK READ$IT: ld a,(echo$reg) ; link runmsg + echo or a jr z,read$it$02 ; else contains 'E'cho call l$sp$msg db cr,lf,lf,lf db '--------------------------------',cr,lf db '--- Reading Sector',00 READ$IT$02: ; READ FILE MACRO M$CPM l$readsf,l$fcb ; read file ; (A) = code push af ; save for exit ld a,(echo$reg) ; link runmsg + echo or a jr z,read$it$04 call l$co$str$sp db ' --- rcd/ext ',00 ld a,(l$fcbcr) call l$co$chr$bit ld a,(l$fcbex) call l$co$chr$bit call l$co$str$sp db ' --- code ',00 pop af ; borrow it only push af call l$co$chr$BIT call l$co$crlf READ$IT$04: pop af or a ret z ;ALL OK , return to caller READ$ERR: cp 01H ; EOF = 1 scf ; carry shows eof jp z,finish$it call l$sp$msg .xlist db cr,lf,'+++ Read Error +++',cr,lf,00 .list jp scan$exit ;----------------------------------------- ;;; SCAN FUNCTION SCAN$IT: ld a,(echo$reg) ; link runmsg + echo or a jr z,scan$it$02 ; else contains 'E'cho call l$sp$msg .xlist db cr,lf,'------- Scanning Sector ------ ',cr,lf,lf,00 .list SCAN$IT$02: ;--------------------------------- ;;; SCAN INIT FUNCTIONS SCAN$SET: ld hl,80H ; point to sector data in buffer ; start SCAN$PNT: ; top of loop ld a,(hl) ; get character from disk buffer ld (scan$savhl),hl ; save character pointer ld (scan$reg),a ; save char from disk buffer ; A = char from disk buffer ;------------------------------- ;;; SCAN MODE PARSE SCAN$MOD$PARSE: ld a,(scan$mod) cp 'C' ; convert old to new jp z,CF$CV$00 cp 'D' ; DBASE Alph/Num conversion jp z,CF$AN$00 cp 'P' ; pass char exclusive OR jp z,CF$PAS$00 cp 'A' ; Logical AND jp z,CF$LOG$A cp 'O' ; Logical OR jp z,CF$LOG$O cp 'X' ; logical XOR jp z,CF$LOG$X cp 'F' ; FFh XOR jp z,CF$FF$00 cp 'W' ; WordStar 7f AND jp z,CF$7f$00 ret ;---------------------------------------- ;;; CONVERT OLD into NEW CF$CV$00: ld a,(echo$reg) or a jr z,cf$cv$02 ; else contains 'E'cho ld a,(scan$reg) call echo ; echo BEFORE CF$CV$02: ld a,(scan$reg) ld hl,conv$old cp (hl) jr nz,cf$cv$ex ld a,(conv$new) CF$CV$EX: ld (scan$reg),a jp scan$sav ;------------------------------------------ ;;; DBASE ALPHA / NUMERIC CONVERSION CF$AN$00: ld a,(echo$reg) or a jr z,cf$an$02 ld a,(scan$reg) call echo ; echo BEFORE CF$AN$02: ld a,(scan$reg) ; converts control 'Z' <1Ah> to space ' ' <20h>. ; EOF will occur at physical end of record. ; allows on and for normal text operations. cp 0Dh ; allow jr z,cf$an$ex cp 0Ah ; allow jr z,cf$an$ex CF$AN$03: cp ' ' ; ' ' is lower limit of printables. jr c,cf$an$sp ; if < space, then substitute. CF$AN$05: cp 'z'+1 ; 'z' is upper limit of printables. jr nc,cf$an$sp ; if > "z" , then substitute. jr cf$an$ex ; ok character ---> exit CF$AN$SP: ; substitute blank character. ld a,' ' CF$AN$EX: ; exit with (a) containing printables, only ! ; control char and hi-ascii ; have been substituted with " ". ld (scan$reg),a jp scan$sav ;----------------------- ;;; Word Star 7F AND CF$7F$00: ld a,(echo$reg) or a jr z,cf$7f$02 ld a,(scan$reg) call echo ; echo BEFORE CF$7F$02: ld a,(scan$reg) cp 8dh jr z,cf$7f$03 ; Leave as is. ; WS uses 0D as hard return ; 8D as soft return and 7fh ; clear hi bit ascii ld (scan$reg),a ; for WordStar trash. CF$7F$03: jp scan$sav ;------------------------- ;;; FF exclusive OR CF$FF$00: ld a,(echo$reg) or a jr z,cf$ff$02 ld a,(scan$reg) call echo ; echo BEFORE CF$FF$02: ld a,(scan$reg) xor 0ffh ; blunt scramble ld (scan$reg),a jp scan$sav ;---------------------------------------------- ;;; PassWord Character Conversion CF$PAS$00: ld a,(echo$reg) or a jr z,cf$pas$02 ld a,(scan$reg) call echo ; echo BEFORE CF$PAS$02: ld a,(scan$reg) ld hl,conv$pass ; hl <- immediate addres XOR (hl) ; is altered by (hl) ld (scan$reg),a jp scan$sav ;------------------------------------ ;;; Logical AND Conversion CF$LOG$A: ld a,(echo$reg) or a jr z,cf$log$a2 ld a,(scan$reg) call echo ; echo BEFORE CF$LOG$A2: ld a,(scan$reg) ld hl,conv$mask ; hl <- immediate addres AND (hl) ; is altered by (hl) ld (scan$reg),a jp scan$sav ;---------------------------------- ;;; Logical OR Conversion CF$LOG$O: ld a,(echo$reg) or a jr z,cf$log$o2 ld a,(scan$reg) call echo ; echo BEFORE CF$LOG$O2: ld a,(scan$reg) ld hl,conv$mask ; hl <- immediate addres OR (hl) ; is altered by (hl) ld (scan$reg),a jp scan$sav ;------------------------------------- ;;; Logical XOR Conversion CF$LOG$X: ld a,(echo$reg) or a jr z,cf$log$x2 ld a,(scan$reg) call echo ; echo BEFORE CF$LOG$X2: ld a,(scan$reg) ld hl,conv$mask ; hl <- immediate addres xor (hl) ; is altered by (hl) ld (scan$reg),a jp scan$sav ;---------------------------------------- ;;; SCAN SAVE RESULTS SCAN$SAV: ld a,(scan$reg) ld hl,(scan$savhl) ; restore character pointer ld (hl),a ; restore char to disk buffer ld a,(echo$reg) or a jr z,scan$sav$02 ld a,(scan$reg) call echo ; echo AFTER ld a,' ' ; space the echo groups call l$co$chr SCAN$SAV$02: ;------------------------------------ ;;; SCAN BOTTOM OF LOOP inc l ; test/loop for next character jp nz, scan$pnt ; limit is 128 characters ret ; after scanning entire sector. ;------------------------------------- ;;; BACKUP BEFORE RE-WRITE BACK$IT: ld a,(l$fcbcr) ; get sector # dec a ; back down -1 rcd. ld (l$fcbcr),a ret p ; return if ok. ; an underflow indicates that ; we backed down into previous extent. ; will have to re-open previous extent. BACK$IT$1: ld a,(l$fcbex) ; get extent # dec a ; back down -1 ext. ld (l$fcbex),a ; OPEN FILE MACRO M$CPM l$openf,l$fcb ; re-open file inc a jp nz,back$it$2 call l$sp$msg .xlist db cr,lf,'+++ Re-Opening Extent Failed +++',cr,lf .list jp scan$exit BACK$IT$2: ld a,7FH ; get hi sector ld (l$fcbcr),a ret ;--------------------------------------- ;;; WRITE BACK THE SECTOR WRITE$IT: ld a,(echo$reg) or a jr z,write$it$02 call l$sp$msg .xlist db cr,lf,'--- Writing Sector',00 .list WRITE$IT$02: ld a,00h ld (l$fcbs2),a ; reset S-2 byte in FCB ; WRITE FILE MACRO M$CPM l$writsf,l$fcb ; write the file ; (A) = code push af ld a,(echo$reg) or a jr z,write$it$ex call l$co$str$sp .xlist db ' --- rcd/ext ',00 .list ld a,(l$fcbcr) call l$co$chr$bit ld a,(l$fcbex) call l$co$chr$bit call l$co$str$sp .xlist db ' --- code ',00 .list pop af ; borrow it only push af call l$co$chr$BIT call l$co$crlf WRITE$IT$EX: pop af or a ; 00h = OK ret z call l$sp$msg .xlist db cr,lf,'+++ Write Error +++',cr,lf,00 .list jp scan$exit WRITE$IT$NOT: call l$sp$msg .xlist db cr,lf,'+++ Disabled Write +++',cr,lf,0 .list ret ;-------------------------- ;;; FINISH IT FINISH$IT: call l$co$str$sp .xlist db cr,lf,'------- Closing File -------',cr,lf,00 .list ; CLOSE FILE MACRO M$CPM l$closf,l$fcb ; close the file inc a ; fail+1=00 jp z,exit$error ;---------------------- ;;; EXIT SCAN$EXIT: call l$sp$msg .xlist db cr,lf,' +++ DONE +++',cr,lf,00 .list ld hl,(scan$stk) ld sp,hl ret ;TO CCP ;----------------------- ;;; EXIT ERROR EXIT$ERROR: call l$sp$msg .xlist db cr,lf,' +++ Close Error +++',cr,lf,00 .list jp scan$exit ;------------------------------------------- ;;; WAIT PROMPT , before continue WAIT$IT: SCAN$WAIT: call l$co$str$sp .xlist db cr,lf db 'Waiting ! Check Entry OK ??? ',cr,lf db ' to continue , <^C> to exit ',cr,lf db 00 .list call l$ci$chr CP 03H JP Z,SCAN$EXIT call l$co$str$sp .xlist db cr,lf,'----------------------------------------',cr,lf db 00 .list ret ;---------------------------------- ;;; CHECK KEYBOARD ; CHECK$KEY: ; immediate return back here call l$check cp 03h jp z,scan$exit ret ;------------------------------- ;;; ECHO FUNCTION ; corrects char to alpha-only ; sends to screen. ; preserves HL. ECHO: ; stricly printable characters ! ; sent to screen only, and right now ! ld (echo$sav),a ; save REAL character ECHO$01: cp ' ' jr nc,ECHO$03 ; if > space, then OK so far. ECHO$02: ld a,' ' ; install blank character jr ECHO$07 ; exit ECHO$03: cp 'z'+1 jr c,ECHO$07 ; if < 'z' then OK so far. ECHO$05: ld a,' ' ; install blank character jr ECHO$07 ; exit ECHO$07: ; exit with (a) containing legal char, ; control char and hi-ascii ; have been trapped call l$co$chr ; echo converted character ECHO$EX: ld a,(echo$sav) ; restore REAL character ret ; return to caller ; with REAL character ;================================== ;;; SCAN REGISTERS ;================================== CONV$MODE: DS 1 CONV$OLD: conv$old1: ds 1 conv$old2: ds 1 CONV$NEW: conv$new1: ds 1 conv$new2: ds 1 conv$pass: DB 00h conv$mask: DB 00h ;================================= ECHO$SAV: DS 1 ECHO$REG: db 00h SCAN$SAVHL: DS 2 SCAN$REG: DB 00h SCAN$MOD: DB 00h SCAN$STK: DS 2 ;OLD LOCAL STACK DS 40H ;LOCSTK AREA ;--------------------------------- END ORIGIN ;---------------------------------