Preface The Libraries, Version 4, has taken over two years to arrive at this point in release. During that time, we have witnessed changes in the main supplier for Z-Tools from Echelon to Alpha Systems and others, with an added glitch of ownership and justi fication for upgrading the Libraries. Thanks to Joe Wright of Alpha Systems for authorizing this effort, and in allowing the downloading and otherwise free distribution of the REL and HELP files. Source code is available from Alpha Systems, Corp, 711 Chatsworth Place, San Jose, CA 95128. I would like to thank Ken Taschner and Bruce Morgen for instigat ing this effort and for their help during the first year. Spe cial thanks go to Jay Sage for allowing his Z33LIB modules to be integrated into Z3LIB for a complete package, and to Bridger Mitchell for allowing me to use some of his code in DSLIB for DateStamper interfaces. Thanks also to some of the best testers in the business who took the Libraries through their paces and kept me up late at night exterminating the pesky bugs. They are: Cameron Cotrill, Howard Goldstein, Malcom Kemp, Bruce Morgen, and Carson Wilson. If I have forgotten anyone, it was inadvertant, and my thanks as well. In the legal department, many trademarks are referenced in these files. They are: DateStamper, DosDisk, BackGrounder ii, of Plu*Perfect Systems; CP/M, CP/M Plus, of Digital Research; ZAS, ZDH, ZDM, ZRDOS, of Echelon, Inc; Macro-80 Link-80, of MicroSoft; ZSDOS, ZDDOS, of Cameron Cotrill, Harold Bower, Carson Wilson. "The Libraries, Version 4" is Copyright 1989 by Alpha Systems Corporation, subject to the release previously stated for REL and HELP files. 11 Apr 89 Harold F. Bower P.O. Box 313 Ft. Meade, MD 20755 Introduction to the Libraries, Version 4 Version 4 of the Libraries is the culmination of over two years of work. Beginning with the Version 3.6 libraries, each routine was optimized for performance on Z80 compatible microprocessors, and much restructuring was performed to reduce code size and increase functionality for programs using these new routines. Some of the ground rules for this effort were: o Convert source code to Zilog mnemonics and optimize routines for execution on Z80 and HD64180 Processors o Isolate unitialized data into the DSEG where possible to permit ROMming of programs and for future growth to the Z280 processor o Extract common code in routines to reduce redundancy o Add routines and a new library to take advantage of develop ments in command processors and operating systems for CP/M- compatible computers The newer family of 8-bit processors, such as the Z80, NSC-800, 64180, and Z180 are capable of much more than the older 8080 and 8085 chips. Until now, they have been saddled with the ineffi cient routines in the older Version 3.6 libraries. Since the majority of systems have migrated to the ZCPR3 command processor replacement which cannot operate on the older processors, sacri ficing backward compatibility with the 8080 was not considered a significant shortcoming. In a like vein, CP/M 1.4 remnants have been deleted, requiring CP/M 2.2 or later "type" systems to oper ate correctly. The original routines placed data as well as executable code in the code segment, or CSEG. In some routines, several hundred bytes of uninitialized data was included in program code which served only to increase the size of the program image. Another undesireable feature of this approach is that this practice will not be permitted in newer processors using the so-called protect ed mode of execution. Moving data storage to a separate segment with the DSEG assembler directive will make programs portable to these newer systems, and allow them to be placed in read only memory (ROM). Because of initialization requirements in some modules, this goal could not be totally achieved. Many cases of duplicate code were identified within library rou tines. Such cases were simplified by extracting the common frag ments, and linking them only once. This feature is transparent and handled automatically by your linker. Only one precaution is necessary with this scheme. These extracted routine names gener ally begin with an "at" sign (@), and, with a few exceptions, are undocumented. If you link your own library routines with the Version 4 Libraries, insure that no duplication of names occurs or strange things will happen. Correction of deficiencies and differences between library rou tines and the documentation was also a high priority during this effort. These help files should exactly reflect routine parame ters and functioning. Where differences exist between the print ed manual and these help files, the help files should be consid ered the more accurate. The only deviation from the documentation is in routines where the A register returns a value of 0 with the zero flag set (Z) on one condition, and the zero flag reset (NZ) on the other condi tion. For most routines, the non-zero value is derived from a 0FFh value in the A register as specified in the printed documen tation. This should not be considered as an absolute, however, and in new development, you should consider any non-zero value as valid, not just 0FFh. This change is reflected in these help files. The area of robustness was also tackled, primarily for VLIB and Z3LIB, in an effort to minimize the adverse effects of running programs using those routines on systems not equipped with ZCPR3. While not all areas could be made "bulletproof", they are consid erably more tolerant than previous libraries. Jay Sage, author of ZCPR 3.3 and 3.4, has contributed many rou tines to Z3LIB to use the additional features of the latest com mand processor replacements. His contributions also correct deficiencies in existing modules. The new Z3LIB has also been updated to use the extended environment description needed with NZCOM and ZCPR 3.4. As such, some of the definitions and parame ters have changed. See specific Z3LIB Help for more details. VLIB has been significantly modified with additional features and much faster operation. Business graphics and pull-down menus are among the added capabilities. Details on the new Z3TCAP needed to take advantage of these routines are in the VLIB help section. Several enhancements have been made to SYSLIB routines. Among the more significant are: - DFREE now additionally returns CP/M Plus free space. - xFN1 filename print routines mask most significant bits. - DIRQ/DIRQS routines call DBUFFER to reduce programming re quirements for additional support functions - DIRF/DIRQ/DIRQS routines now ignore CP/M Plus date stamps. - New routines have been added for filename comparisons, hex conversions, and console output masking the MSB. These are documented in the SYSLIB help file. A new library, DSLIB, has been created to provide tools for work ing with clocks and file time and date stamping features provided by ZSDOS/ZDDOS, DateStamper, and Digital Research's CP/M Plus (also known as CP/M 3.x). Utility routines are also featured for conversions between a variety of different date and time formats. For user programs, however, a standardized format patterned after Plu*Perfect Systems' DateStamper is used. Directory routines patterned after those in SYSLIB will return file date stamps along with basic file information. .he ZCPR3: THE LIBRARIES 4.2 -- SYSLIB I. SYSLIB -- General Routines Introduction . . . . . . . . . . . . . . . . . . . . . . 10 Comments on Software Engineering . . . . . . . . . 10 Definitions and Terms . . . . . . . . . . . . . . . 11 Parameter-Passing Conventions . . . . . . . . . . . 12 Overview of Routines . . . . . . . . . . . . . . . 13 Directory Manipulation . . . . . . . . . . . . . . . . . 15 Directory Buffer Structure . . . . . . . . . . . . 16 How To Use These Routines . . . . . . . . . . . . . 16 Buffer Allocation . . . . . . . . . . . . . . . . . 18 DBUFFER Disk Free Space . . . . . . . . . . . . . . . . . . 18 DFREE Directory Alphabetization . . . . . . . . . . . . . 18 DIRALPHA Generalized Directory Routines . . . . . . . . . . 19 DIRF, DIRFS Directory Load Routines . . . . . . . . . . . . . . 20 DIRLOAD, DIRSLOAD Directory Pack Routines . . . . . . . . . . . . . . 21 DIRPACK, DIRNPACK Optimal Directory Routines . . . . . . . . . . . . 21 DIRQ, DIRQS Directory Entry Selection Routine . . . . . . . . . 22 DIRSEL Disk Parameter Information . . . . . . . . . . . . 23 DPARAMS, BLKSHF (global), BLKMSK (global), EXTENT (global), BLKMAX (global), DIRMAX (global) File Size Computation . . . . . . . . . . . . . . . 23 FSIZE Byte-Oriented File Input/Output Routines . . . . . . . . 24 Byte-Oriented I/O File Open . . . . . . . . . . . . 25 FI0$OPEN, FI1$OPEN, FI2$OPEN, FI3$OPEN, FO0$OPEN, FO1$OPEN, FO2$OPEN, FO3$OPEN Byte-Oriented I/O File Close . . . . . . . . . . . 25 FI0$CLOSE, FI1$CLOSE, FI2$CLOSE, FI3$CLOSE, FO0$CLOSE, FO1$CLOSE, FO2$CLOSE, FO3$CLOSE Byte-Oriented Input/Output . . . . . . . . . . . . 26 F0$GET, F1$GET, F2$GET, F3$GET, F0$PUT, F1$PUT, F2$PUT, F3$PUT Error Return Codes . . . . . . . . . . . . . . . . 27 Byte-Oriented File I/O with Variable Buffers . . . . . . 28 Input and Output File Open . . . . . . . . . . . . 30 FXI$OPEN, FXO$OPEN Input and Output File Close . . . . . . . . . . . . 30 FXI$CLOSE, FXO$CLOSE Input and Output . . . . . . . . . . . . . . . . . 30 FX$GET, FX$PUT Byte-Oriented File I/O with Variable Buffers and UNGET . 31 Input and Output File Open . . . . . . . . . . . . 33 FYI$OPEN, FYO$OPEN Input and Output File Close . . . . . . . . . . . . 33 FYI$CLOSE, FYO$CLOSE Input, Unget, and Output . . . . . . . . . . . . . 33 FY$GET, FY$UNGET, FY$PUT General-Purpose CP/M File Manipulation Routines . . . . 34 Close a File . . . . . . . . . . . . . . . . . . . 34 F$CLOSE Delete a File . . . . . . . . . . . . . . . . . . . 34 F$DELETE Test File Existence . . . . . . . . . . . . . . . . 35 F$EXIST Create a File . . . . . . . . . . . . . . . . . . . 35 F$MAKE Open a File . . . . . . . . . . . . . . . . . . . . 35 F$OPEN, F$MOPEN Append to a File . . . . . . . . . . . . . . . . . 35 F$APPEND, F$APPL Read Block from File . . . . . . . . . . . . . . . 36 F$READ Rename a File . . . . . . . . . . . . . . . . . . . 37 F$RENAME Compute File Size . . . . . . . . . . . . . . . . . 37 F$SIZE Write a Block to a File . . . . . . . . . . . . . . 37 F$WRITE Return Random Record Number . . . . . . . . . . . . 37 GETRR, GETRR1 Return File Size . . . . . . . . . . . . . . . . . 38 GETFS, GETFS1 Get File Attributes . . . . . . . . . . . . . . . . 38 GFA Read File Block Random . . . . . . . . . . . . . . 38 R$READ Write File Block Random . . . . . . . . . . . . . . 39 R$WRITE Set or Clear File Attributes . . . . . . . . . . . 39 SCFA, SFA Library File Manipulation . . . . . . . . . . . . . . . 40 Initialize Library . . . . . . . . . . . . . . . . 40 LUINIT Return Library Directory . . . . . . . . . . . . . 40 LUDIR Open a Library File . . . . . . . . . . . . . . . . 41 LUOPEN Close a Library File . . . . . . . . . . . . . . . 41 LUCLOSE Read a Library File . . . . . . . . . . . . . . . . 41 LUREAD Filename String Parser . . . . . . . . . . . . . . . . . 41 FNAME File Control Block Initialization . . . . . . . . . . . 42 INITFCB Disk/User Manipulation . . . . . . . . . . . . . . . . . 42 Get and Set Current User Area . . . . . . . . . . . 43 GUA, SUA Return the Current Disk and User . . . . . . . . . 43 RETUD Log into a Specified Disk and User . . . . . . . . 43 LOGUD Save and Restore Current Disk and User . . . . . . 44 PUTUD, GETUD Set DMA Transfer Address . . . . . . . . . . . . . 44 SETDMA Numeric String Evaluation . . . . . . . . . . . . . . . 44 General Purpose Numeric String Evaluation . . . . . 44 EVAL Hexadecimal String Evaluation . . . . . . . . . . . 45 EVAL16 Decimal String Evaluation . . . . . . . . . . . . . 45 EVAL10 Octal String Evaluation . . . . . . . . . . . . . . 45 EVAL8 Binary String Evaluation . . . . . . . . . . . . . 46 EVAL2 The L, M, P, and S Numeric Output Routines . . . . . . . 46 Sample Numeric Outputs . . . . . . . . . . . . . . 47 2 Hexadecimal Characters . . . . . . . . . . . . . 47 LA2HC, PA2HC, SA2HC, MA2HC 3 Decimal Characters . . . . . . . . . . . . . . . 47 LA3DC, PA3DC, SA3DC, MA3DC 1 to 3 Decimal Characters with Leading Spaces . . . 48 LADC, PADC, SADC, MADC 1 to 3 Decimal Characters . . . . . . . . . . . . . 48 LAFDC, PAFDC, SAFDC, MAFDC 4 Hexadecimal Characters . . . . . . . . . . . . . 48 LHL4HC, PHL4HC, SHL4HC, MHL4HC 5 Decimal Characters . . . . . . . . . . . . . . . 49 LHL5DC, PHL5DC, SHL5DC, MHL5DC 1 to 5 Decimal Characters with Leading Spaces . . . 49 LHLDC, PHLDC, SHLDC, MHLDC 1 to 5 Decimal Characters . . . . . . . . . . . . . 49 LHLFDC, PHLFDC, SHLFDC, MHLFDC Input Line Editors . . . . . . . . . . . . . . . . . . . 50 BDOS-Based Input Line Editors . . . . . . . . . . . 50 BBLINE, BLINE Independent Input Line Editor . . . . . . . . . . . 51 INLINE String and Switched Output . . . . . . . . . . . . . . . 52 Print String from Stack . . . . . . . . . . . . . . 53 PRINT, EPRINT, LPRINT, SPRINT Print String from HL . . . . . . . . . . . . . . . 53 PSTR, EPSTR, LPSTR, SPSTR Filename Output . . . . . . . . . . . . . . . . . . . . 53 Print Filename . . . . . . . . . . . . . . . . . . 54 LFNn, PFNn, SFNn Store Filename in Memory . . . . . . . . . . . . . 54 MFNn Character-Oriented Input/Output . . . . . . . . . . . . 55 Character Input Via BDOS . . . . . . . . . . . . . 56 BIN Character Input Status Via BDOS . . . . . . . . . . 56 BIST Character Output Via BDOS . . . . . . . . . . . . . 56 BOUT Character Input and Capitalization with Echo . . . 56 CAPIN, CAPINE Character Input . . . . . . . . . . . . . . . . . . 56 CIN, RIN Character Output . . . . . . . . . . . . . . . . . 57 COUT, COUT7, LOUT, POUT, SOUT Character Output with Control Characters . . . . . 57 CCOUT, CLOUT, CPOUT, CSOUT Conditional Input . . . . . . . . . . . . . . . . . 57 CONDIN New Line Output . . . . . . . . . . . . . . . . . . 58 CRLF, LCRLF, SCRLF Console Status . . . . . . . . . . . . . . . . . . 58 CST Branching . . . . . . . . . . . . . . . . . . . . . . . 58 Case via A Register . . . . . . . . . . . . . . . . 59 ACASE1, ACASE2, ACASE3 Case via HL Register Pair . . . . . . . . . . . . . 61 HCASE1, HCASE2, HCASE3 Computed GOTO via A . . . . . . . . . . . . . . . . 62 AGOTO1, AGOTO2, BGOTO1, BGOTO2 Computed GOTO via HL . . . . . . . . . . . . . . . 63 HGOTO1, HGOTO2, DGOTO1, DGOTO2 Arithmetic IF via A . . . . . . . . . . . . . . . . 65 AIF1, AIF2 Arithmetic IF via HL . . . . . . . . . . . . . . . 66 HIF1, HIF2 Parsing Aids . . . . . . . . . . . . . . . . . . . . . . 67 UNIX-Style ARGC/ARGV String Parsing . . . . . . . . 67 ARGV Capitalization . . . . . . . . . . . . . . . . . . 68 CAPS, CAPSTR Character Test Routines . . . . . . . . . . . . . . 68 ISALNUM, ISALPHA, ISCTRL, ISDIGIT, ISGRAPH, ISPRINT, ISPUN, ISSP Character Skip Routines . . . . . . . . . . . . . . 69 SKNPUN, SKNSP, SKPUN, SKSP General-Purpose Arithmetic . . . . . . . . . . . . . . . 69 Arithmetic -- Add, Subtract, Multiply, Divide . . . 69 ADDHD, SUBHD, MULHD, DIVHD Complement -- Negate (2's) and Complement (1's) . . 70 NEGH, CMPH Logical -- And, Or, Xor . . . . . . . . . . . . . . 71 ANDHD, ORHD, XORHD Rotate and Shift -- Left and Right . . . . . . . . 71 ROTLH, ROTRH, SHFTLH, SHFTRH CRC Calculation . . . . . . . . . . . . . . . . . . . . 72 Initialization . . . . . . . . . . . . . . . . . . 72 CRCCLR, CRC1CLR, CRC2CLR, CRC3CLR, CRC3INIT CRC Updating . . . . . . . . . . . . . . . . . . . 73 CRCUPD, CRC1UPD, CRC2UPD, CRC3UPD CRC Completion . . . . . . . . . . . . . . . . . . 73 CRCDONE, CRC1DONE, CRC2DONE, CRC3DONE Random Number Generation . . . . . . . . . . . . . . . . 73 Initialize Random Number Generator Seed . . . . . . 73 RNDINIT Set Known Seed Value . . . . . . . . . . . . . . . 73 RNDSEED Return 8-bit Pseudo-Random Number . . . . . . . . . 74 RND String and Value Comparison . . . . . . . . . . . . . . 74 Compare Vectors . . . . . . . . . . . . . . . . . . 74 COMPB, COMPBC Compare Filenames . . . . . . . . . . . . . . . . . 74 @FNCMP, @AFNCMP Compare HL to DE . . . . . . . . . . . . . . . . . 75 COMPHD Substring Search . . . . . . . . . . . . . . . . . 75 INSTR Vector Search . . . . . . . . . . . . . . . . . . . 76 SCANNER Memory Allocation . . . . . . . . . . . . . . . . . . . 76 Allocate a Block of Memory . . . . . . . . . . . . 77 ALLOC Initialize Memory Allocation System . . . . . . . . 78 IALLOC Check for Top of Available Memory . . . . . . . . . 78 GMEMTOP Sort Routines . . . . . . . . . . . . . . . . . . . . . 78 Sort Specification Block Initializer . . . . . . . 79 SSBINIT Main Sort Routine . . . . . . . . . . . . . . . . . 80 SORT Miscellaneous Routines . . . . . . . . . . . . . . . . . 80 BDOS and BIOS Routines . . . . . . . . . . . . . . 80 BDOS, BIOS Character and Nybble Conversions . . . . . . . . . 81 CATH, @B2HH, @B2HL Command Line Tail Extraction . . . . . . . . . . . 82 CLINE End of Code . . . . . . . . . . . . . . . . . . . . 82 CODEND, $MEMRY (global) Exchange Nybbles . . . . . . . . . . . . . . . . . 83 EN Memory Fill Routines . . . . . . . . . . . . . . . 83 FILLB, FILLBC, HFILB, HFILBC Memory Move Routines . . . . . . . . . . . . . . . 83 MOVEB, MOVEBC, HMOVB, HMOVBC Delay Routine . . . . . . . . . . . . . . . . . . . 84 PAUSE Version Number of SYSLIB . . . . . . . . . . . . . 84 VERSION SYSLIB -- General Routines INTRODUCTION: SYSLIB 4 is an integrated tool set which is de signed to assist you, the assembly language programmer, in writ ing programs. It is intended to place you at a higher level of abstraction and allow you to concentrate on the problem at hand without having to concern yourself with the low-level implementa tion details of the operating system interface, input/output, text parsing and evaluation, math, and sorting. To illustrate this point, consider an assembly language program which needs to access a disk directory, then display a sorted list of filenames. Without SYSLIB 4 or similar library, you would have to write a relatively sophisticated body to code to access the directory, load it in memory, sort, and display it. SYSLIB 4, however, provides you with a "toolbox" of routines to call on to perform some of the more tedious functions. One of these tools, DIRF, loads the elements of a disk directory which match a file specification into a memory buffer for you. But, more than just providing a set of tools, SYSLIB 4 was de signed with structured programming and software engineering in mind. The basic goal in software design is that the programs meet the stated requirements. In applying software engineering, we want more than just this. Among other things, we want the program to be: o Modifiable o Efficient o Reliable o Understandable SYSLIB 4 offers a significant set of facilities which can help to achieve these goals. COMMENTS ON SOFTWARE ENGINEERING: We are experiencing a software crisis today, the basis of which is simply that it is more diffi cult to build reliable software systems that we think it should be. All too often, the symptoms of the software crisis are seen: o Cost -- unpredictable and judged excessive o Efficiency -- time and space utilitization are not efficient o Modifiability -- software is difficult to change o Reliability -- software often fails o Responsiveness -- user needs are not met o Timeliness -- software is not delivered on time o Transportability -- software used on one system may not be used on another The bottom line in the design of a software system is that the software should meet its stated requirements. To achieve this end, the field of software engineering has arisen. The goals of software engineering are: 1.Modifiability -- Software should be easy to change, and software should be designed with later change in mind. 2.Efficiency -- The software system should use available resources in an optimal manner. 3.Reliability -- The software should perform according to specification and recover safely from failure during use. 4.Understandability -- Software should be easy to read and follow. Understandability is the tool used to pass from a particular problem space to a solution. SYSLIB 4 attempts to help you achieve the goals of software engi neering by applying these principles: 1.Abstraction and Information Hiding -- Unnecessary detail is hidden from you. For example, the DIRF routine loads the contents of a disk directory into a memory buffer. How this load is done is hidden; all you need to know is that the load was done and you have a vector of directory entries. 2.Modularity -- SYSLIB 4 is very modular in design. Each routine in the library performs one and only one function, and the documentation provides complete detail as to what that function is, what its input parameters are, what its output parameters are, what its side effects are, and other data. 3.Localization and Loose Coupling -- SYSLIB 4 modules are loosely coupled; each module may be treated independently of the others. Additionally, the modules are strongly cohe sive; the components of each module are intimately related to each other but not to components of other modules. 4.Uniformity -- The calling conventions between the vari ous SYSLIB 4 modules are consistent with each other, and it is frequently the case that the output parameters from one module may be directly used as input parameters to another. 5.Completeness -- Each module or group of related modules are functionally complete. No additional functions are needed. 6.Confirmability -- A program written using SYSLIB 4 mod ules can be readily decomposed for incremental testing. DEFINITIONS AND TERMS: Some terms are used frequently in the SYSLIB 4 documentation. These terms are defined below. 1.Buffer -- A contiguous vector of bytes in memory. The buffer is known by its starting address and size as: BUFFER: DEFS 40 ; 40-byte buffer 2.Character -- A one-byte (8-bit) value. A value range within the ASCII character set (a 7-bit value) is implied but not required, so a character could have a value of 81h. 3.Directory -- An index to files on a disk. A directory entry contains the name of a file, the user number it re sides in, the file size, and where the file is located on the disk. The information loaded by SYSLIB directory rou tines does not include file location information, but does include everything else. In another sense, the term direc tory is used to refer to a particular disk and user area (such as A4 or B31). 4.FCB (File Control Block) -- A 36-byte buffer satisfying the full definition of a CP/M File Control Block. SYSLIB 4 FCB's are always 36 bytes long. In many cases, when rou tines need a user-supplied FCB, you need only fill in the filename and type fields (bytes 1-11) and need not concern yourself with the rest of the fields. The INITFCB routine stores zero in all bytes except bytes 1-11 of the FCB. 5.File -- Any CP/M file, either text or binary. SYSLIB 4 makes no distinction between these two types of files. 6.String -- Any sequence of ASCII characters terminated by a character, which is a byte of value 0. Examples of strings are: DEFB 'This is a string',0 DEFB 1,2,3,'This is also',0 PARAMETER-PASSING CONVENTIONS: SYSLIB 4 is very consistent in its parameter-passing conventions. In all cases, parameters are passed to and from SYSLIB 4 routines in registers. If more val ues are required than there are available registers, the register values are pointers to specification blocks which contain the desired parameters (see the FXn$xxxxx and the SORT routines). In nearly all cases, the following register usage rules apply: The HL register pair is used: 1.as a buffer pointer; for example, HL contains the ad dress of the buffer used by DIRF 2.as a string pointer; for example, HL points to the first byte of a string for the EVAL routine 3.to hold the first operand for math routines; for exam ple, DIVHD divides HL by DE The DE register pair is used: 1.to point to an FCB; for example, DE contains the address of the FCB used by DIRF 2.to contain the second operand for math routines; for example, SUBHD subtracts DE from HL 3.to point to special blocks (buffers) used by SYSLIB 4 routines; for example, DE points to the sort specification block for the SORT routine The BC register pair is used: 1.to contain a DU form, where B holds a disk number (A=0) and C holds a user number The A register is used: 1.to contain an input flag; for example, A contains the selection flag used by DIRF 2.to contain an error return code; if the value of this code is 0, the zero flag (Z) is also set, and vice-versa; for example, A contains a TPA overflow error flag returned by the DIRF routine 3.to contain a character input or output from a a SYSLIB 4 routine; for example, CIN returns a character in A and COUT outputs a character in A OVERVIEW OF ROUTINES: SYSLIB 4 contains many routines grouped into the following functional areas: 1.Directory Manipulation Routines -- These routines deal with directory access. The entries of a disk directory can be loaded into a memory buffer, selected against an FCB, sorted, and manipulated. 2.Numeric String Evaluation Routines -- These routines convert character strings into 16-bit binary values. Strings like those below are processed: DEFB '123',0 ; value is 123 decimal DEFB '5AH',0 ; value is 5A hexadecimal DEFB '110B',0 ; value is 110 binary DEFB '77Q',0 ; value is 77 octal 3.Byte-Oriented File Input/Output Routines -- These rou tines support input and output to and from files on the basis of a byte at a time. FX$GET, for example, returns the next byte from the current file in A. 4.CP/M File Input/Output Routines -- These routines sup port input and output to and from files on the basis of a 128-byte block at a time. Provisions for deleting files, renaming files, and computing file sizes also exist. 5.User/Disk Manipulation Routines -- These routines allow the program to find out what disk and user area it is in and to move between directories. 6.Filename String Parser -- This routine is used to con vert a filename text string into an acceptable form and place it into an FCB. For example, the following conversion can be done: DEFB 'MYFILE.TXT',0 ; string DEFB 0 ; ..converted to DEFB 'MYFILE ' DEFB 'TXT' DEFS 24 7.Input Line Editors -- These routines accept user input with editing and return a pointer to the first byte of user input in string form (terminated by a binary 0). 8.String Output Routines -- These routines send strings to various devices. Routines are provided to send strings of characters to the console or printer with or without con trol-character processing. 9.Numeric Output Routines -- These routines convert binary values to character sequences and output them to various devices. Output to the console and printer is provided, and the output is either in the form of decimal or hexadecimal numbers. 10.String and Value Comparison Routines -- These routines provide various comparison functions for both strings and numbers. One string may be compared against another string or a substring of another string. Two 16-bit numbers can be compared. 11.Character-Oriented Input/Output Routines -- These rou tines provide input and output services on a character-for- character basis to a variety of devices. Output to the console and the printer is provided. Also, device status, such as console input status, routines are available. 12.Math Routines -- These routines perform mathematical calculations on 16-bit quantities. Add, subtract, multiply, divide, rotate, shift, logical AND, logical OR, and logical XOR are some of the functions provided. 13.CRC Routines -- These routines support computation of Cyclic Redundancy Check values for byte streams. A number of different CRC calculation routines are available for different CRC polynomials. 14.Random Number Generator Routines -- These routines implement a pseudo-random number generator which returns an 8-bit value when called. The seed value for this generator may be fed to it, thereby generating the same sequence for each given seed, or it may be selected randomly. 15.Sort Routines -- These routines provide a fast, gen eral-purpose in-memory sort capability. The sort algorithm is very efficient (a shell sort), and may be performed using element pointers or not using pointers (pointers cost more memory but speed up the sort even further). 16.Capitalization and Character Test/Skip Routines -- These routines are useful for text parsing. A variety of evaluation routines are provided to determine the type of character being dealt with (such as alphabetic, numeric, hexadecimal, space, punctuation, etc.). Both string and individual character capitalization capabilities are also provided. 17.Memory Allocation Routines -- These routines provide a dynamic memory allocation mechanism that constantly checks for TPA overflow. After defining the bounds of a memory buffer, requests for space from this area may be issued on a byte-for-byte basis. DIRECTORY MANIPULATION ROUTINES: This set of SYSLIB routines concerns itself with the loading of and access of a disk directo ry for the general purposes of the user. Included in this set of routines are the functions of: - Pre-allocation of buffer space for the routines - Loading of all undeleted directory entries into a buffer, constantly checking for memory overflow - Determining the amount of free space on the disk - Computing the size of a file in Kilobytes (K) - Sorting a loaded directory by file name and type or by file type and name - Selecting (by marking) a set of directory entries which match a given ambiguous file spec - Packing the loaded directory, leaving in it only those en tries marked by the select routine The majority of these routines is intended to be used to provide a flexible directory access system which can be tailored by the user to his specific needs. For instance, with the DIRLOAD rou tine separated from the rest, several different loads of the directory (from, for instance, different ambiguous file specs) can be performed, and then one selection and one sort on all file specs loaded can be done. The DIRQ/DIRQS pair are intended for those applications which do not need this kind of flexibility. DIRQ (quick) and DIRQS (quick with sizing information) perform a load, select, and sort based on only one file specification. Using DIRQ/DIRQS instead of DIRF/DIRFS results in less code being generated and (generally) faster execution. DIRECTORY BUFFER STRUCTURE: DIRLOAD and DIRSLOAD are used to load a directory from disk into memory. The entries loaded are all non-deleted entries in either a particular user area or all user areas on the disk which is currently logged in. Each file entry is 16 bytes long, structured as: byte 1 1 1 1 1 1 offset 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 00 T E S T C O M 01 00 00 79 | \______________________/\_______/ | | | | user-+ filename type | | | | *extent number--+ S2 DM | record number--+ *extent is the file extent; for DIRLOAD, it is the first extent number of the file; for DIRSLOAD, it is the last extent number of the file HOW TO USE THESE ROUTINES: The DIRF or DIRFS routines will prob ably be used to perform your directory access functions the vast majority of the time. Given a buffer, an ambiguous file spec, and a selection flag, DIRF and DIRFS load the desired files for you and then you can work with the 16-byte file entries from there. A typical calling sequence for DIRF or DIRFS is: CALL CODEND ; point to buffer space LD DE,FCB ; point to FCB of file spec LD A,11000000B ; select all files in user 0 CALL DIRF ; load entries JR Z,TPAOVFL ; ..jump if error ... ; HL pts to 1st entry, ; ..BC=number of files If you wish to deviate from the "normal" use for DIRF and DIRFS, access to the routines used by DIRF and DIRFS is available. A case in which you may want to do this is when you are interested in files which match more than one file spec, such as *.ASM and *.TXT. A typical calling sequence for this type of access is: ; setup CALL CODEND ; point to buffer space CALL DBUFFER ; get internal info and ptrs CALL DIRLOAD ; ..or DIRSLOAD to load names JR Z,TPAOVFL ; jump if error condition ... ; select first set of files LD DE,FCB1 ; pt to first FCB to match LD A,11000000B ; select all files in user 0 CALL DIRSEL ; select entries from buffer ; repeat the following 2 lines as necessary LD DE,FCB2 ; pt to 2nd FCB to match CALL DIRSEL ; select again ; finish up CALL DIRPACK ; pack the file entries, ; ..leaving only the valid ; ..entries in the buffer LD A,0 ; alphabetize CALL DIRALPHA ; done -- HL pts to first file entry, BC=number of entries BUFFER ALLOCATION: Routine: DBUFFER Function: Buffer allocation routine Entry: HL = address of buffer start (usually CODEND to CCP) Exit: HL = points to first byte at which DIR entries loaded A <> 0, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if CCP overwritten Affected: AF, HL Usage: Allocates the buffer space necessary for the set of directory functions in general. In particular, it allocates the necessary space for the alphabet ization function as well as the loaded directory itself. This routine must be used if the DIRALPHA routine is to be later used to sort the directory; this routine allocates all the space necessary by DIRALPHA to sort the routine (pointer space). If this routine is called, it is not necessary to call the DPARAMS routine. DISK FREE SPACE: Routine: DFREE Function: Free space computation routine (CP/M 2.2 and 3) Entry: None DPARAMS (or DBUFFER which calls DPARAMS) must be called before using this routine under CP/M 2.2 compatible systems. Exit: DE = free disk space in kilobytes on current disk Affected: DE Usage: Commonly used in directory listing routines to obtain the amount of free space on the logged disk. It may also be used before a file copy to insure that adequate space exists on the destina tion drive. Under CP/M Plus (CP/M 3), BDOS func tion 46 is automatically used to properly return file size in a banked system. DIRECTORY ALPHABETIZATION: Routine: DIRALPHA Function: Directory alphabetization routine Entry: HL = pointer to first directory entry (usually set by DBUFFER) BC = number of files to sort (usually set by DIRLOAD or DIRSLOAD) A = sort flag; 0 = sort by filename then type, non-0 = sort by filetype then name Exit: None (directory list is sorted) Affected: AF Usage: To alphabetize the files in the directory pointed to by HL by either filename and type (STEST.ASM goes before TEST.AAA) or by filetype and name (TEST.AAA goes before STEST.ASM). In the unlikely event that an internal error is detected in the internal sort routine, DIRALPHA will send a BEL character to the console and abort to the operat ing system via the BDOS warm boot vector. GENERALIZED DIRECTORY ROUTINES: Routine: DIRF Function: Generalized directory routine without sizing Entry: HL = pointer to buffer area after user code DE = pointer selection FCB (first 12 bytes used) A = selection flag structured as: b7 -- set to select non-system files b6 -- set to select system files b5 -- set to select all user areas b4-b0 -- if bit 5 reset (0), contains number of user area to select Exit: HL = pointer to first 16-byte file entry in buffer BC = number of files selected A <> 0, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if TPA overflow Affected: AF, BC, HL Usage: The most flexible, though slowest, of the directo ry routines in SYSLIB. It initializes the buffer area, loads a disk directory, selects a specified set of files, packs and sorts the list of files. DIRF executes slightly faster since it does not obtain sizing information, while DIRFS obtains all information which may be passed to the FSIZE rou tine to determine the size of each entry in the directory. For entry parameters, the address for the buffer is usually obtained from a call to CODEND which returns the address of free memory above your program. The FCB used for selection need not be a complete FCB since only the charac ters in the filename and type fields are used. It may therefore be as short as 12 bytes (drive byte, filename and type). Routine: DIRFS Function: Generalized directory routine with sizing data Entry: HL = pointer to buffer area after user code DE = pointer selection FCB (first 12 bytes used) A = selection flag structured as: b7 -- set to select non-system files b6 -- set to select system files b5 -- set to select all user areas b4-b0 -- if bit 5 reset (0), contains number of user area to select Exit: HL = pointer to first 16-byte file entry in buffer BC = number of files selected A <> 0, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if TPA overflow Affected: AF, BC, HL Usage: The most flexible, though slowest, of the directo ry routines in SYSLIB. It initializes the buffer area, loads a disk directory, selects a specified set of files, packs and sorts the list of files. DIRF executes slightly faster since it does not obtain sizing information, while DIRFS obtains all information which may be passed to the FSIZE rou tine to determine the size of each entry in the directory. For entry parameters, the address for the buffer is usually obtained from a call to CODEND which returns the address of free memory above your program. The FCB used for selection need not be a complete FCB since only the charac ters in the filename and type fields are used. It may therefore be as short as 12 bytes (drive byte, filename and type). DIRECTORY LOAD ROUTINES: Routine: DIRLOAD Function: Directory load routine without sizing Entry: HL = pointer to buffer area after user code Exit: BC = number of 16-byte file entries loaded in buffer A <> 0, zero flag clear (NZ) if load OK A = 0, zero flag set (Z) if TPA overflow error Affected: AF, BC Usage: Loads entries for all undeleted files on the cur rently logged drive for later selection, sorting or other actions. DIRLOAD is faster than DIRSLOAD since it does not have to load sizing information, while the latter returns information which will allow FSIZE to return the file size. If sorting is to be done, the value returned in HL from the DBUFFER routine is a correct input for these rou tines. Routine: DIRSLOAD Function: Directory load routine with sizing data Entry: HL = pointer to buffer area after user code Exit: BC = number of 16-byte file entries loaded in buffer A <> 0, zero flag clear (NZ) if load OK A = 0, zero flag set (Z) if TPA overflow error Affected: AF, BC Usage: Loads entries for all undeleted files on the cur rently logged drive for later selection, sorting or other actions. DIRLOAD is faster than DIRSLOAD since it does not have to load sizing information, while the latter returns information which will allow FSIZE to return the file size. If sorting is to be done, the value returned in HL from the DBUFFER routine is a correct input for these rou tines. DIRECTORY PACK ROUTINES: Routine: DIRPACK Function: Pack directory buffer retaining selected entries Entry: HL = pointer to directory buffer (from DBUFFER) BC = number of files in buffer (from DIRLOAD) Exit: BC = number of files remaining in buffer Affected: BC Usage: Used after selection of directory routines with DIRSEL or equivalent to delete all files which have not been selected by setting the most signi ficant bit of the first byte in each entry. DIRPACK removes references to those files not marked. DIRNPACK removes those entries which are marked, keeping those which are not marked (nega tive pack). DIRSEL MUST be called before DIRNPACK is used since DIRNPACK uses an internal flag set by DIRSEL (for SYSTEM and R/O information). Routine: DIRNPACK Function: Pack directory buffer retaining non-selected entries Entry: HL = pointer to directory buffer (from DBUFFER) BC = number of files in buffer (from DIRLOAD) Exit: BC = number of files remaining in buffer Affected: BC Usage: Used after selection of directory routines with DIRSEL or equivalent to delete all files which have not been selected by setting the most signi ficant bit of the first byte in each entry. DIRPACK removes references to those files not marked. DIRNPACK removes those entries which are marked, keeping those which are not marked (nega tive pack). DIRSEL MUST be called before DIRNPACK is used since DIRNPACK uses an internal flag set by DIRSEL (for SYSTEM and R/O information). OPTIMAL DIRECTORY ROUTINES: Routine: DIRQ Function: Quick access directory routine without sizing Entry: HL = pointer to buffer area (from CODEND) DE = pointer to 12-byte select FCB A = mode selection flag b7 -- if set, select non-system files b6 -- if set, select system files b5 -- if set (1), sort by filetype and name; if reset (0), sort by filename and type b4-b0 -- unused Exit: HL = points to first 16-byte buffer entry BC = number of files selected A <> 0, zero flag clear (NZ) if load OK A = 0, zero flag set (Z) if TPA overflow Affected: AF, BC, HL Usage: Commonly used where a simple sorted directory list is needed with minimum time and code overhead. Information is gathered by DIRQS which will allow FSIZE to calculate file sizes, while DIRQ does not. Since DIRQS obtains sizing information as it loads the directory information, it runs slightly slower. In the unlikely event of an internal pointer sort error, a BEL character will be sent to the console and the program will be aborted with a warm boot. Routine: DIRQS Function: Quich access directory routine With sizing data Entry: HL = pointer to buffer area (from CODEND) DE = pointer to 12-byte select FCB A = mode selection flag b7 -- if set, select non-system files b6 -- if set, select system files b5 -- if set (1), sort by filetype and name; if reset (0), sort by filename and type b4-b0 -- unused Exit: HL = points to first 16-byte buffer entry BC = number of files selected A <> 0, zero flag clear (NZ) if load OK A = 0, zero flag set (Z) if TPA overflow Affected: AF, BC, HL Usage: Commonly used where a simple sorted directory list is needed with minimum time and code overhead. Information is gathered by DIRQS which will allow FSIZE to calculate file sizes, while DIRQ does not. Since DIRQS obtains sizing information as it loads the directory information, it runs slightly slower. In the unlikely event of an internal pointer sort error, a BEL character will be sent to the console and the program will be aborted with a warm boot. DIRECTORY ENTRY SELECTION: Routine: DIRSEL Function: Directory entry selection routine Entry: HL = pointer to directory buffer (set by DBUFFER) DE = pointer to 12-byte selection FCB BC = number of files in directory (from DIRLOAD or DIRSLOAD) A = mode selection flag: b7 -- set to select non-system files b6 -- set to select system files b5 -- set to select all user areas b4-b0 -- if bit 5 reset (0), contains number of user area to select Exit: None. MSB set on first byte of selected entries Affected: None Usage: Marks all files in the directory buffer matching the specified criteria by setting the MSB of the first byte. It may be used after any of the SYSLIB directory routines (DIRF, DIRFS, DIRQ, DIRQS) to select a subset of all entries in the directory buffer. DISK PARAMETER INFORMATION: Routine: DPARAMS Function: Disk parameter information extraction routine Entry: None Exit: None (information is placed in local buffers) Affected: None Usage: Extracts necessary information from the disk para meter block (DPB) and stores it away for use by other disk directory routines. If DBUFFER (or any of the SYSLIB directory routines) is called, it is not necessary to call DPARAMS again. The follow ing global variables are set from DPB information: Global: BLKSHF -- Block shift factor (1 byte) Global: BLKMSK -- Block mask (1 byte) Global: EXTENT -- Extent mask (1 byte) Global: BLKMAX -- Maximum number of blocks on disk (2 bytes) Global: DIRMAX -- Maximum number of directory entries (2 bytes) FILE SIZE COMPUTATION: Routine: FSIZE Function: File size computation routine Entry: HL = pointer to first byte of 16-byte file entry DPARAMS (or DBUFFER, DIRFS, DIRQS, DIRSLOAD) must be called before FSIZE so that the correct disk parameter information is established. Exit: DE = file size in kilobytes (K) Affected: DE Usage: Normally used to compute the size of a file con tained in a directory produced by DIRSLOAD or DIRQS. This routine will generally work, but return incorrect results, if the entry was loaded by DIRLOAD or DIRQ which do not return sizing information. BYTE-ORIENTED FILE INPUT/OUTPUT ROUTINES: The following documen tation covers the series of byte-oriented file input/output rou tines in SYSLIB. These routines allow you to sequentially read from (GET) and write to (PUT) a file on a byte-for-byte basis. Hence, these routines provide an exceptionally simple method for handling input from and output to a file. A typical program which employs these routines must open the required files before doing any processing, must then perform the processing on the opened files, and must then close the files when the processing is complete (closing the files is optional for input files and mandatory for output files). SYSLIB provides four sets of routines for byte-oriented file input and output: input open output open GET PUT input close output close FI0$OPEN FO0$OPEN F0$GET F0$PUT FI0$CLOSE FO0$CLOSE FI1$OPEN FO1$OPEN F1$GET F1$PUT FI1$CLOSE FO1$CLOSE FI2$OPEN FO2$OPEN F2$GET F2$PUT FI2$CLOSE FO2$CLOSE FI3$OPEN FO3$OPEN F3$GET F3$PUT FI3$CLOSE FO3$CLOSE This system allows the user to have up to 8 files open simultane ously -- four are open for input using GET and four are open for output using PUT. For example, the following is a sample code section using these routines for two files: EXT FI0$OPEN ; declare library references EXT FO0$OPEN EXT FI0$CLOSE EXT FO0$CLOSE EXT F0$GET EXT F0$PUT ... LD DE,FCBI ; pt to FCB of input file CALL FI0$OPEN LD DE,FCBO ; pt to FCB of output file CALL FO0$OPEN ... [body containing CALL F0$GET and CALL F0$PUT] ... CALL FI0$CLOSE ; close file CALL FO0$CLOSE ... END Note that only the routines to be used are referenced in the EXT statements. If you do not need a particular routine, do not reference it. Not referencing an unneeded routine usually saves the overhead memory space of loading it from the library. Each set of INPUT OPEN, INPUT CLOSE, OUTPUT OPEN, OUTPUT CLOSE, GET, and PUT routines is contained in one library module, so referencing any of these routines causes the entire module to be loaded, and all the routines are accessable to the user (provided they are mentioned in the external definitions) without any addi tional memory overhead. Specifically, FI0$OPEN, FI0$CLOSE, FO0$OPEN, FO0$CLOSE, F0$GET, and F0$PUT are contained in one module, and reference to any of these routines loads the entire module; the same is true for the other sets of routines. The CLOSE routine for output (FOn$CLOSE) is always required; it fills the rest of the current block with ^Z followed by bytes and properly closes file. The CLOSE routine for input (FIn$CLOSE) is required only if you are going to later open ano ther file for input using the corresponding OPEN routine (FIn$OPEN). FIn$CLOSE only serves to reset the OPEN flag (used to GET to ascertain that the file has been properly opened). Routines: FI0$OPEN, FI1$OPEN, FI2$OPEN, FI3$OPEN Function: Open file for byte input Entry: DE = address of FCB of file to open Exit: A = 0, zero flag set (Z) if open successful A = error code, zero flag clear (NZ) if error Affected: AF Usage: Opens the specified file for input (use with F$GET), and output (use with F$PUT). They ini tialize the FCB fields, so further initialization is not necessary. The output open functions also create the indicated file if it does not already exist. Routines: FO0$OPEN, FO1$OPEN, FO2$OPEN, FO3$OPEN Function: Open file for byte output Entry: DE = address of FCB of file to open Exit: A = 0, zero flag set (Z) if open successful A = error code, zero flag clear (NZ) if error Affected: AF Usage: Opens the specified file for input (use with F$GET), and output (use with F$PUT). They ini tialize the FCB fields, so further initialization is not necessary. The output open functions also create the indicated file if it does not already exist. Routines: FI0$CLOSE, FI1$CLOSE, FI2$CLOSE, FI3$CLOSE Function: Close byte input file Entry: None Exit: A = 0, zero flag set (Z) if close successful A = error code, zero flag clear (NZ) if error Affected: AF Usage: Closes files previously opened by the correspond ing FI$OPEN or FO$OPEN routines. While closing an input file is optional if another file will not be opened later by the corresponding FI$OPEN routine, it is poor programming practice which may cause problems in more advanced operating systems. Closing output files is mandatory if you want to retain the file. Routines: FO0$CLOSE, FO1$CLOSE, FO2$CLOSE, FO3$CLOSE Function: Close byte output file Entry: None Exit: A = 0, zero flag set (Z) if close successful A = error code, zero flag clear (NZ) if error Affected: AF Usage: Closes files previously opened by the correspond ing FI$OPEN or FO$OPEN routines. While closing an input file is optional if another file will not be opened later by the corresponding FI$OPEN routine, it is poor programming practice which may cause problems in more advanced operating systems. Closing output files is mandatory if you want to retain the file. Routines: F0$GET, F1$GET, F2$GET, F3$GET Function: Get next byte from input file Entry: None Exit: A = byte from file, zero set (Z) if OK A = error code, zero clear (NZ) if error Affected: AF Usage: Gets a byte from the file specified in the corre sponding Fn$OPEN routine. Routines: F0$PUT, F1$PUT, F2$PUT, F3$PUT Function: Put a byte to output file Entry: A = byte to add to file Exit: A = 0, zero flag set (Z) if OK A = error code, zero clear (NZ) if error Affected: AF Usage: Puts a byte to the file specified in the corre sponding Fn$OPEN routine. ERROR RETURN CODES: For each of the routines in this set of byte-oriented file I/O routines, the zero flag and the A register play a key role in indicating the error conditions of the rou tines. If the zero flag is set (Z) after a routine has been executed, then this indicates that no error has occurred. The A register is either unaffected (in most cases) or contains a returned value (if so indicated, as in Fn$GET routines). If the zero flag is clear (NZ) after a routine has been executed, then this indicates that an error has occurred. The A register now contains the error code. Following is a summary of the error codes. code meaning 1 GET or PUT attempted on an unopened file 2 Disk full (ran out of space) 3 Input file not found 4 Attempt to read past EOF 5 Directory full 6 Error in closing a file 7 Attempt to open a file which is already open BYTE-ORIENTED FILE I/O WITH VARIABLE BUFFERS: In addition to the routines mentioned previously, a set of byte-oriented file I/O routines is available under SYSLIB 4 which permits the user to define the size and location of the buffers to be used. The routines mentioned above all use 128- byte buffers, and, on larg er capacity disk systems (and on any systems in general), it may be more efficient to buffer more than 128 bytes at a time. This will cut down on disk activity and leave more memory-based pro cessing overhead. The routines described in this section are: routine function FXI$OPEN open file for input (similar to FIn$OPEN) FXO$OPEN open file for output (similar to FOn$OPEN) FXI$CLOSE close input file (similar to FIn$CLOSE) FXO$CLOSE close output file (similar to FOn$CLOSE) FX$GET get a byte (similar to Fn$GET) FX$PUT put a byte (similar to Fn$PUT) All of the file extended byte I/O routines (FX means file extend ed) work with an I/O Control Block which is structured as: block length user- offset (bytes) set?* function 0 1 Y Number of 128-byte pages in working buffer 1 1 N End of file flag 2 2 N byte counter 4 2 N Next byte pointer 6 2 Y Address of working buffer 8 36 Y FCB of file (only Fn and Ft fields set by user) *"User-Set" means that you must initialize this value before these routines are called. The following DEFB/DEFS structure can be used in the calling program to implement the I/O Control Block: IOCTL: DEFB 8 ; use 8 128-byte pages (1K) DEFS 1 ; filled in by FXIO DEFS 2 ; filled in by FXIO DEFS 2 ; filled in by FXIO DEFW WORK ; address of working buffer IOCFCB: DEFS 1 ; filled in by FXIO to 0 DEFB 'MYFILE ' ; filename DEFB 'TXT' ; filetype DEFS 24 ; filled in by FXIO WORK: DEFS 128*8 ; working buffer (1K) All of the FXIO routines are consistent in that DE always points to the I/O Control Block (IOCTL above) and A and the PSW are used to pass flags and values. A sample program body which illus trates the calling procedures: ... [Initialize IOCTL1 and IOCTL2, where 1 is input, 2 is output] ... LD DE,IOCTL1 CALL FXI$OPEN ; open 1 for input JR Z,FNF ; file not found error LD DE,IOCTL2 CALL FXO$OPEN ; open 2 for output JR Z,NODIR ; no dir space error ... ... LD DE,IOCTL1 CALL FX$GET ; get next input byte in A JR Z,EOF ; process EOF ... LD DE,IOCTL2 CALL FX$PUT ; put byte in A to output file JR Z,WERR ; process write error ... LD DE,IOCTL1 CALL FXI$CLOSE ; close input file JR Z,FCERR ; file close error LD DE,IOCTL2 CALL FXO$CLOSE ; close output file JR Z,FCERR ... This simple example illustrates the flexibility of the FXIO rou tines. As many files as desired may be open for input or output, each file having its own I/O Control Block and working buffer. The advantages in efficient disk accessing with this set of rou tines over the previous ones are notable. The major disadvantage of using these routines is that the buf fers are larger and the overhead of always ensuring that DE points to the proper I/O Control Block before each routine is called is present. Routines: FXI$OPEN, FXO$OPEN Function: Open file for input or output Entry: DE = address of I/O Control Block of file to open Exit: A <> 0, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if error Affected: AF Usage: Opens the file specified by the addressed I/O Con trol Block for input or output. FXI$OPEN opens the file in the current directory after initializ ing the FCB and loads as much of the buffer space as possible with data from the file. If the file does not exist, FXI$OPEN returns an error code. FXO$OPEN deletes the file referenced by the FCB if it exists and opens the referenced file for out put. If there is no directory space remaining in which to store the file's entry, FXO$OPEN returns an error code. The FXIO standard error return codes are used. A=0 and zero flag set (Z) if error. Routines: FXI$CLOSE, FXO$CLOSE Function: Close input or output file Entry: DE = address of an I/O Control Block Exit: A <> 0, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if close error Affected: AF Usage: Closes the file whose I/O Control Block is ad dressed by DE. FXI$CLOSE simply closes the file. FXO$CLOSE flushes the working buffer to disk, filling the last 128-byte block with ^Z's if not completely filled already, and closes the file on disk. The FXIO standard error return codes are used with A=0 and the zero flag set (Z) if an error occured. Routine: FX$GET Function: Byte input routine Entry: None Exit: A = next byte from file, zero clear (NZ) if no error A = 0, zero flag set (Z) if read past EOF Affected: AF Usage: Gets the next byte from the file whose I/O Control Block is pointed to by DE. The corresponding open function (FXI$OPEN) must have been called before any call to FX$GET. Routine: FX$PUT Function: Byte output routine Entry: A = byte to output to specified file Exit: A = output byte, zero clear (NZ) if put OK A = 0, zero flag set if write error Affected: AF Usage: Puts the specified byte into the file specified in the I/O Control Block pointed to by DE. The cor responding open function (FXO$OPEN) must have been called before any call to FX$PUT. BYTE-ORIENTED FILE I/O WITH VARIABLE BUFFERS AND UNGET: In addi tion to the FX routines covered in the previous section are the FY routines. For only a slight increase in memory requirements, the FY prefix routines provide the same functions as the FX rou tines and add the UNGET function. FY$UNGET sets the next character to be returned by FY$GET. Only one character ahead can be set. This function is extremely use ful in applications which read and parse an input file in a sin gle pass. Often the end of a token is detected only when the character after the token is picked up and examined. FY$UNGET allows you to put this character back, so that the next FY$GET picks it up and can process it in its own right as opposed to being a part of the token processing routine. Aside from the new FY$UNGET function, FY prefix routines provide the same functions as the FX prefix routines. The I/O Control Block for the FY routines, however, is two bytes larger than the IOCB for the FX routines. The routines described in this section are: routine similar to function FYI$OPEN FXI$OPEN open file for input FYO$OPEN FXO$OPEN open file for output FYI$CLOSE FXI$CLOSE close input file FYO$CLOSE FXO$CLOSE close output file FY$GET FX$GET get byte FY$UNGET unget byte FY$PUT FX$PUT put byte All of the file extended byte I/O routines (FY means file extend ed beyond FX) work with an I/O Control Block structured as: block length user- offset (bytes) set?* function 0 1 Y Number of 128-byte pages in working buffer 1 1 N End of file flag 2 2 N Byte counter 4 2 N Next byte pointer 6 1 N Character pending flag 7 1 N Pending character 8 2 Y Address of working buffer 10 36 Y FCB of file (only Fn and Ft fields set by user) *"user-set" means that you must initialize this value before these routines are called. The following DEFB/DEFS structure can be used in the calling program to implement the I/O Control Block: IOCTL: DEFB 8 ; use 8 128-byte pages (1K) DEFS 7 ; filled in by FYIO DEFW WORK ; address of working buffer IOCFCB: DEFS 1 ; filled in by FYIO to 0 DEFB 'MYFILE ' ; filename DEFB 'TXT' ; filetype DEFS 24 ; filled in by FYIO WORK: DEFS 128*8 ; working buffer (1K) All of the FYIO routines are consistent in that DE always points to the I/O Control Block (IOCTL above) and A and the PSW are used to pass flags and values. A sample program body which illus trates the calling procedures: ... [Initialize IOCTL1 and IOCTL2, where 1 is input, 2 is output] ... LD D,IOCTL1 CALL FYI$OPEN ; open 1 for input JR Z,FNF ; ..jump if file not found err LD D,IOCTL2 CALL FYO$OPEN ; open 2 for output JR Z,NODIR ; ..jump if no dir space error ... ... LD D,IOCTL1 CALL FY$GET ; get next input byte in A JR Z,EOF ; ..jump to process EOF ... LD D,IOCTL1 LD A,CH ; unget character CH CALL FY$UNGET ... LD D,IOCTL2 CALL FY$PUT ; put byte in A to output file JR Z,WERR ; ..jump to process write error ... LD D,IOCTL1 CALL FYI$CLOSE ; close input file JR Z,FCERR ; ..jump if file close error LD D,IOCTL2 CALL FYO$CLOSE ; close output file JR Z,FCERR ; ..jump if error ... This simple example illustrates the flexibility of the FYIO rou tines. As many files as desired may be open for input or output, each file having its own I/O Control Block and working buffer. The advantages in efficient disk accessing with this set of rou tines over the previous ones are notable. The major disadvantage of using these routines is that the buf fers are larger and the overhead of always ensuring that DE points to the proper I/O Control Block before each routine is called is present. Routines: FYI$OPEN, FYO$OPEN Function: FYIO file open routines Entry: DE = pointer to I/O Control Block of file to open Exit: A <> 0, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if error Affected: AF Usage: Opens files for subsequent processing by other FY- prefix routines. FYI$OPEN opens the file in the current directory after initializing the FCB and loads as much of the buffer space as possible with data from the file. If the file does not exist, FYI$OPEN returns an error code. FYO$OPEN deletes the file referenced by the FCB if it exists and opens the referenced file for output. If there is no directory space remaining in which to store the file's entry, FYO$OPEN returns an error code. Routine: FYI$CLOSE, FYO$CLOSE Function: FYIO file close routines Entry: DE = pointer to I/O Control Block Exit: A <> 0, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if close error Affected: AF Usage: Closes files opened by the respective FY-prefix open routines. FYI$CLOSE simply closes the file. FYO$CLOSE flushes the working buffer to disk, filling the last 128-byte block with ^Z characters if not completely filled already, and closes the file. Routine: FY$GET Function: FYIO byte input routine Entry: None Exit: A = next byte, zero clear (NZ) if no error A = 0, zero flag set (Z) if past EOF Affected: AF Usage: Reads the contents of files opened by appropriate FY open routines. FY$GET gets the next byte from the specified file. FYI$OPEN must have been called before any call to FY$GET. Routine: FY$UNGET Function: FYIO byte unget routine Entry: A = byte to "Unget" Exit: A = character, zero flag clear (NZ) if OK A = character, zero set (Z) if byte pending already Affected: AF Usage: Sets the next byte to be returned by FY$GET. FY$UNGET may only be called once before the next FY$GET, since it works only one byte ahead. If a byte was already pending, FY$UNGET returns an error code with no UNGET function. A call to FYI$OPEN is required before FY$UNGET can be used. Routine: FY$PUT Function: FYIO byte output routine Entry: A = byte to output Exit: A = character, zero flag clear (NZ) if OK A = 0, zero flag set (Z) if write error Affected: AF Usage: Changes the contents of files opened by appropri ate FY open routines. FY$PUT puts the next byte into the specified file. FYO$OPEN must have been called before any call to FY$PUT. GENERAL PURPOSE CP/M FILE MANIPULATION ROUTINES: The following routines are general-purpose file I/O routines which interface to CP/M through the entry point at location 5. They preserve BC, DE, and HL, and return with the standard CP/M error codes for the corresponding routines. These routines are: F$CLOSE F$MAKE F$READ F$WRITE F$DELETE F$MOPEN F$RENAME R$READ F$EXIST F$OPEN F$SIZE R$WRITE The routines GFA, SCFA, and SFA all deal with getting (GFA) and setting (SCFA and SFA) the attributes of files whose FCBs are addressed by DE. The following files allow you to append to the end of an existing file conveniently. They return unique error codes. F$APPEND GETRR GETFS F$APPL GETRR1 GETFS1 Routine: F$CLOSE Function: Close a file Entry: DE = points to FCB for desired file Exit: A = 0, zero flag set (Z) if close OK A <> 0, zero clear (NZ) if error in closing Affected: AF Usage: Closes a specified file in the current drive and user area. Routine: F$DELETE Function: Delete a file Entry: DE = points to FCB for file to delete Exit: A = 0, zero flag set (Z) if delete OK A <> 0, zero clear (NZ) if file not found Affected: AF Usage: Deletes a specified file from current drive and user area. Routine: F$EXIST Function: Test for existence of a file Entry: DE = address of an FCB for file to test Exit: A <> 0, zero flag clear (NZ) if file exists A = 0, zero flag set (Z) if file not found Affected: AF Usage: Tests for the presence of a specified file in the current disk and user area. Status is returned showing the results of the search. Routine: F$MAKE Function: Create a file Entry: DE = points to an FCB for the desired file Exit: A = directory code [0..3] if file is created OK A = 0FFh if no directory space is available Affected: AF Usage: Creates (makes) a specified file in the current drive and user area. Routine: F$OPEN Function: Open a file Entry: DE = pointer to FCB for desired file Exit: A = 0, zero flag set (Z) if file opened OK A <> 0, zero flag clear (NZ) if not opened Affected: AF Usage: Opens a specified file in the current drive and user area. Routine: F$MOPEN Function: Open a file with creation Entry: DE = pointer to FCB for file to open Exit: A = 0, zero flag set (Z) if file opened OK A <> 0, zero clear (NZ) if no directory space (error) Affected: AF Usage: Opens a specified file. If the file is not found, F$MOPEN tries to create one. This routine should not be used as a substitute for existence testing with F$EXIST. Routine: F$APPEND Function: Append to a file Entry: DE = pointer to an FCB for the desired file Exit: A = 0, zero flag set (Z) if file opened OK A = error code, zero flag clear (NZ) if error is: 1 = file not found 2 = file is full (no more room) 3 = file found but empty Affected: AF, current DMA buffer has last file record if A=0 Usage: Opens a file for appending. The results of the operation are reported. Various error conditions can occur, and are reported. Error 3 is a note that the file is empty and is not fatal (process ing can continue). If the append is successful, the current DMA buffer contains the last record in the file. The next sequential write will write to the record after the last one in the file. (See F$APPL which starts writing on the last record of the file). Example: See F$APPL below. Routine: F$APPL Function: Append to a file Entry: DE = pointer to FCB for desired file Exit: A = 0, zero flag set (Z) if file opened OK A = error code, zero flag clear (NZ) if error 1 = file not found 2 = file is full (no more room) 3 = file found but empty Affected: AF, current DMA buffer has last record if A=0 Usage: Opens a file for appending. The results of the operation are reported. Various error conditions can occur, and are reported. Error 3 is a note that the file is empty and is not fatal (process ing can continue). If the APPL is successful, the last record in the file is in the current DMA buffer. The next sequential write (F$WRITE) will write back over the last record in the file. Example: The following code segment illustrates the intend ed usage for the two file append routines. With F$APPEND: With F$APPL: ... ... LD DE,FCB LD DE,FCB CALL F$APPEND CALL F$APPL ... ... [Prepare next record] [Modify last record] ... ... LD DE,FCB LD DE,FCB CALL F$WRITE ; after last CALL F$WRITE ; on last ... ... LD DE,FCB LD DE,FCB CALL F$CLOSE ; close file CALL F$CLOSE ; close ... ... Routine: F$READ Function: Read a block from a file Entry: DE = pointer to FCB for desired file Exit: A = 0, zero flag set (Z) if read OK A = error code, zero flag clear (NZ) if error 1 = read past end of file 2 = reading unwritten data in random access Usage: Reads the next block (128 bytes) of data from an open file in the current drive and user area. The data is loaded into the current DMA buffer. Routine: F$RENAME Function: Rename a file Entry: HL = pointer to first 12 bytes of new FCB DE = pointer to first 12 bytes of old FCB Exit: A <> 0, zero flag clear (NZ) if rename OK A = 0, zero flag set (Z) if file not found error Affected: AF Usage: Renames a file in the current drive and user area. Only the Fn and Ft fields are significant in the FCB's, so the rest of the FCB need not be present for this function to work. Routine: F$SIZE Function: Compute file size Entry: DE = pointer to the 1st 12 bytes of an FCB Exit: HL = file size in kilobytes Affected: AF Usage: Obtains the computed size of a file (in K) based on its record count. This routine gives the file size correct to the next 1K, but does not take into account the grouping factor. Routine: F$WRITE Function: Write a block to a file Entry: DE = pointer to FCB for open file Exit: A = 0, zero flag set (Z) if write OK A = error code, zero clear (NZ) if error 1 = error in extending file 2 = end of disk data 0FFh = no more directory space Affected: AF Usage: Write the next 128 byte block of data from the current DMA buffer to a specified open file in the current drive and user area. Routines: GETRR, GETRR1 Function: Get random record number Entry: DE = pointer to FCB Exit: HL = random record number A = 0, zero flag set (Z) if no error A <> 0, zero flag clear (NZ) if random record overflow (value in A is error code) Affected: AF, HL Usage: Return the random record number of the last record read or written sequentially from the specified file. These routines are convenient in determin ing the current position in a file. GETRR does not affect the random record number field of the FCB and is larger in size. GETRR1 is smaller, but does affect the random record number field of the FCB. Routines: GETFS, GETFS1 Function: Get file size in records Entry: DE = pointer to FCB Exit: HL = number of records in file (file size) A = 0, zero flag set (Z) if no error A <> 0, zero flag clear (NZ) if random record overflow (value in A is error code) Affected: AF, HL Usage: Return the file size (in terms of records) of the file whose FCB is pointed to by DE. These rou tines are convenient in determining the number of records in a file. GETFS does not affect the random record number field of the FCB and is larg er in size. GETFS1 is smaller, but does affect the random record number field of the FCB. Routine: GFA Function: Get file attributes Entry: DE = pointer to FCB Exit: A = attribute code b0 = read-only attribute (1 = R/O, 0 = R/W) b7 = system attribute (1 = SYS, 0 = DIR) Affected: AF Usage: Returns the attributes of the file whose FCB is pointed to by DE. On return, A contains a code indicating the R/O and SYS attributes, where the 8th bit of A (b7) is 1 if the file is a system file and 0 if the file is a directory (non-system) file and the 1st bit of A (b0) is 1 if the file is read/only and 0 if the file is read/write. As a side effect, the MSBs of all bytes in the filename and filetype fields of the original FCB (bytes 1- 11, where byte 0 is first) are set equal to the MSBs of the corresponding directory entry. Routine: R$READ Function: Random read a block from a file Entry: DE = pointer to FCB HL = random record number Exit: A = 0, zero flag set (Z) if no error A = error code, zero clear (NZ) if error where: 1 = attempt to read unwritten record 3 = CP/M could not close current extent 4 = attempt to read unwritten extent 6 = attempt to read beyond end of disk Affected: AF Usage: Reads a block from the specified file in random mode. It is assumed that the file has already been opened by the F$OPEN routine or equivalent. Routine: R$WRITE Function: Random write of a block to a file Entry: DE = pointer to FCB HL = random record number Exit: A = 0, zero flag set (Z) if no error A = error code, zero flag clear (NZ) if error: 0 = no error (Z flag set) 1 = attempt to read unwritten record 3 = CP/M could not close current extent 4 = attempt to read unwritten extent 5 = directory full 6 = attempt to read beyond end of disk Affected: AF Usage: Writes data at the current DMA position to the designated file in a specific record number. This file should have been previously opened by a call to F$OPEN or equivalent. Routine: SCFA Function: Set and clear file attributes Entry: DE = pointer to FCB A = attribute code: b0 = read-only (1=set to R/O, 0=set to R/W) b7 = system (1=set to SYS, 0=set to DIR) Exit: A = 0, zero flag set (Z) if operation OK A <> 0, zero clear (NZ) if ambiguous file or not found Affected: AF Usage: Sets or clears read-only and system attributes of the specified file and clear all other attributes to 0 (the MSBs of bytes 1-8 and 11 are set to 0). Bits 0 and 7 of the A register are set to signify how the read-only and system bits are to be set in the file. All attribute bits other then read-only and system are cleared to zero. Routine: SFA Function: Set file attributes Entry: DE = pointer to FCB A = attribute code: b0 = read-only (1 = set to R/O, 0 = set to R/W) b7 = system (1 = set to SYS, 0 = set DIR) Exit: A = 0, zero flag set (Z) if operation OK A <> 0, zero clear (NZ) if ambiguous file or not found Affected: AF Usage: Sets or clears the read-only and/or system attri butes of the specified file while not affecting the other attribute bits (bytes 1-11, where byte 0 is first). All attributes in the FCB are set to those of the directory entry except for read-only and system. LIBRARY FILE MANIPULATION: Libraries are a method of combining a number of files into a single file in such a way that each member file can be discretely accessed. Advantages of libraries are that only one directory entry is needed for the library rather than one for each file, and only a maximum of 127 bytes per file is wasted compared to several thousand bytes wasted for small files on large hard disks. These routines provide a standard way to access files contained in libraries. Access to library files is via a library utility descriptor which is a block of memory organized as: LUD: DEFS 2 ; length of lbr directory (set by LUxx) DEFS 2 ; next block of curr file (set by LUxx) DEFS 2 ; # of remaining blks in file (by LUxx) LUFIL: DEFS 11 ; name of current file (set by LUOPEN) LUFCB: DEFS 36 ; FCB of library (Fn.Ft set by user) Multiple Libraries may be accessed by using several LUD's. Routine: LUINIT Function: Initialize file for library file manipulation Entry: DE = pointer to an LUD containing FCB and other info Drive and user of library must already be set. Exit: A = 0, zero flag set (Z) if no error A = error code, zero reset (NZ) if error is: 1 = file not found 2 = file empty 3 = library file format error Affected: AF, DMA address is set to 80hH by this routine Usage: Must be called for each LUD before it is used to access any of the other routines in this section. You must insure that bytes 1-11 in the FCB section of the LUD are set with the desired library name and type before calling LUINIT. Routine: LUDIR Function: Return directory list for library Entry: DE = address of a library utility descriptor (LUD) HL = address of ambiguous 11-char filename and type BC = pointer to start of memory buffer Drive and user of library must already be set. Exit: A = 0, zero flag set (Z) if operation OK A <> 0, zero flag reset (NZ) if TPA overflow Affected: AF, DMA address is set to 80h by this routine Usage: Locates all files in a library matching a speci fied ambiguous or non-ambiguous filename and type. If all question marks or spaces are specified, a file with all spaces in name and type fields will be returned. Files are listed in 17-byte entries organized as: DEFB 'FILENAME' ; 11-char filename DEFB 'TYP' ; 3-char filetype DEFW START_IDX ; index of file start DEFW LENGTH ; # of 128-byte blocks in file DEFW FILE_CRC ; CRC of file Routine: LUOPEN Function: Open a library file for access Entry: DE = address of a library utility descriptor (LUD) HL = pointer to filename and type Drive and user of library must already be set Exit: A = 0, zero flag set (Z) if open OK A <> 0, zero flag reset (NZ) if file not found Affected: AF, DMA address is set to 80h by this routine Usage: Opens a file in a library for access by LUREAD. The filename and type addressed by HL may be am biguous in which case the first file in the libra ry matching the specification will be opened. The exact name may be determined by examining the current file Name section of the LUD after calling LUOPEN. Routine: LUCLOSE Function: Close a library file Entry: DE = points to library utility descriptor Exit: None Affected: None Usage: Zeros the index and length fields of the LUD, but does nothing else since no close is needed on a file which is only accessed for reading. Routine: LUREAD Function: Read record from a file in a library Entry: DE = address of a library utility descriptor (LUD) Drive and user of library must already be set Exit: A = 0, zero flag set (Z) if read OK A <> 0, zero flag reset (NZ) if end-of-file Affected: AF Usage: May be used in the same manner as other SYSLIB routines to read a single 128-byte record to the current DMA address. The current record and num ber of records remaining fields of the LUD are updated by each call to LUREAD. FILENAME STRING PARSER: Routine: FNAME Function: Filename string parser Entry: HL = pointer to target string ending with delimiter DE = pointer to a 36-byte long FCB Exit: B = disk (drive A=1..P=16, 0FFh=no disk specified) C = user (0..31, '?'=all users, 0FFh=no user spec) HL = pointer to the character which ended the scan A <> 0, zero flag clear (NZ) if string parsed OK A = 0, zero set (Z) if invalid disk or user Affected: AF, BC, HL Usage: Parses a string to a specified FCB, and puts disk and user to registers. The string is assumed to be in form: DU:FILENAME.TYP where any part of the specification is optional. It clears all bytes of the FCB to zero except for the Fn (filename) and Ft (filetype) fields which are initialized to values extracted from the string, or spaces if absent. The string pointed to by HL is not a conventional string in the sense of the rest of the SYSLIB routines. It is ended by any of the following delimiters, as opposed by simply always being ter minated by a binary zero. The delimiters are: , , "=", "_", ";", ",", "<", ">" Examples: TEST.TXT = FN=TEXT, FT=TXT, B=0FFh, C=0FFh A:T = FN=T, FT=, B=1, C=0FFh 5:T = FN=T, FT=, B=0FFh, C=5 C10:X.Y = FN=X, FT=Y, B=3, C=10 FILE CONTROL BLOCK INITIALIZTION: Routine: INITFCB Function: FCB initialization Entry: DE = pointer to 36-byte FCB buffer Exit: None Affected: None Usage: A general purpose application to clear all bytes in an FCB to zero except for the filename and type fields. Using INITFCB to prepare FCBs for use destroys any drive specification in the first byte of the FCB. It will be set to zero equating to the currently logged drive. DISK/USER MANIPULATION ROUTINES: This is a set of six routines which allow the user to readily move around between disks and user Areas. These routines are: GUA -- return the current user SUA -- log into a specified user area RETUD -- return the current disk and user LOGUD -- log into a specified disk and user PUTUD -- save away the current disk and user GETUD -- restore the disk and user saved by PUTUD GUA and SUA are to be used to find out what user area the program is in (GUA) and to enter a specific user area (SUA). For exam ple: CALL GUA ; find out current user PUSH AF ; save it [move around on other user areas] POP AF ; get current user CALL SUA ; log into user GUA and SUA are useful in conjunction with the automatic disk logging feature of CP/M, where the first byte of the FCB indi cates a disk to autolog (0=default, 1=A, 2=B, etc.). RETUD and LOGUD are to be used to find out where the program is (RETUD) and to enter a specific disk and user area (LOGUD). For example: CALL RETUD ; find out where we are PUSH BC ; save disk/user [move around on disks/users] POP BC ; get disk/user CALL LOGUD ; log into disk/user PUTUD and GETUD are designed to be used as a place marker and return combination. They are intended to be used in such code sequences as the following: CALL PUTUD ; mark current location [move around on disks/users] CALL GETUD ; return to marked location Since PUTUD stores the values in a single level buffer, multiple calls to PUTUD should be avoided since GETUD will restore the last disk/user saved by PUTUD. Routine: GUA Function: Return current user area Entry: None Exit: A = user area (0-31) Affected: AF Usage: Returns the currently logged user area. No error codes exist with this function. Routine: SUA Function: Set current user area Entry: A = user area (0-31) Exit: None Affected: None Usage: Logs into the user area represented by the low- order 5 bits of the supplied value (value 0-31). No error codes exist with this function. Routine: RETUD Function: Return the current disk and user Entry: None Exit: B = disk (drive A=0), C = user (0..31) Affected: BC Usage: Returns the currently logged user number and cur rently logged drive in a single operation. Routine: LOGUD Function: Log into a disk and user Entry: B = disk (drive A=0), C = user (0..31) Exit: None Affected: None Usage: Logs in a specified drive and sets the specified user area to current in a single operation. Routine: PUTUD Function: Save away disk and user Entry: None Exit: None Affected: None Usage: Commonly used near the beginning of a program or routine to save the current user and disk numbers for restoration upon program or routine exit. PUTUD saves the current disk and user in a local buffer, while GETUD restores these saved settings to the currently logged BDOS values. The buffer used by PUTUD and GETUD is internal and not avail able for general use. Routine: GETUD Function: Restore disk and user saved by PUTUD Entry: None Exit: None Affected: None Usage: Commonly used near the beginning of a program or routine to save the current user and disk numbers for restoration upon program or routine exit. PUTUD saves the current disk and user in a local buffer, while GETUD restores these saved settings to the currently logged BDOS values. The buffer used by PUTUD and GETUD is internal and not avail able for general use. Routine: SETDMA Function: Set the BDOS DMA transfer address Entry: HL = start of DMA buffer to set Exit: None Affected: None Usage: Sets the DMA transfer address within the BDOS and BIOS to the specified address. Since no registers are destroyed by this routine, it is suitable for use within loops in programs. NUMERIC STRING EVALUATION: Routine: EVAL Function: General-purpose numeric string evaluation Entry: HL = address of first byte of string to convert Exit: HL = points to character after converted string (or character causing error if error flag set) DE = 16-bit binary value of string A = E value, carry flag clear (NC) if OK Carry flag set (C) if error in string Affected: AF, DE, HL Usage: Converts the character string pointed to by HL into a 16-bit binary representation. EVAL per forms the conversion until a non-hexadecimal char acter is encountered, at which time it looks at the last character and the previous character to determine if the string is representing a binary, octal, decimal, or hexadecimal number. Input string characters may be uppercase or lowercase. Valid input string formats are: binary string, where b=0 or b=1 bbbbbbbbbbbbbbbbB decimal string, where 0 <= t <= 9 ttttt tttttD hexadecimal string, where 0 <= h <= F hhhhH hhhhX octal string, where 0 <= o <= 7 oooooooO oooooooQ Routine: EVAL16 Function: Hexadecimal string evaluation Entry: HL = address of first character of string to con vert Exit: HL = points to character terminating conversion DE = contains the 16-bit binary value of string A = E value Affected: AF, DE, HL Usage: Converts the string of ASCII hexadecimal charac ters pointed to by HL into a 16-bit binary value. Conversion progresses until an invalid hexadecimal digit (0-9, A-F) is encountered. Routine: EVAL10 Function: Decimal string evaluation Entry: HL = address of first character of string to convert Exit: HL = points to character terminating conversion DE = contains the 16-bit binary value of string A = E value Affected: AF, DE, HL Usage: Converts the string of ASCII decimal characters pointed to by HL into a 16-bit binary value. Conversion progresses until an invalid decimal digit (0-9) is encountered. Routine: EVAL8 Function: Octal string evaluation Entry: HL = address of first character of string to convert Exit: HL = points to character terminating conversion DE = contains the 16-bit binary value of string A = E value Affected: AF, DE, HL Usage: Converts the string of ASCII octal characters pointed to by HL into a 16-bit binary value. Conversion progresses until an invalid octal digit (0-7) is encountered. Routine: EVAL2 Function: Binary string evaluation Entry: HL = address of first character of string to convert Exit: HL = points to character terminating conversion DE = contains the 16-bit binary value of string A = E value Affected: AF, DE, HL Usage: Converts the string of ASCII binary characters pointed to by HL into a 16-bit binary value. Conversion progresses until an invalid binary digit (0-1) is encountered. THE L, M, P, AND S NUMERIC OUTPUT ROUTINES: The numeric output routines described here are used to output either the HL register pair or the A register in a variety of forms. These forms are as hexadecimal characters, as decimal characters, as decimal charac ters with leading spaces, and as decimal characters with no lead ing zeroes or spaces. In addition, each of these routines has a prefix to their names: L, M, P, or S. These prefixes indicate the output destination. L indicates the LST device (or printer), M indicates memory, P indicates the console (print the output), and S indicates a switched output to nothing, the console, the printer, or both. For example, PADC sends A as decimal characters with leading spaces to the console, while LADC sends A as decimal characters with leading spaces to the printer. The S-series of routines is different from the other series in that the S-series uses an external data byte to determine where the output is to be routed. This byte is referred to as SCTLFL (S Control Flag), and its switching function is illustrated in the following table. SCTLFL: binary hex outputs to 00000000b 00h nothing 00000001b 01h console 10000000b 80h printer 10000001b 81h console and printer If you do not initialize the SCTLFL variable before using the S- routine, output will go to the console (the default is 01h). An example of code using S-routines is: EXT SCTLFL,SADC ; SCTLFL flag, SADC routine ... LD A,81H ; enable printer and console LD (SCTLFL),A ... LD A,32 ; print number 32 CALL SADC ... LD A,80H ; enable printer only LD (SCTLFL),A ... LD A,150 ; print number 150 CALL SADC ... SAMPLE NUMERIC OUTPUTS: The following tables illustrate how values will be output by the various routines. The underscore character (_) indicates a space. Value xA2HC xA3DC xADC xAFDC 0 00 000 __0 0 10 0A 010 _10 10 255 FF 255 255 255 Value xHL4HC xHL5DC xHLDC xHLFDC 0 0000 00000 ____0 0 10 000A 00010 ___10 10 100 0064 00100 __100 100 1000 03E8 01000 _1000 1000 65535 FFFF 65535 65535 65535 Routines: LA2HC, PA2HC, SA2HC Function: Print A as two hex characters Entry: A = value to be converted and printed Exit: None Affected: None Usage: Prints a byte as two hexidecimal characters on LST: (LA2HC), CON: (PA2HC), or switched output (SA2HC). Routine: MA2HC Function: Store A as two hex characters in memory Entry: A = value to be converted and stored DE = pointer to start of 2-byte buffer Exit: DE = points to byte after string Affected: DE Usage: Stores a byte in memory as two (2) hexadecimal characters. Routines: LA3DC, PA3DC, SA3DC Function: Print A as three decimal digits Entry: A = binary value to convert and print Exit: None Affected: None Usage: Prints a byte (0..255) as three (3) decimal char acters in a fixed length space on LST: (LA3DC), CON: (PA3DC), or switched output (SA3DC). Routine: MA3DC Function: Store A as three decimal digits in memory Entry: A = binary value to convert and store DE = pointer to 3-byte buffer Exit: DE = points to the byte after the buffer Affected: DE Usage: Stores a byte in memory as three (3) decimal dig its. Routines: LADC, PADC, SADC Function: Print byte as up to three decimal digits Entry: A = binary value to convert and print Exit: None Affected: None Usage: Prints a byte in variable format with leading spaces (right justified) on LST: (LADC), CON: (PADC), or switched output (SADC). Routine: MADC Function: Store a byte as up to three digits in memory Entry: A = binary value to convert and store DE = pointer to 3-byte memory buffer Exit: DE = points to byte after the buffer Affected: DE Usage: Stores a byte in memory in a fixed three character buffer as up to three (3) decimal characters with leading spaces. Routines: LAFDC, PAFDC, SAFDC Function: Print A as 1 to 3 digits (variable) Entry: A = binary value to be converted and printed Exit: None Affected: None Usage: Prints a byte as one to three decimal characters with no leading spaces on LST: (LAFDC), CON: (PAFDC), or switched output (SAFDC). Routine: MAFDC Function: Store A as 1 to 3 digits (variable) in memory Entry: A = value to be converted and stored DE = pointer to a 3-byte buffer Exit: DE = points to the byte after the last one saved Affected: DE Usage: Stores a byte as up to three (3) decimal digits in a 3-byte memory buffer. Routines: LHL4HC, PHL4HC, SHL4HC Function: Print 16-bit value as four hexadecimal chars Entry: HL = 16-bit value to print Exit: None Affected: None Usage: Prints HL as four (4) hexadecimal characters on LST: (LHL4HC), CON: (PHL4HC), or switched output (SHL4HC). Routine: MHL4HC Function: Save 16-bit value as four hexadecimal characters Entry: HL = 16-bit value to convert and save DE = pointer to 4-byte buffer Exit: DE = points to byte after buffer Affected: DE Usage: Stores HL as four (4) hexadecimal characters in a 4-byte memory buffer. Routine: LHL5DC, PHL5DC, SHL5DC Function: Print 16-bit value as 5 decimal characters Entry: HL = 16-bit value to print Exit: None Affected: None Usage: Prints HL as five (5) decimal characters on LST: (LHL5DC), CON: (PHL5DC), or switched output (SHL5DC). Routine: MHL5DC Function: Save 16-bit value as 5 decimal characters Entry: HL = value to be converted and stored DE = pointer to 5-byte buffer Exit: DE = points to byte after buffer Affected: DE Usage: Stores HL as five (5) decimal characters in a 5- byte memory buffer. Routine: LHLDC, PHLDC, SHLDC Function: Print 16-bit value as 1-5 decimal digits Entry: HL = value to be printed Exit: None Affected: None Usage: Prints HL as one to five decimal digits with leading spaces on LST: (LHLDC), CON: (PHLDC), or switched output (SHLDC). Routine: MHLDC Function: Store 16-bit value as 1-5 decimal digits in memory Entry: HL = value to convert and store DE = pointer to five byte memory buffer Exit: DE = points to byte after buffer Affected: DE Usage: Converts and stores HL as one to five decimal characters with leading spaces in a 5-byte memory buffer. Routine: LHLFDC, PHLFDC, SHLFDC Function: Print HL as 1 to 5 decimal digits Entry: HL = value to be printed Exit: None Affected: None Usage: Prints HL as one to five decimal digits with no leading spaces on LST: (LHLFDC), CON: (PHLFDC), or switched output (SHLFDC). Routine: MHLFDC Function: Store HL as 1 to 5 decimal digits in memory Entry: HL = value to convert and store DE = pointer to 5-byte memory buffer Exit: DE = points to byte after last one stored Affected: DE Usage: Converts and stores HL as one to five decimal digits in a 5-byte buffer. INPUT LINE EDITORS: An input line editor is used to accept a line of text from the terminal, allowing you to issue commands like backspace and ^X (erase all of line typed so far) to edit text as you enter it. Once the text has been entered, the input line editor returns to the calling program with your text stored in a buffer. This text is terminated by a binary 0. Two of the input line editors in SYSLIB use the CP/M BDOS to provide the line editor function. They mainly serve to preserve the registers during the function call and to store the terminat ing zero at the end of the text. They occupy less space than the third input line editor, INLINE. The third input line editor, INLINE, is used when security is important. Unlike the other two, when typing a ^C to INLINE, the input line editor (and calling program) is not aborted and con trol returned to CP/M. Instead, the ^C character is simply stored in your line. Also, unlike the other two, INLINE can be instructed to echo or not echo the input characters. This fea ture is useful for programs which want to input a password. INLINE can be instructed not to echo the password, but it will still provide the line editing functions so that you can correct any mistakes. Routine: BBLINE Function: BDOS-based line editor with internal buffer Entry: A = 0 to not capitalize line A <> 0 to capitalize line Exit: HL = pointer to first character in the line A = number of characterss in the line (excluding ending zero) Affected: AF, HL Usage: BBLINE provides a very convenient interface to the BDOS for input line editor functions. It contains an internal buffer for storage of the input line (200 bytes allocated), and it returns a pointer to the first byte of the line upon return. The line stored in this buffer is terminated by a NUL (0). To use BBLINE, you only need to call it with the capitalization flag set for the desired action. Routine: BLINE Function: BDOS-based line editor with user-supplied buffer Entry: A = 0 to not capitalize line A <> 0 to capitalize line HL = pointer to first byte of user-supplied buffer Exit: HL = pointer to first character in the line A = number of characters in the line (excluding ending zero) Affected: AF, HL Usage: BLINE performs the same type of function as BBLINE, but does not contain an internal buffer. You are expected to provide a buffer, structured as: SIZE: DEFB ; size of buffer CCNT: DEFS 1 LINE: DEFS ; size of buffer + 1 To use BLINE, call it with the address of the buffer (SIZE in the example), and the capitaliza tion flag. BLINE returns a pointer to the first byte of the line (LINE) upon return. The line stored in this buffer is NUL-terminated. Routine: INLINE Function: Independent input line editor Entry: HL = pointer to input line buffer A = echo flag (A=0 for no echo, A<>0 to echo input) Exit: None Affected: None Usage: INLINE essentially provides all of the convention al input line editor functions. It is somewhat more flexible than BLINE and BBLINE, but the tradeoff is that INLINE takes up more space. If security is not required, you should use BLINE or BBLINE instead of INLINE. You may edit the text as you type it with the following editor commands: key function Delete previous character and back up cursor Delete previous character and echo it Input complete, return to calling program Go to next physical line; adding a to buffer Move to next tab stop (every 8 spaces) ^U Erase line (clear buffer) and re start input (same as ^X) ^X Erase line (clear buffer) and re start input (same as ^U) ^R Retype current line ^E Go to next physical line; add no thing to buffer On exit, the buffer contains the text entered followed by a (binary 0); the typed to end the input is not placed in the buffer. INLINE offers two features not found in BLINE and BBLINE. First, it cannot be aborted by a ^C; this is good, since it can be used in "secure" programs without fear of breaking out of the program. Second, it can be made to echo or not echo the input; this provides some protection for inputting sensitive information, such as passwords. A BEL character (beep on console) is output if attempt is made to delete characters with BS or DEL before the beginning of the line. No limit or error checking is made on the size of the input line buffer, so you should made the buffer arbi trarily large to avoid buffer overflow. A hash mark (#) is printed in response to ^R, ^U, and ^X. STRING AND SWITCHED OUTPUT: The switched output series of rou tines is different from the other series in that the switched output series uses a global data byte (SCTLFL -- S Control Flag) to determine where the output is to be routed. Its switching functions are: SCTLFL: binary hex outputs to 00000000b 00h nothing 00000001b 01h console 10000000b 80h printer 10000001b 81h console and printer If you do not initialize the SCTLFL variable before using an S- routine, output will go to the console (default value of SCTLFL is 01h). An example of code using S-routines is: EXT SCTLFL,SADC,SOUT ; declare routines/value ... LD A,81H ; enable printer and console LD (SCTLFL),A ... LD A,32 ; print number 32 CALL SADC ... LD A,80H ; enable printer only LD (SCTLFL),A ... LD A,'D' ; print letter "D" CALL SOUT ... Routines: PRINT, EPRINT, LPRINT, SPRINT Function: PRINT prints to console interpreting control char acters, EPRINT prints to console only expanding tabs, LPRINT prints to printer interpreting con trol characters, SPRINT prints to switched (con sole/printer) interpreting control characters Entry: stack = points to NUL-terminated (binary 0) string Exit: None (execution resumes at byte after ending NUL) Affected: None Usage: Most often used for "inline" print requirements where the text strings are embedded within the executable code. With the exception of EPRINT, control characters other than TAB, BS, CR, LF, and BEL are output as "^c" sequences. (See character output routines.) Example: EXT PRINT ; declare the routine ... ; ..preceeding code CALL PRINT ; print the following string DEFB 'Hello World',0 ... ; execution resumes here Routines: PSTR, EPSTR, LPSTR, SPSTR Function: PSTR prints to console interpreting control char acters, EPSTR prints to console only expanding tabs, LPSTR prints to printer interpreting control characters, SPSTR prints to switched (console/ printer) interpreting control characters Entry: HL = pointer to NUL-terminated (binary 0) string Exit: HL = points to byte following NUL terminating string Affected: HL Usage: Prints NUL-terminated strings from indexed strings or remotely-located places in the code body. With the exception of EPSTR, control characters other than TAB, BS, CR, LF, and BEL are output as "^c" sequences. (See character output routines.) FILENAME OUTPUT: Filename output routines described here are used to display the filename and filetype stored in an FCB in a variety of forms. These forms are denoted in the routine names (xFNn) as: xFN1 -- print filename in 12-character field, embedded spaces xFN2 -- print filename in n-character field, no spaces xFN3 -- print filename in 12-character field, trailing spaces The following illustrates how values will be output by these routines. The underscore character (_) indicates a space. FCB name/type xFN1 xFN2 xFN3 FILENAMETYP FILENAME.TYP FILENAME.TYP FILENAME.TYP MYFILE TXT MYFILE__.TXT MYFILE.TXT MYFILE.TXT__ R R R_______.R__ R.R R.R_________ S S_______.___ S. S.__________ T ________.T__ .T .T__________ In addition to the method of printing the filename and filetype, each of these routines has a prefix to its name: L, M, P, or S. These prefixes indicate where the output is to be sent. L indi cates the printer (or LST device), M for memory, P for the con sole (print the output), and S for a switched output to nothing, the console, the printer, or both. The list is: letter example outputs to L LFN1 LST device (printer) M MFN1 Memory pointed to by HL P PFN1 CON device (console) S SFN1 Switched output Routines: LFNn, PFNn, SFNn Function: LFNn prints filename to printer (LST device), PFNn prints filename to console (CON device), SFNn prints filename to switched (LST/CON) devices Entry: DE = address of FCB+1 Exit: None Affected: None Usage: Prints filename and filetype information from a File Control Block (FCB). The n in the routine name specifies the method in which to display the information. Values of n are 1 to 3, where 1 prints fixed 12-character output with embedded spaces, 2 prints variable length (up to 12 chars) with no trailing spaces, and 3 prints fixed 12- char output with trailing spaces. (See Filename Output above.) Routine: MFNn Function: Store filename in memory Entry: DE = pointer to FCB+1 HL = pointer to memory buffer of at least 12 char acters Exit: None Affected: None Usage: Stores a filename and filetype in memory formatted as the routines for console and printer output. The suffix n in the routine name specifies the form of the information where where 1 stores a fixed 12-character field with embedded spaces, 2 stores a variable length (up to 12 characters) in the field with no trailing spaces, and 3 stores a fixed 12-character field with trailing spaces. (See Filename Output above.) MFN1 and MFN3 are quite straight-forward to use since they always fill exactly 12 bytes of memory. Advancing to the next byte after the last one used is quite simple, as shown by: LD DE,FCB+1 ; point to Fn field LD HL,BUFFER ; ..and to memory buffer CALL MFN1 ; store the name LD BC,12 ; skip to after last byte ADD HL,BC ; ..by adding 12 to start MFN2 is not quite as easy to use since it fills at most 12 bytes, but could fill less than this. The problem may be overcome by using a 13-character buffer and the FILLB and SKNSP routines, as: LD HL,BUFFER ; point to buffer LD B,13 ; fill 13 bytes w/spaces LD A,' ' CALL FILLB LD DE,FCB+1 ; point to Fn field CALL MFN2 ; ..and store CALL SKNSP ; skip over non-spaces (HL now ... ; ..points to byte after last) CHARACTER-ORIENTED INPUT/OUTPUT: This set of routines provides simple I/O capabilities with absolutely no side effects on any registers. Direct BIOS calls are used on all routines except for BIN, BIST, and BOUT, so functions such as ^P (which are imple mented by the BDOS) will not work by-and-large. The I/O capabilities provided by these routines include: Character input from console and reader Character output to console, printer, and punch Character output to console, printer, and punch with control character processing Console input status Conditional input New line (CRLF) output Capitalized character input Switched output is provided in this set of routines; these are called the S-series of routines, and are complementary to the S- series numeric print routines. The S-series of routines is different from the other series in that the S-series uses an external data byte to determine where the output is to be routed. This byte is referred to as SCTLFL (S Control Flag), and its switching function is illustrated in the following table: SCTLFL: binary hex outputs to 00000000b 00h nothing 00000001b 01h console 10000000b 80h printer 10000001b 81h console and printer If you do not initialize the SCTLFL variable before using an S- routine, output will go to the console (the default is 01h). An example of code using S-routines is: EXT SCTLFL,SOUT ; SCTLFL flag, SOUT routine ... LD A,81H ; enable printer and console LD (SCTLFL),A ... LD A,'A' ; print character 'A' CALL SOUT ... LD A,80H ; enable printer only LD (SCTLFL),A ... LD A,'a' ; print character 'a' CALL SOUT ... Routine: BIN Function: BDOS console character input routine Entry: None Exit: A = character input from CON Affected: AF Usage: Inputs a character from the console with normal BDOS processing (echo, ^P and ^S sensing). Routine: BIST Function: BDOS character input status routine Entry: None Exit: A <> 0, zero flag clear (NZ) if character ready A = 0, zero flag set (Z) if no character Affected: AF Usage: Returns the console input status via BDOS function 11. Routine: BOUT Function: BDOS character output routine Entry: A = character to send to console display Exit: None Affected: None Usage: Outputs a character to the console via BDOS func tion 2. Routines: CAPIN, CAPINE Function: Capitalized character input Entry: None Exit: A = capitalized character input from console Affected: AF Usage: Waits for an input character from the console, capitalizes it, and returns it to your program. CAPIN simply returns the capitalized character, while CAPINE also echoes it to the console dis play. Routines: CIN, RIN Function: Input a character from the console or reader (aux iliary device) Entry: None Exit: A = character from console (CIN) or reader (RIN) Affected: AF Usage: Provides character input functions with BIOS-level interfaces avoiding BDOS processing. They are somewhat faster in response than their BDOS coun terparts. Routines: COUT, COUT7, LOUT, POUT, SOUT Function: COUT outputs a character to the console, COUT7 outputs a character to the console stripping high bit, LOUT outputs a character to the list device (printer), POUT outputs a character to the punch (auxiliary) device, SOUT outputs a character to the switched (CON/LST) output Entry: A = character to send to output device Exit: None (COUT7 returns character in A with high bit clear) Affected: AF Usage: For direct BIOS-level output within a program, these routines avoid the BDOS character traps and processing, and are therefore somewhat faster than BDOS routines. COUT7 is identical to COUT except that the high-order bit is stripped from the out put character before passing it to the driver. Routines: CCOUT, CLOUT, CPOUT, CSOUT Function: CCOUT outputs to console with control character display, CLOUT outputs to list device with control character display, CPOUT outputs to punch device with control character display, CSOUT outputs to switched CON/LST with control character display Entry: A = character to output Exit: None Affected: Flags Usage: These routines should be used to control printing to devices which may be disturbed by non-printing (control) characters. They function as their primary counterparts for normal printable charac ters, but treat all ASCII codes less than a space (20H) except for , , , , and in a special manner. These values are output as an caret (^) followed by the corresponding letter generated by adding 40h to the character value (i.e., 1 outputs as "^A", 2 as "^B", etc.). Routine: CONDIN Function: Conditional console input Entry: None Exit: A = console character, zero clear (NZ) if present A indeterminate, zero set (Z) if no character Affected: AF Usage: Tests for any waiting character on the console, and returns it. If no character is waiting, the routine returns a flag indicating that no charac ter was returned. Routine: CRLF, LCRLF, SCRLF Function: CRLF send carriage return and linefeed to console, LCRLF send carriage return and linefeed to LST (printer), SCRLF send carriage return and linefeed to switched output Entry: None Exit: None Affected: None Usage: Sends a new line combination of carriage return and linefeed to the CON (CRLF), LST (LCRLF), or switched output (SCRLF). Routine: CST Function: Return console status routine Entry: None Exit: A = 0, zero flag set (Z) if console data available A = 1, zero clear (NZ) if no data available Affected: AF Usage: Quickly samples the console status with a direct BIOS interface. BRANCHING: The routines in this section deal with conditional branching via CASE, computed GOTO, and arithmetic IF constructs. The following example illustrates the CASE concept: [register A = key value] CALL ACASE1 DEFB SIZE ; number of entries in table DEFW ERROR ; ..go here if no match DEFB VAL1 ; first value to test for DEFW ADDR1 ; ..go here if A = VAL1 DEFB VAL2 ; 2nd value to test for DEFW ADDR2 ; ..go here if A = VAL2 ... DEFB VALSIZE ; 'SIZE' value to test for DEFW ADDRSIZE ; ..go here if A = VALSIZE The following example illustrates the computed GOTO: [register A = index (zero-relative)] CALL AGOTO1 DEFW ADDR0 ; go here if A = 0 DEFW ADDR1 ; go here if A = 1 ... DEFW ADDRN ; go here if A = N The following example illustrates the computed GOTO with limits: [register A = index (zero-relative)] [register B = limit] CALL AGOTO1 DEFW ADDR0 ; go here if A = 0 DEFW ADDR1 ; go here if A = 1 ... DEFW ADDRN ; go here if A = N [error code] ; ..come here if A > B The following example illustrates the arithmetic IF: [register A = key value] [register B = test value] CALL AIF1 DEFW ADDRLT ; go here if A < B DEFW ADDREQ ; go here if A = B DEFW ADDRGT ; go here if A > B The following routines are provided: ACASE1 -- case statement with A = key value ACASE2 -- like ACASE1, but DE = address of case table ACASE3 -- like ACASE2, but return address is left on stack HCASE1 -- like ACASE1, but HL = key value HCASE2 -- like ACASE2, but HL = key value HCASE3 -- like ACASE3, but HL = key value AGOTO1 -- computed GOTO with A = key value AGOTO2 -- like AGOTO1, but JPs rather than DEFW follow HGOTO1 -- computed GOTO with HL = key value HGOTO2 -- like AGOTO2, but HL = key value BGOTO1 -- like AGOTO1, but B = limit value BGOTO2 -- like AGOTO2, but B = limit value DGOTO1 -- like HGOTO1, but DE = limit value DGOTO2 -- like HGOTO2, but DE = limit value AIF1 -- arithmetic IF with A, B = values AIF2 -- like AIF1, but JPs rather than DEFW follow HIF1 -- arithmetic IF with HL, DE = values HIF2 -- like AIF2, but HL, DE = values Routine: ACASE1 Function: Multiway jump from A register value, embedded table Entry: A = value to test for branch Exit: None (branch is made) Affected: None Usage: A case statement processor which acts as a multi way jump instruction, since the return address from the call to ACASE1 is not retained. The value to test is compared to values in a case table and control is transferred to an associated address if a match is found. Example: LD A,TEST CALL ACASE1 DEFB N ; number of entries in table DEFW DEFAULT ; goto address if no match DEFB VAL1 ; test for TEST = VAL1 DEFW ADDR1 ; go here if TEST = VAL1 ... DEFB VALN ; test for TEST = VALN DEFW ADDRN ; go here if TEST = VALN Routine: ACASE2 Function: Multiway jump from A register value, external table Entry: A = value to test for branch DE = address of case table Exit: None (branch is made) Affected: None Usage: A case statement processor which acts as a multi way jump. The return address from the call to ACASE2 is not retained. An entry value is com pared to values in an external case table and control is transferred to the associated address upon a match. Example: LD A,TEST ; value to test for LD DE,TABLE ; address of table CALL ACASE2 ... TABLE: DEFB N ; number of entries in table DEFW DEFAULT ; goto address if no match DEFB VAL1 ; test for TEST = VAL1 DEFW ADDR1 ; go here if TEST = VAL1 ... DEFB VALN ; test for TEST = VALN DEFW ADDRN ; go here if TEST = VALN Routine: ACASE3 Function: Multiway call from A register, external table Entry: A = value to test for call DE = address of case table Exit: None (branch is made) Affected: None Usage: ACASE3 is a case statement processor which func tions as a multiway CALL instruction with the return address from the call to ACASE3 left on the stack. The routine is entered with a value which is compared to those in a table and control is transferred to an associated address if a match is made. Example: LD A,TEST ; value to test for LD DE,TABLE ; address of table CALL ACASE3 [resume execution here if routines execute a RET instr] ... TABLE: DEFB N ; number of entries in table DEFW DEFAULT ; ..go here if no match DEFB VAL1 ; test for TEST = VAL1 DEFW ADDR1 ; ..go here if TEST = VAL1 ... DEFB VALN ; test for TEST = VALN DEFW ADDRN ; ..go here if TEST = VALN Routine: HCASE1 Function: Multiway jump from HL, embedded table Entry: HL = value to test for Exit: None (branch is made) Affected: None Usage: A case statement processor where a 16-bit value is compared to entries in a table. Upon a match, control is transferred to an associated address. The return address from the CALL to HCASE1 is not retained making this analagous to a jump instruc tion. Example: LD HL,TEST CALL HCASE1 DEFW N ; number of entries in table DEFW DEFAULT ; ..go here if no match DEFW VAL1 ; test for TEST = VAL1 DEFW ADDR1 ; ..go here if TEST = VAL1 ... DEFW VALN ; test for TEST = VALN DEFW ADDRN ; ..go here if TEST = VALN Routine: HCASE2 Function: Multiway jump from HL, external table Entry: HL = value to test for DE = address of case table Exit: None (branch is made) Affected: None Usage: A case statement processor where a 16-bit value is compared to entries in an addressed table. If a match is found, control is transferred to an asso ciated address from the table. The return address from the CALL to HCASE2 is not retained, so this routine functions as a jump. Example: LD H,TEST ; value to test for LD DE,TABLE ; address of table CALL HCASE2 ... TABLE: DEFW N ; number of entries in table DEFW DEFAULT ; ..go here if no match DEFW VAL1 ; test for TEST = VAL1 DEFW ADDR1 ; ..go here if TEST = VAL1 ... DEFW VALN ; test for TEST = VALN DEFW ADDRN ; ..go here if TEST = VALN Routine: HCASE3 Function: Multiway call from HL, external table Entry: HL = value to test for DE = address of case table Exit: None (branch is made) Affected: None Usage: A case statement processor where a 16-bit value is compared to entries in an addressed table. Ia a match is found, control is transferred to an asso ciated address from the table. The return address from the CALL to HCASE3 is retained so this rou tine functions as a call. Example: LD HL,TEST ; value to test for LD DE,TABLE ; address of table CALL HCASE3 [resume execution here if routines execute an RET instr] ... TABLE: DEFW N ; number of entries in table DEFW DEFAULT ; ..go here if no match DEFW VAL1 ; test for TEST = VAL1 DEFW ADDR1 ; ..go here if TEST = VAL1 ... DEFW VALN ; test for TEST = VALN DEFW ADDRN ; ..go here if TEST = VALN Routine: AGOTO1 Function: Computed GOTO on A register Entry: A = index value (zero-relative) Exit: None Affected: None Usage: A computed GOTO based on a specified 8-bit value. No range or limit checking is done, so you must insure that the computed GOTO does not exceed the table limit. Example: LD A,INDEX ; index value CALL AGOTO1 DEFW ADDR0 ; go here if A = 0 DEFW ADDR1 ; go here if A = 1 ... DEFW ADDRN ; go here if A = N Routine: AGOTO2 Function: Computed GOTO on A register Entry: A = index value (zero-relative) Exit: None Affected: None Usage: A computed GOTO based on a specified 8-bit value. No range or limit checking is done, so you must insure that the computed GOTO does not exceed the table limit. Example: LD A,INDEX ; index value CALL AGOTO2 JP ADDR0 ; return to this JP if A = 0 JP ADDR1 ; return to this JP if A = 1 ... JP ADDRN ; return to this JP if A = N [next instruction] ; return here if A = N+1 Routine: BGOTO1 Function: Computed GOTO on A register with limit check Entry: A = index value (zero-relative) B = maximum index value allowed Exit: None Affected: None Usage: A computed GOTO based on a specified 8-bit value. A second byte is passed specifying a limit value. If the test value exceeds the limit, control is transferred to after the last address in the ta ble. Example: LD A,INDEX ; index value LD B,LIMIT ; maximum index value CALL BGOTO1 DEFW ADDR0 ; go here if A = 0 DEFW ADDR1 ; go here if A = 1 ... DEFW ADDRLIMIT ; go here if A = LIMIT [next instruction] ; return here if A > LIMIT Routine: BGOTO2 Function: Computed GOTO on A register with limit check Entry: A = index value (zero-relative) B = maximum index value Exit: None Affected: None Usage: A computed GOTO based on a specified 8-bit value. A second byte is passed specifying a limit value. If the test value exceeds the limit, control is transferred to after the last address in the ta ble. Example: LD A,INDEX ; index value LD B,LIMIT ; maximum index value CALL BGOTO2 JP ADDR0 ; return to this JP if A = 0 JP ADDR1 ; return to this JP if A = 1 ... JP ADDRLIMIT ; return to this JP if A=LIMIT [next instruction] ; return here if A > LIMIT Routine: HGOTO1 Function: Computed GOTO on HL register pair Entry: HL = index value (zero-relative) Exit: None Affected: None Usage: A computed GOTO based on a specified 16-bit value. No range or limit checks are performed, so you must insure that the range of the computed GOTO is not exceeded. Example: LD HL,INDEX ; index value CALL HGOTO1 DEFW ADDR0 ; go here if HL = 0 DEFW ADDR1 ; go here if HL = 1 ... DEFW ADDRN ; go here if HL = N Routine: HGOTO2 Function: Computed GOTO on HL register pair Entry: HL = index value (zero-relative) Exit: None Affected: None Usage: A computed GOTO based on a specified 16-bit value. No range or limit checks are performed, so you must insure that the range of the computed GOTO is not exceeded. Example: LD HL,INDEX ; index value CALL HGOTO2 JP ADDR0 ; return to this JP if HL = 0 JP ADDR1 ; return to this JP if HL = 1 ... JP ADDRN ; return to this JP if HL = N [next instruction] ; return here if HL = N+1 Routine: DGOTO1 Function: Computed GOTO on HL with limit check Entry: HL = index value (zero-relative) DE = maximum index value allowed Exit: None Affected: None Usage: A computed GOTO based on a specified 16-bit value. A second 16-bit value is passed specifying the upper limit of computed values. If the specified test value exceeds the limit value, then control is transferred to after the last address in the table. Example: LD HL,INDEX ; index value LD DE,LIMIT ; maximum index value CALL DGOTO1 DEFW ADDR0 ; go here if HL = 0 DEFW ADDR1 ; go here if HL = 1 ... DEFW ADDRLIMIT ; go here if HL = LIMIT [next instruction] ; return here if HL > LIMIT Routine: DGOTO2 Function: Computed GOTO on HL with limit check Entry: HL = index value (zero-relative) DE = maximum index value Exit: None Affected: None Usage: A computed GOTO based on a specified 16-bit value. A second 16-bit value is passed specifying the upper limit of computed values. If the specified test value exceeds the limit value, then control is transferred to after the last address in the table. Example: LD HL,INDEX ; index value LD DE,LIMIT ; maximum index value CALL DGOTO2 JP ADDR0 ; return to this JP if HL = 0 JP ADDR1 ; return to this JP if HL = 1 ... JP ADDRLIMIT ; return to this JP if HL = LIMIT [next instruction] ; return here if HL > LIMIT Routine: AIF1 Function: Arithmetic IF on A register Entry: A = test value B = key value Exit: None Affected: None Usage: An arithmetic IF facility where a specified key value (in B) is compared to a specified test value (in A). Branching is done depending on the fol lowing tests: AB. Example: LD A,TEST ; test value LD B,KEY ; key value CALL AIF1 DEFW ALTB ; go here if AB Routine: AIF2 Function: Arithmetic IF on A register Entry: A = test value B = key value Exit: None Affected: None Usage: An arithmetic IF facility where a specified key value (in B) is compared to a specified test value (in A). Branching is done depending on the fol lowing tests: AB. Example: LD A,TEST ; test value LD B,KEY ; key value CALL AIF2 JP ALTB ; resume at this JP if AB Routine: HIF1 Function: Arithmetic IF on HL register pair Entry: HL = test value DE = key value Exit: None Affected: None Usage: An arithmetic IF facility where a specified key value (in DE) is compared to a specified test value (in HL). Branching is done depending on the following tests: HLDE. Example: LD HL,TEST ; test value LD DE,KEY ; key value CALL HIF1 DEFW HLTD ; go here if HLDE Routine: HIF2 Function: Arithmetic IF on HL register pair Entry: HL = test value DE = key value Exit: None Affected: None Usage: An arithmetic IF facility where a specified key value (in DE) is compared to a specified test value (in HL). Branching is done depending on the following tests: HLDE. Example: LD HL,TEST ; test value LD DE,KEY ; key value CALL HIF2 JP HLTD ; resume at this JP if HLDE PARSING AIDS: UNIX-STYLE ARGC/ARGV STRING PARSING: Routine: ARGV Function: UNIX-style ARGC/ARGV string parser Entry: HL = address of NUL-terminated string to parse DE = address of token table A <> 0 if NUL is to be placed after each token A = 0 if NUL not to be placed after each token Exit: A = 0, zero flag set (Z) if no error A <> 0, zero flag reset (NZ) if more tokens than allowed (last token pointer points to the rest of the string) Affected: AF Usage: Isolates tokens within a string for subsequent action, such as filename or argument parsing. Tokens are delimited by spaces and tabs. For example: " THIS IS FUN " contains three tokens, and ARGV will return point ers to the "T" in "THIS", the "I" in "IS", and the "F" in "FUN". If A <> 0 on input, ARGV will store binary 0's (NUL's) over the first space after the "S" in "THIS", the "S" in "IS", and the "N" in "FUN". No changes are made to the string if A = 0 on entry. ARGV is called with the address of a table struc tured as: DEFB MAXENT ; number of token pointers filled / DEFS 1 ; number of tokens found by ARGV in | DEFS 2 ; pointer to token 1 (in string) by | DEFS 2 ; pointer to token 2 (in string) ARGV | ... \ DEFS 2 ; Ptr to token MAXENT (in string) If there were more tokens in the string than al lowed in the token table, ARGV returns with A<>0 and the zero flag reset (NZ). In this case, the last token pointer points to the last token al lowed, and extends to the end of the string. The NUL is not placed after the last token, so the rest of the string appears as a single token (and may be parsed by ARGV again). CAPITALIZATION: Routine: CAPS Function: Capitalize a character Entry: A = character to capitalize Exit: A = capitalized character Affected: AF Usage: Returns the uppercase version of any lowercase ASCII character specified. Characters other than those in the set [a-z] are returned unaffected. If the character is a lowercase alphabetic charac ter, it is converted to Uppercase in the set [A..Z]. Only the lower seven bits of the byte are considered, and the most significant bit is zeroed. Routine: CAPSTR Function: Capitalize a string Entry: HL = pointer to first byte of a string Exit: None (string is capitalized) Affected: None Usage: Capitalizes a NUL-terminated string specified in the calling parameters. CHARACTER TEST ROUTINES: Character test routines check the spec ified ASCII character (after masking off the high bit) to see if it meets a specified condition. All routines conform to the same conventions. Routines: ISALNUM, ISALPHA, ISCTRL, ISDIGIT, ISGRAPH, ISHEX, ISPRINT, ISPUN, ISSP Function: Test for specific types of characters Entry: A = character to test Exit: A = character, zero flag set (Z) if condition true Zero flag reset (NZ) if condition false Affected: Flags Usage: ISALNUM tests for an alphanumeric character (A-Z, a-z, 0-9), ISALPHA tests for an alphabetic charac ter (A-Z, a-z), ISCTRL tests for a control charac ter (less than SP, or DEL), ISDIGIT tests for a digit (0-9), ISGRAPH tests for a graphic character (between SP and DEL), ISHEX tests for a hexadeci mal character (0-9, A-F, a-f), ISPRINT tests for a printable character (between SP and DEL, including SP), ISPUN tests for a punctuation character (be tween SP and DEL, incl DEL, but not 0-9, A-Z, or a-z), ISSP tests for a space character (HT, LF, VT, FF, CR, and SP) CHARACTER SKIP ROUTINES: These routines are used to skip over characters in the string specified until either a character of the type not being skipped is encountered or the end of the string (NUL character) is found. They all conform to the same parameters as: Routines: SKNPUN, SKNSP, SKPUN, SKSP Function: Skip over specific type of character Entry: HL = pointer to first character in NUL-terminated string Exit: HL = pointer to character which terminated skip Affected: HL Usage: SKNPUN skips over non-punctuation characters, SKNSP skips over non-space characters, SKPUN skips over punctuation characters, SKSP skips over space characters. Punctuation characters are those between SP and DEL which are not 0-9, A-Z, or a-z. Space characters are any of the set HT, LF, VT, FF, CR, or SP. GENERAL PURPOSE ARITHMETIC: These routines are for 16-bit un signed arithmetic. All use HL as the accumulator or the result, and HL and DE contain the operands required (if only one operand is needed, HL is used). The available routines are: ADDHD -- HL = HL + DE SUBHD -- HL = HL - DE MULHD -- HL = HL * DE DIVHD -- HL = HL / DE NEGH -- HL = 2's complement of HL CMPH -- HL = 1's complement of HL ROTLH -- HL is rotated left one bit position ROTRH -- HL is rotated right one bit position SHFTLH -- HL is shifted left one bit position SHFTRH -- HL is shifted right one bit position ANDHD -- HL = HL AND DE ORHD -- HL = HL OR DE XORHD -- HL = HL XOR DE The carry flag is frequently used to indicate overflow. Routine: ADDHD Function: 16-bit addition Entry: HL = operand 1 DE = operand 2 Exit: HL = operand 1 + operand 2 Carry set (C) if overflow, otherwise clear (NC) Affected: F, HL Usage: This routine is not really needed since a simple ADD HL,DE instruction accomplishes the same thing with only one byte instead of a 3-byte call. Routine: SUBHD Function: 16-bit subtraction Entry: HL = minuend DE = subtrahend Exit: HL = minuend - subtrahend Carry set (C) if DE > HL, otherwise clear (NC) Affected: F, HL Usage: This routine is no longer needed with Z80 proces sors since the SBC HL,DE operation accomplishes the same function without resorting to a function call. Routine: MULHD Function: 16-bit multiplication Entry: HL = operand 1 DE = operand 2 Exit: HL = operand 1 times operand 2 Carry set (C) if result is > 65535 Affected: F, HL Usage: Multiplies two numbers. It is optimized for speed, with a minor sacrifice on size, and it always takes 16 loops to perform any multiplica tion. Routine: DIVHD Function: 16-bit division Entry: HL = dividend DE = divisor Exit: HL = HL / DE Affected: HL Usage: Divides two numbers. It is optimized for speed, with a minor sacrifice on size, and always takes 16 loops to perform any division. Routine: NEGH Function: Two's complement (negate) a 16-bit number Entry: HL = 16-bit operand Exit: HL = two's complement of operand Affected: HL Usage: Returns the 2's complement of a 16-bit number. Routine: CMPH Function: One's complement a 16-bit number Entry: HL = 16-bit operand Exit: HL = one's complement of operand Affected: HL Usage: Returns the 1's complement of a 16-bit number. Routine: ANDHD Function: Logically AND two 16-bit values Entry: HL = operand 1 DE = operand 2 Exit: HL = bitwise logical AND of two operands Affected: HL Usage: Performs the specified Boolean operation on the two supplied 16-bit values, and return the result. Routine: ORHD Function: Logically OR two 16-bit values Entry: HL = operand 1 DE = operand 2 Exit: HL = bitwise logical OR of two operands Affected: HL Usage: Performs the specified Boolean operation on the two supplied 16-bit values, and return the result. Routine: XORHD Function: Logically XOR two 16-bit values Entry: HL = operand 1 DE = operand 2 Exit: HL = bitwise logical XOR of two operands (XORHD) Affected: HL Usage: Performs the specified Boolean operation on the two supplied 16-bit values, and return the result. Routines: ROTLH, ROTRH Function: ROTLH does a one bit right rotation of 16-bit value, ROTRH does a one bit left rotation of 16- bit value Entry: HL = 16-bit operand to rotate Exit: HL = rotated operand left (ROTLH) or right (ROTRH) Affected: HL Usage: Rotates the furnished 16-bit value left (ROTLH) or right (ROTRH) one bit position. These are circu lar rotates, in which the most significant bit of H is rotated into the least significant bit posi tion of L (ROTLH), and least significant bit of L is rotated into the most significant bit position of H (ROTRH). Routines: SHFTLH, SHFTRH Function: SHFTLH does a one bit right shift of 16-bit value, zero fill, SHFTRH does a one bit left shift of 16- bit value, zero fill Entry: HL = 16-bit operand to shift Exit: HL = shifted operand left (SHFTLH) or right (SHFTRH) Affected: HL Usage: Shifts the furnished 16-bit value left (SHFTLH) or right (SHFTRH) one bit position filling the cleared position with a zero. In SHFTLH, HL is shifted left one bit position with the least sig nificant bit of L filled with a zero. In SHFTRH, HL is shifted right one bit position with the most significant bit of H filled with a zero. SHFTLH is equivalent to the more efficient single byte ADD HL,HL operation and SHFTRH is equivalent to the four byte Z80 sequence: SRL H RR L CRC CALCULATION: The CRC routines may be used to check the va lidity of an incoming serial byte stream or check for validity of data copies. These routines compute and check a true 16-bit cyclic redundancy code (CRC). The use of these routines will guarantee detection of all single- bit and double-bit errors, all errors with an odd number of error bits, all burst errors of length 16 or less, 99.9969% of all 17- bit error bursts, and 99.9984% of all possible longer error bursts. CRC and CRC3 routines use the X^16 + X^12 + X^5 + 1 polynomial commonly used in floppy disk controllers and modem programs. The CRC1 routine uses the X^16 + X^15 + X^2 + 1 polynomial also used in synchronous communications. CRC2 uses the X^16 + X^15 + X^13 + X^7 + X^4 + X^2 + X + 1 polynomial found in public-domain file CRC checking programs. All four families of routines are used in the same way, except that a unique initialization routine, CRC3INIT, is required with CRC3 before any processing is performed. This is because the CRC3 update routine is table-driven compared to the others which calculate the CRC "on the fly". The added routine builds the table of pre-computed remainders. Typical use is: CRCMAKE: ; call CRC3INIT here if using CRC3 CALL CRCCLR ; clear the CRC [loop CALLing CRCUPD] ; ..acquire values CALL CRCDONE ; get the finished value LD (CRCVAL),HL ; ..and save CRCCK: ; routine to check incoming CRC CALL CRCCLR ; clear CRC [loop CALLing CRCUPD] ; ..acquire new set of values CALL CRCDONE ; get the finished value in HL LD DE,(CRCVAL) ; get the first value in DE CALL COMPHD ; compare HL to DE JR NZ,ERROR ; ..error if CRC's don't match Routines: CRCCLR, CRC1CLR, CRC2CLR, CRC3CLR Function: Clear CRC accumulator Entry: None Exit: None Affected: None Usage: Must be executed before beginning a new operation on a file, block, or sector of data. Do not call these routines before completing calculations on a block or the accumulated data will be incorrect. Routine: CRC3INIT Function: Initialize CRC3 table for use Entry: HL = pointer to 512-byte space for table Exit: None Affected: AF, BC, DE Usage: Must be executed before using the CRC3 updating routine, or incorrect results will be obtained. It initializes a table with pre-computed CRC re mainders for use by the updating routine. Routine: CRCUPD, CRC1UPD, CRC2UPD, CRC3UPD Function: Update CRC accumulator count Entry: A = byte to be included in CRC Exit: None Affected: None Usage: Called once for every byte to be included in the CRC calculation. Routines: CRCDONE, CRC1DONE, CRC2DONE, CRC3DONE Function: Return CRC value Entry: None Exit: HL = calculated CRC value Affected: HL Usage: This routine is used to terminate CRC accumulation and return the calculated 16-bit CRC value. RANDOM NUMBER GENERATION: Routine: RNDINIT Function: Initialize random number generator seed Entry: None Exit: None Affected: None Usage: Version 4 of the libraries changes this function from the keyboard/loop counter used in previous versions to one where the refresh register of the Z80/Z180 is read to form the initial seed, requir ing no user action. This method will not work on the Z280 where refresh is just another register. Routine: RNDSEED Function: Set known seed value Entry: A = 8-bit seed value Exit: None Affected: None Usage: Allows you to provide a seed value for the random number generator instead of using the automatic method in RNDINIT. Routine: RND Function: Return 8-bit pseudo-random number Entry: None Exit: A = random number Affected: AF Usage: Provides a pseudo-random byte. The returned val ues are between zero and 255. You must do any scaling needed for your application. STRING AND VALUE COMPARISON: Routines: COMPB, COMPBC Function: Compare vectors Entry: HL, DE = pointers to vectors to compare BC (for COMPBC), B (for COMPB) = number of bytes to compare Exit: zero flag set (Z): HL = DE carry flag set (C): HL < DE zero and carry reset (NZ and NC): HL > DE Affected: AF Usage: Most commonly used to do string comparison. Since all eight bits are used in the compare logic, they are also suitable for raw binary elements as well. COMPB uses only an 8-bit counter (B register) and can compare one to 256 bytes, while COMPBC uses a 16-bit counter (BC pair) and can compare one to 65,536 bytes. The maximum counts of 256 and 65536 are achieved by setting the counter registers to zero. Routine: @FNCMP Function: Unambiguous 7-bit filename comparison Entry: HL = pointer to first string to match DE = pointer to second string to match B = number of characters to check (0 checks 256) Exit: zero flag set (Z) if strings match zero flag reset (NZ) if no match carry flag set (C) if (DE) is less than (HL) Affected: AF, BC, DE, HL Usage: Most often used to compare filenames and file types. It performs 7-bit comparisons, ignoring any attribute bits (bit 7). In general use, it compares two strings of one to 256 characters in length. In addition to equality, the inequalities of greater than and less than are also supported by also sensing the carry flag. Routine: @AFNCMP Function: Perform ambiguous 7-bit filename comparison Entry: HL = pointer to possibly ambiguous string DE = pointer to second string to match B = number of characters to check (0 checks 256) Exit: zero flag set (Z) if match zero flag reset (NZ) if no match Affected: AF, BC, DE, HL Usage: Most often used to compare filenames and file types, where one name may be ambiguous (question marks, "?", match any character). High bits (bit 7) of both strings are masked with only the least significant bits being compared. It may also be used as a general 7-bit utility compare strings of one to 256 characters in length. Examples: EXT @AFNCMP,@FNCMP ; declare the routines ... ; ..preceeding code LD HL,AMBIG ; set ptr to ambiguous name LD DE,FNAME ; set to name to check LD B,11 ; match filename and type only CALL @AFNCMP ; ..call the routine JR Z,OK ; jump if match ... ; else here if mismatch ... LD HL,ENTRY1 ; set ptr to first name LD DE,ENTRY2 ; ..and name to check LD B,11 ; mMatch filename and type only CALL @FNCMP ; ..call the routine JR Z,EQUAL ; jump if same JR C,ONEMORE ; ..jump here if ENTRY1>ENTRY2 ... ; else here if ENTRY1 < ENTRY2 Routine: COMPHD Function: 16-bit value comparision Entry: HL, DE = values to compare Exit: Zero flag set (Z): HL = DE Carry flag set (C): HL < DE Carry and zero reset (NZ and NC): HL > DE Affected: AF Usage: Commonly used to compare two 16-bit values such as addresses or integer values. Routine: INSTR Function: Substring search (NUL-terminated character strings) Entry: HL = pointer to NUL-terminated string to be scanned DE = pointer to NUL-terminated substring to locate Exit: HL = pointer to beginning of substring in string if found (unaffected if not found) A = 0, zero flag set (Z) if found A <> 0, zero flag clear if not found Affected: AF, HL Usage: Most often used to locate a character string with in a larger body of text, such as within a simple text editor. Automatic success if substring is of zero-length (null string). Routine: SCANNER Function: Vector search Entry: HL = pointer to vector to be scanned DE = pointer to vector to locate BC = vector lengths: B = number of bytes in HL-vector C = number of bytes in DE-vector Exit: HL = pointer to located vector (unchanged if not found) Zero flag set (Z) if found (A indeterminate) A <> 0, zero flag reset (NZ) if not found Affected: AF, HL Usage: Locates a string of bytes in a block of up to 255 bytes. Since only 8-bits are available for length values for both the search and target vectors, neither length can exceed 256. Because of the logic used, the block to be scanned must be of non-zero length to avoid an error for search lengths less than 256 (0 length byte). Automatic failure if scanned vector is shorter than vector to locate (B < C). MEMORY ALLOCATION: The concept of memory allocation with these routines is relatively simple; SYSLIB routines provide primative memory allocation/de-allocation capabilities, but you stay in control. The basic idea is to reserve a buffer in memory from which to take bits and pieces from at a time. The bounding addresses of this buffer are specified (or set by default) by the IALLOC rou tine, and the ALLOC routine is used to obtain subbuffers from this larger buffer when needed. ALLOC constantly checks to see if the buffer has enough space left to grant the request for a subbuffer, and if it does, the subbuffer is provided. The largest buffer which may be reserved by the IALLOC routine is that buffer which extends from the end of the program to just below the CCP. This buffer is selected if IALLOC is called with A=0. The following illustrates use of the largest buffer possible: XOR A ; select full buffer CALL IALLOC ... LD DE,1024 ; request 1K CALL ALLOC JR Z,MEMOVFL ; abort if memory overflow LD (BUF1),HL ; set pointer to 1st subbuffer ... LD DE,36 ; request 36 bytes CALL ALLOC JR Z,MEMOVFL ; abort if memory overflow LD (BUF2),HL ; set pointer to 2nd subbuffer ... This memory allocation scheme also permits the division of memory into a group of buffers. One buffer may be allocated, its ad dress preserved, another buffer may be allocated, its address preserved, and then subsequent calls to IALLOC may be used to select one buffer or the other. Each call to IALLOC frees the entire buffer area, so care should be taken in doing this. For example: ... CALL CODEND ; use CODEND as first buffer LD (BUF1),HL EX DE,HL ; address in DE LD HL,1024 ; 1K for this buffer ADD HL,DE ; HL pts to after this buffer EX DE,HL ; HL is start, DE is end LD A,3 ; select start and end CALL IALLOC ... ... CALL ALLOC ; calls to ALLOC ... LD HL,(BUF1) ; pt to 1st buffer LD DE,1024 ; set 2nd buffer ADD HL,DE ; pt to 2nd buffer LD (BUF2),HL EX DE,HL ADD HL,DE ; pt to end of 2nd 1K buffer EX DE,HL ; HL is start, DE is end LD A,3 ; select start and end CALL IALLOC ... CALL ALLOC ; calls to ALLOC ... Routine: ALLOC Function: Allocate a block of memory Entry: DE = number of bytes requested Exit: HL = address of first byte allocated A <> 0, zero flag reset (NZ) if request granted A = 0, zero flag set (Z) if not enough space Affected: AF, HL Usage: Allocates a block of memory from the larger block reserved by IALLOC. Block sizes may be as small as one byte, or as large as the entire buffer. If the memory request is granted, the starting ad dress is returned. A call to IALLOC must be made before calling ALLOC. Routine: IALLOC Function: Initialize memory allocation buffer Entry: HL = possible starting address of buffer DE = possible ending address of buffer A = selection code: b0 - 1 = use HL as starting address 0 = use CODEND value b1 - 1 = use DE as ending address 0 = use CCP-1 Exit: None Affected: None Usage: Initializes the buffer from which memory is allo cated via calls to ALLOC. You may specify the bounds of this buffer, or use default bounds set by IALLOC. Routine: GETMTOP Function: Return the highest TPA byte below the CCP Entry: None Exit: HL = address of the highest byte below CCP Affected: HL, AF Usage: Determines the top of available memory in routines which exit back to the command processor with a simple return instruction instead of a warm boot. This routine returns the highest available memory location beneath the command processor to avoid overwriting it. If you are writing for a ZCPR3 environment, use the corresponding GZMTOP routine in Z3LIB. SORT ROUTINES: Two routines are provided which give you access to a very flexible sorting system. The main routine is SORT, providing a utility which sorts in-memory a set of fixed-length records. The sorting technique used is a Shell sort, adapted from the book "Software Tools" by Kernigan and Plaugher, pub lished by Addison-Wesley, 1976, page 106. This sort is much faster than the simple bubble sort. A Shell sort can be done in two ways: with or without using pointers. Sorting without using pointers is typically slower than sorting with pointers, and the only advantage to not using pointers is the space savings from not having pointers (2 * num ber of entries bytes). If pointers are used for the sort, then whenever an exchange is done, the pointers are simply exchanged, rather than the full records, thereby decreasing sort time in most casts. The SORT routine is controlled by passing a pointer to a Sort Specification Block (SSB). This Sort Specification Block is a series of 2-byte words organized as follows: Bytes 0 & 1 = starting address of 1st record Bytes 2 & 3 = number of records to sort Bytes 4 & 5 = size of each record (in bytes) Bytes 6 & 7 = address of user-supplied compare routine, which compares two records, one pointed to by HL and the other pointed to by DE. If the record pointed to by DE is less in sorting order than that pointed to by HL, this com pare routine is to return with carry set (C). If the records are equal in sorting order, this compare routine is to return with zero set (Z). Only the AF is to be affected by the compare routine. Bytes 8 & 9 = address of pointer table Byte 10 = flag (0FFh means to use pointers, 0 means not) Byte 11 = unused As mentioned previously, two routines are available in this sort module. The first routine, SSBINIT, looks at the beginning of a scratch area and the initial contents of an SSB and allocates space for the pointer table. It also checks to see if the buffer required overflows the transient program area. The second routine, SORT, performs the sort, and is controlled by the SSB pointer passed to it in DE. Routine: SSBINIT Function: Sort Specification Block initializer Entry: HL = pointer to start of scratch RAM area DE = pointer to SSB Exit: A <> 0, zero flag reset (NZ) if OK A = 0, zero flag set (Z) if TPA overflow Affected: AF Usage: This routine may be used as described above before any records are loaded into memory for the sort, or it may be used after the records have already been loaded. In the latter case, you should save the start address of the first record and call SSBINIT with the address of the first byte after the last record. Once SSBINIT has loaded the buffers in the SSB and checked for a TPA overflow (note that this is done for the pointers only), it will return to the caller, at which time you should restore the first two bytes of the SSB to their proper values, the actual start address of the first record. SSBINIT loads bytes 0 & 1 (address of first rec ord) and 8 & 9 (address of pointer table) of an SSB, checking for TPA overflow. It sets the poin ter table to start at the specified scratch RAM area, examines the record size and record count entries of an SSB, and adds the product of these two to the starting address of the pointer table. The resulting address is returned as the address of the first record. Routine: SORT Function: Sort set of fixed length records Entry: DE = pointer to sort specification block (SSB) Exit: None (records are sorted) Affected: None Usage: Sorts the set of fixed length records according to the control information in the Sort Specification Block (SSB) addressed by DE. No special action is required, nor possible in its operation. In the unlikely event of an error within the SORT rou tine, the error message "SORT Pointer Error" may be printed. This indicates a flaw has developed with the SORT routine and it could not SORT the set of records as desired. This is fatal and will abort to CP/M. MISCELLANEOUS ROUTINES: The following routines are described in this section: BDOS -- direct BDOS interface BIOS -- direct BIOS interface CAPS -- character capitalization CAPSTR -- string capitalization CATH -- convert ASCII character to hexadecimal @B2HH,@B2HL -- convert high and low nybbles of byte to hex CLINE -- command line extraction CODEND -- provide end of code/data area EN -- exchange nybbles in A FILLB -- fill memory (up to 255 bytes) FILLBC -- fill memory (up to 65,535 bytes) HFILB -- fill memory (up to 255 bytes) HFILBC -- fill memory (up to 65,535 bytes) MOVEB -- move memory (up to 255 bytes) MOVEBC -- move memory (up to 65,535 bytes) HMOVB -- move memory (up to 255 bytes) HMOVBC -- move memory (up to 65,535 bytes) PAUSE -- delay n 10ths of a second VERSION -- return version number of SYSLIB Routine: BDOS Function: Call a BDOS function Entry: DE = arguments (if needed for function) C = BDOS function number Exit: A = return status or parameter (if returned) HL = return parameter (if returned) Affected: AF, HL Usage: A way of calling the BDOS while preserving the BC and DE registers. This is often of benefit when dealing with FCB addresses in DE and/or loop coun ters in the B register. Routine: BIOS Function: Call a BIOS function directly Entry: A = offset to BIOS function entry in jump table BC = function parameters (if needed) Exit: A, BC = return parameters (if returned) Affected: AF, BC, DE, HL Usage: Provides very fast response where BDOS overhead cannot be tolerated. This routine provides you with a direct interface into the CP/M BIOS. It is called with an index offset into the BIOS jump table. No registers are preserved by this rou tine. The following table summarizes the offsets of the BIOS jump table entries: 0 Cold start 1 Warm boot 2 Console status; returns A=0FFh if char acter ready, A=0 if not 3 Console input; returns character in A 4 Console output; character passed in C 5 List output; character passed in C 6 Punch output; character passed in C 7 Reader input; returns character in A 8 Home disk head 9 Select disk; disk number (A=0, etc.) passed in C 10 Set track number; track number passed in C 11 Set sector number; sector number passed in C 12 Set DMA address; DMA address passed in BC 13 Read block from disk; returns A=0 if OK, A=1 if error 14 Write block to disk; returns A=0 if OK, A=1 if error 15 List status; returns A=0FFh if ready, A=0 if not 16 Sector translation, logical-to-physical; logical sector number passed in BC, translate table address in DE; returns physical sector number in HL Routine: CATH Function: Convert ASCII to hexadecimal Entry: A = ASCII hex character ("0"-"9", "A"-"F") Exit: A = binary value represented by character Affected: AF Usage: Useful in numeric conversion and entry routines. It simply converts the ASCII hexadecimal character provided to its binary representation. If an invalid hex character is passed, a space (20h) is returned in A. Routines: @B2HH, @B2HL Function: Convert binary to hexadecimal Entry: A = data byte to convert Exit: A = hex character (0..9, A..F) for specified nybble Affected: AF Usage: Performs conversions from binary nybbles to hexa decimal ASCII characters. @B2HH converts high nybble of byte to hex digit, while @B2HL convert low nybble of byte to hex digit. Example: EXT @B2HH,@B2HL ... ; enter with byte in A PUSH AF ; save the byte CALL @B2HH ; call the routine ... ; do something with high nybble POP AF ; restore original byte CALL @B2HL ; now have hex char of low nybble ... ; do something with it Routine: CLINE Function: Command line tail extraction Entry: HL = address of command line buffer (character count) Exit: HL = address of command line string (1st character) A <> 0, zero flag clear (NZ) if buffer OK A = 0, zero flag set (Z) if buffer truncated Affected: AF, HL Usage: Frees the default buffer at 80h by copying the contents to a local buffer. The preserved copy may then be parsed or evaluated at a later time. The line may be up to 255 characters long and will be truncated if longer. The string will be termi nated by a as per the SYSLIB concept of strings. Routine: CODEND Function: End of code Entry: None Exit: HL = address of page above last byte used in program Affected: HL Usage: Used to determine the base address of free memory for use in sorting, directory listing, and other programs. Scratch memory extends from the value returned by CODEND to the base of the CCP or BDOS. Global: $MEMRY -- Contains the address of the next avail able byte of memory after the last module loaded and resolved by MicroSoft's LINK-80 linker, SLR Systems' SLRNK, or Mitek's ZLINK. This reserved global variable should be accessed as: ... EXT $MEMRY ... LD HL,($MEMRY) ; get value ... Routine: EN Function: Exchange nybbles Entry: A = byte to manipulate Exit: A = manipulated Byte Affected: AF Usage: Exchanges the nybbles in the A register; high- order four bits are exchanged with low-order four bits. Routines: FILLB, FILLBC, HFILB, HFILBC Function: Memory fill routines Entry: HL = pointer to first byte of memory area to fill BC (FILLBC and HFILBC) = number of bytes to fill B (FILLB and HFILB) = number of bytes to fill A = value to store in buffer Exit: HL (HFILB and HFILBC only) = pointer to byte after last Affected: HL (HFILB and HFILBC only) Usage: Fills an area of memory with a constant byte val ue. FILLB can fill up to a 256-byte buffer, and FILLBC can fill up to a 65,536-byte (within rea son) buffer. FILLB and FILLBC have no effects on any registers. HFILB and HFILBC both affect the HL register pair, and they return with HL pointing to the byte after the last byte filled. HFILB and HFILBC are useful when further processing from the last point filled is desired. Routines: MOVEB, MOVEBC, HMOVB, HMOVBC Function: Memory move routines Entry: HL = pointer to first byte of source buffer DE = pointer to first byte of destination buffer BC (MOVEBC & HMOVBC) = number of bytes to move B (MOVEB & HMOVB) = number of bytes to move Exit: HL (HMOVB & HMOVBC) = pointer to byte after last source DE (HMOVB & HMOVBC) = pointer to byte after last destination Affected: HL, DE (HMOVB & HMOVBC only) Usage: Moves the block of memory specified by the source address to the specified destination memory loca tion. MOVEB can move up to a 256-byte buffer, and MOVEBC can move up to a 65,536-byte buffer. MOVEB and MOVEBC have no effects on any registers. HMOVB and HMOVBC both affect the HL register pair, and they return with HL and DE pointing to the byte after the last byte moved. HMOVB and HMOVBC are useful when further processing from the last point filled is desired. Routine: PAUSE Function: Delay routine Entry: HL = number of 10ths of a second delay desired B = processor speed in MHz (1, 2, 3, ...) Exit: None Affected: None Usage: For delays from one to 65,536 tenths of a second. Calculations are approximate and depend on accura cy on clock specification and number of clock cycles per opcode in the delay code. (i.e., the Z180/64180 execute in fewer clock cycles than the Z80). Routine: VERSION Function: Version number of SYSLIB Entry: None Exit: HL = version (H=major, L=minor); H=4, L=2 for 4.2 Affected: HL Usage: Returns the library version and identification text string.