diff --git a/.github/workflows/commit.yml b/.github/workflows/commit.yml index 2110be86..33eaad76 100644 --- a/.github/workflows/commit.yml +++ b/.github/workflows/commit.yml @@ -26,7 +26,8 @@ jobs: run: | export TZ='America/Los_Angeles' sudo apt-get install srecord - make distlog + make transpile-c-code + make distlog --trace rm -rf .git* - name: List Output diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 877aa34b..e418df06 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,8 @@ jobs: export TZ='America/Los_Angeles' sudo apt-get install libncurses-dev sudo apt-get install srecord - make distlog + make transpile-c-code + make distlog --trace rm -rf .git* - name: Create Package Archive @@ -52,6 +53,21 @@ jobs: title: "${{env.TITLE}} ${{github.ref_name}}" files: | RomWBW-${{github.ref_name}}-Package.zip + + - name: Build Docs + run: | + export TZ='America/Los_Angeles' + sudo apt-get install gpp pandoc + pip install mkdocs + make -C Source/Doc deploy_mkdocs + mkdocs build -f Source/Doc/mkdocs.yml + + - name: Deploy Docs + uses: peaceiris/actions-gh-pages@v4 +# if: github.ref == 'refs/heads/master' + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: Source/Doc/site # - name: Upload Package Archive # uses: AButler/upload-release-assets@v2.0.2 diff --git a/.gitignore b/.gitignore index af06bcf5..6c116cc0 100644 --- a/.gitignore +++ b/.gitignore @@ -114,20 +114,24 @@ Source/ZPM3/genbnk.dat Source/ZSDOS/zsdos.err # Lets explicit list all generate untracked binary files +Binary/*.upd +Binary/Apps/bbcbasic.txt +Binary/Apps/copysl.doc +Binary/Apps/copysl.doc +Binary/Apps/fdu.doc +Binary/Apps/fdu.doc Binary/Apps/Tunes/bgm.vgm Binary/Apps/Tunes/ending.vgm Binary/Apps/Tunes/inchina.vgm Binary/Apps/Tunes/shirakaw.vgm Binary/Apps/Tunes/startdem.vgm Binary/Apps/Tunes/wonder01.vgm -Binary/Apps/copysl.doc -Binary/Apps/fdu.doc Binary/Apps/zmconfig.ovr Binary/Apps/zminit.ovr -Binary/Apps/zmp.doc -Binary/Apps/zmp.hlp Binary/Apps/zmp.cfg +Binary/Apps/zmp.doc Binary/Apps/zmp.fon +Binary/Apps/zmp.hlp Binary/Apps/zmterm.ovr Binary/Apps/zmxfer.ovr Binary/CPM3/bdos3.spr @@ -146,13 +150,12 @@ Binary/CPNET/cpn12ser.lbr Binary/CPNET/cpn3duo.lbr Binary/CPNET/cpn3mt.lbr Binary/CPNET/cpn3ser.lbr -Binary/*.upd +Binary/hd1k_prefix.dat Binary/ZPM3/bnkbdos3.spr Binary/ZPM3/bnkbios3.spr Binary/ZPM3/gencpm.dat Binary/ZPM3/resbdos3.spr Binary/ZPM3/zinstal.zpm -Binary/hd1k_prefix.dat Source/BPBIOS/def-ww.lib Source/CPNET/cpn12duo.lbr Source/CPNET/cpn12mt.lbr @@ -169,6 +172,9 @@ Source/Fonts/font8x16u.asm Source/Fonts/font8x8c.asm Source/Fonts/font8x8c.bin Source/Fonts/font8x8u.asm +Source/Fonts/font6x8c.asm +Source/Fonts/font6x8c.bin +Source/Fonts/font6x8u.asm Source/Fonts/fontcgac.asm Source/Fonts/fontcgac.bin Source/Fonts/fontcgau.asm @@ -177,6 +183,8 @@ Source/Fonts/fontvgarcc.bin Source/Fonts/fontvgarcu.asm Source/HBIOS/*.upd Source/HBIOS/build_env.cmd +Source/HBIOS/build_env.cmd +Source/HBIOS/hbios_env.sh Source/HBIOS/hbios_env.sh Source/HBIOS/netboot.mod Source/Images/*.cat @@ -194,4 +202,3 @@ Source/ZPM3/setz3.com Tools/unix/OpenSpin/build/ Tools/unix/zxcc/config.h Tools/unix/zxcc/zxcc -Binary/Apps/bbcbasic.txt diff --git a/.vscode/settings.json b/.vscode/settings.json index 7c12e6b0..45145d9e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,38 @@ { + "z80-macroasm.format.enabled": true, + "z80-macroasm.format.baseIndent": 1, + "z80-macroasm.format.whitespaceAfterInstruction": "tab", + "z80-macroasm.format.uppercaseKeywords": true, + "z80-macroasm.format.spaceAfterArgument": true, + "z80-macroasm.format.hexaNumberStyle": "motorola", + "z80-macroasm.format.hexaNumberCase": true, "files.trimTrailingWhitespace": false, - "files.eol": "\r\n" + "files.eol": "\r\n", + "files.associations": { + "*.inc": "z80-macroasm", + "*.asm": "z80-macroasm", + "*.180": "z80-macroasm", + "*.asm.m4": "z80-macroasm", + "*.inc.m4": "z80-macroasm", + "*.mac": "z80-macroasm", + "*.asmpp": "z80-macroasm", + "*.zdsproj": "xml", + "*.Z80": "z80-macroasm", + "ch376.h": "c", + "protocol.h": "c", + "usb_state.h": "c", + "functional": "c", + "class_scsi.h": "c", + "z80.h": "c", + "dev_transfers.h": "c", + "usb-base-drv.h": "c", + "critical-section.h": "c", + "enumerate.h": "c", + "ch376inc.h": "c", + "enumerate_storage.h": "c", + "work-area.h": "c", + "hbios-driver-storage.h": "c", + "class_hid_keyboard.h": "c", + "print.h": "c" + } } diff --git a/Doc/CPM/BPBIOS/BPBIOS_1_Introduction.md b/Doc/CPM/BPBIOS/BPBIOS_1_Introduction.md new file mode 100644 index 00000000..611ffe0f --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_1_Introduction.md @@ -0,0 +1,81 @@ +# B/P Bios +# Banked and Portable Basic IO System + +# 1 Introduction + +The Banked and Portable (B/P) Basic I/O System (BIOS) is an effort to standardize many of the logical to physical mapping mechanisms on Microcomputers running Z-Systems with ZSDOS. In expanding the capabilities of such systems, it became apparent that standard BIOSes do not contain the functionality necessary, adequate standardization in extended BIOS calls, nor an internal structure to fully support external determination of system parameters. B/P Bios provides a method of achieving these goals, while also possessing the flexibility to operate on a wide range of hardware systems with a much smaller level of systems programming than previously required. + + +## 1.1 About This Manual + +Documentation on B/P Bios consists of this manual plus the latest addendum on the distribution disk in the file README.2ND. This manual is divided into the following sections: + +* The Features of B/P Bios summarizes the significant features of B/P Bios in general, highlighting advantages and the few limitations in the system. + +* Tailoring B/P Bios contains details on altering the many options to generate a customized `.REL` file tailored to your system. + +* Installing a B/P Bios details the installation of B/P Bios in both Unbanked and Banked configurations in a "how to" fashion. + +* Programming for B/P Bios describes the interfaces, data structures and recommended programming practices to insure the maximum benefit and performance from systems with B/P Bios. + +* The B/P Bios Utilities describes the purpose, operation, and customization of all supplied B/P Bios utilities and support routines. + +* Appendices which summarize various technical information. + +* A glossary defining many technical terms used in this Manual. + +* An index of key words and phrases used in this Manual. + +For those not interested in the technical details, or who want to bring the system up with a pre-configured version as quickly as possible, Section 4, Installing a B/P Bios, will lead you through the installation steps needed to perform the final tailoring to your specific computer. Other chapters cover details of the individual software modules comprising the B/P Bios, and specifics on the utilities provided to ease you use of this product. + + +## 1.2 Notational Conventions + +Various shorthand terms and notations are used throughout this manual. Terms are listed in the Glossary at the end of this manual. + +Though the symbols seem cryptic at first, they are a consistent way of briefly summarizing program syntax. Once you learn to read them you can tell at a glance how to enter even the most complicated commands. + +Several special symbols are used in program syntax descriptions. By convention, square brackets (\[\]) indicate optional command line items. You may or may not include items shown between brackets in your command, but if you do not, programs usually substitute a default value of their own. If items between brackets are used in a command, all other items between the brackets must also be used, unless these items are themselves bracketed. + +All of the support utilities developed to support the B/P Bios system contain built-in help screens which use the above conventions to display helpful syntax summaries. Help is always invoked by following the command with two slashes (`//`). So for example, + +`ZXD //` + +invokes help for ZXD, the ZSDOS extended directory program. Interactive ZSDOS programs such as BPCNFG2 also contain more detailed help messages which appear as a session progresses. + +Many utilities may be invoked from the command line with options which command the programs to behave in slightly different ways. By convention, options are given after other command parameters. For example, the `P` option in the command + +`ZXD *.* P` + +causes the ZXD directory utility to list all files (*.*) and send its output to the printer (P). For convenience, a single slash character (/) can often be used in place of leading parameters to signify that the rest of the command line consists of option characters. Therefore, the command + +`ZXD /P` + +is identical in meaning to the previous example (see 6.23 for more on ZXD). + + +## 1.3 What is B/P Bios? + +B/P Bios is a set of software subroutines which directly control the chips and other hardware in your computer and present a standard software interface to the Operating System such as our ZSDOS/ZDDOS, Echelon's ZRDOS, or even Digital Research's CP/M 2.2. These routines comply with the CP/M 2.2 standards for a Basic IO System (BIOS) with many extensions; some based on CP/M 3.x (aka CP/M Plus), and others developed to provide necessary capabilities of modern software. When properly coded, the modules comprising a B/P Bios perform with all the standard support utilities, nearly all Z-System utilities, and most application programs without alteration. + +The ability to operate Banked, Non-banked and Boot System versions of the Bios with a single suite of software, across a number of different hardware machines, plus the maximization of Transient Program Area for application programs in banked systems are features which are offered by no other system of which we are aware. + + +## 1.4 The History of B/P Bios + +Our earlier work developing ZSDOS convinced us that we needed to attack the machine-dependent software in Z80-compatible computers and develop some standard enhancements in order to exercise the full potential of our machines. This premise is even more true today with large Hard Disks (over 100 Megabytes) being very common, needs for large RAM Drives, and an ever shrinking Transient Program Area. Attempts to gain flexibility with normal operating systems were constrained by the 64k addressable memory range in Z80-compatible systems, and forced frequent operating system changes exemplified by NZCOM and NZBLITZ where different operating configurations could be quickly changed to accommodate application program needs. + +In the mid to late 1980's, several efforts had been made to bank portions of CP/M 2.2 "type" systems. XBIOS was a banked Bios for only the HD64180-based MicroMint SB-180 family. While it displayed an excellent and flexible interface and the ability to operate with a variety of peripherals, it had several quirks and noticeably degraded the computer performance. A banked Bios was also produced for the XLM-180 single board S-100 computer, but required special versions of many Z-System utilities, and was not produced in any significant quantity. Other spinoffs, such as the Epson portable, attempted banking of the Bios, but most failed to achieve our comprehensive goals of compatibility with the existing software base, high performance, and portability. + +In 1989, Cam developed the first prototype of B/P Bios in a Non-banked mode on his TeleTek while Hal concentrated on extending ZSDOS and the Command Processor. As of 1997, B/P Bios has been installed on: + +| Computer | Features | +| :--- | :--- | +| YASBEC | Z180 CPU, FD1772 FDC, DP8490 SCSI, 1MB RAM | +| Ampro LB w/MDISK | Z80 CPU, FD1770 FDC, MDISK 1MB RAM | +| MicroMint SB-180 | HD64180 CPU, SMS9266 FDC, 256KB RAM | +| MicroMint SB180FX | HD64180Z CPU, SMS9266 FDC, 512KB RAM | +| Compu/Time S-100 | Z80 CPU, FD1795 FDC, 1 MB RAM | +| Teletek | Z80 CPU, NEC765 FDC, 64KB RAM | +| D-X Designs P112 | Z182 CPU, SMC FDC37C665 FDC, Flash ROM, 512KB RAM (mods for 5380 SCSI and GIDE) | + diff --git a/Doc/CPM/BPBIOS/BPBIOS_2_Features.md b/Doc/CPM/BPBIOS/BPBIOS_2_Features.md new file mode 100644 index 00000000..308b3f3f --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_2_Features.md @@ -0,0 +1,36 @@ +# 2 Features of B/P Bios + +B/P BIOS is designed to be completely compatible with the CP/M 2.2 standards for a Basic IO System, as well as to provide many extensions needed for banked memory which is becoming so prevalent with newer systems and processors. Additionally, strict coding standards used in the various modules forming the BIOS ease interface problems with applications programs and provide a more robust framework for future development. The extensions added to the basic CP/M 2.2 foundation include many elements from Digital Research's CP/M 3 (aka CP/M Plus), but in a more logically consistent manner. Also included in banked versions are provisions for managing up to 8 MB of extended memory for banked applications, RAM Drives and potentially multitasking in future versions. To provide insight into the methodology used, let us now examine some of the features in a generic B/P Bios. + + +## 2.1 Character IO + +As defined by Digital Research in their CP/M 2.2 standards, character IO consisted of logical devices referred to as TTY, CRT, UC1, CON, etc. B/P Bios extends and generalizes these interfaces using the IOBYTE to define four physical devices called COM1, COM2, PIO and NUL. The first two, COM1 and COM2, are serial ports; PIO is a Parallel port, while NUL is a "bit-bucket" which can be replaced by a customized driver, or used in lieu of an actual device. Digital Research provided only a limited interface capability to the character devices in CP/M 2.2, consisting of a Console (CON), an auxiliary Input and Output (RDR/PUN), and a Printer (LST). The ability to sense Input and Output Status with these devices was extremely limited and was enhanced in CP/M 3. These enhanced capabilities are completely incorporated into B/P Bios with the addition of strict register usage so that only relevant registers may be altered in the respective routines. By manipulating the IOBYTE, any of the four physical devices may be used in the three logical devices of CONsole, AUXiliary, and Printer (LST). + +Also featured in B/P Bios are modifications of CP/M 3 functions to initialize (or re-initialize) all devices and parameters, and return the address of a table which contains names and parameters of the defined character devices. While not totally compatible with CP/M 3 equivalents, these functions are consistent with the spirit and functionality needed with this advanced system. Included in the device table are; flags defining whether the device is capable of Input, Output or Both, Data rates for serial devices (Maximum and Set), Serial data format where applicable, and Handshaking method (CTS/RTS, XON/XOFF or None), as well as Input and Output Data masks for stripping unneeded bits from characters during IO. + + +## 2.2 Mass Storage IO + +All versions of Digital Research's CP/M BIOSes define only a generic Disk driver with implementations of Floppy, Hard, RAM and Tape drives left to the user or developer. In B/P Bios, we went several steps further to ease many problems. First, we retained all standard CP/M 2.2 functions and parameters, added CP/M 3 features for returning the Disk Parameter Header (DPH) table address, and flushing of the software deblocking code segment, and added a new vector to the BIOS jump table to provide a standard method of directly addressing low-level device functions. Several standard low-level Floppy Disk functions are supported and used by the standard utilities, including a function to return the type of Disk Controller in use which permits a single support utility to adapt to a wide variety of hardware platforms. In a like manner, low-level functions are provided for SCSI/SASI Hard Disk drives, and provisions for RAM Disk drives in the event special hardware is implemented. The methods used to implement these access mechanisms may be logically extended to handle Tape Drives or Network Interfaces. + + +## 2.3 Clock Support for Time and Date + +Many Hardware vendors have added provisions for Time and Date as non-standard extensions to CP/M 2.2 BIOSes, and more have incorporated such support into CP/M 3 BIOSes. We opted to define the CP/M 3 clock vector as a ZSDOS-standard clock building on our previous Operating System work. This entry point into the Bios completely complies with our ZSDOS standards and can completely replace the separate clock driver when used with ZSDOS. For systems capable of returning tenths-of-seconds, such as the YASBEC and SB-180, the standard has been enhanced to support this capability as well. + + +## 2.4 Banked Memory Support + +While Digital Research added banked memory support to their CP/M 3, it was in a manner incompatible with Bios interface standards defined for earlier CP/M standards. The method used in B/P Bios is compliant with CP/M 2.2 in direct accessing of Bios functions with only one minor exception when using the Banked ZSDOS2, and contains many of the CP/M 3 extensions added for banked memory support, with some being modified to be consistent with standards adopted for Z-System software. The exception to CP/M 2.2 accesses occurs when the Operating System can access certain buffers in the System Memory Bank. With ZSDOS 2, Allocation Bit Buffers (ALV), Check Buffers (CSV), and the Disk Host Buffer are all contained in the System Bank and not directly accessible from Transient Programs. To compensate for this, we have added a command to ZSDOS 2 to return the free space on disks (the most common reason for accessing these buffers) and tailored several utilities to adapt to banked and non-banked systems. + +In addition to the primitives initiated by Digital Research, we added functions to directly access Words and Bytes in extended banks of memory, Directly accessing software routines contained in alternate memory banks, and properly managing the system when errors occur. These features make B/P Bios much more robust and resilient than other products. These features are implemented by methods transparent to the system utilities so that the same functions are available in both banked and non-banked versions. + + +## 2.5 Other Features + +B/P Bios contains a standardized identification method which may be used to determine the hardware on which the software is operating. This allows applications to "adapt" to the environment in a manner similar to that used in the rest of the Z-System community. It also minimizes system "crashes" by executing programs which assume certain hardware features which may be detrimental if executed on other systems. The effects of identification of physical system parameters is most readily noticed by virtue of a single suite of support programs performing low-level functions such as formatting and diagnostics which function across widely differing hardware platforms. Portability on this scale can rarely be seen in other computer systems. + +The ZCPR 3.4 Environment with extensions is mandatory in a B/P Bios system. Beginning with the addition of System Segment address and size information for CPR, DOS and BIOS which were added in the ZCPR 3.4 Environment, B/P Bios also adds a Resident User Space which may be used to locate unique routines for custom applications in a manner similar to, but more consistent than NZ-COM. An Environment Version number of 90H identifies the Z3 Environment as being compliant with B/P definitions. + +In Banked systems, application programs may also be placed in alternate memory banks using location and sizing information contained at standard positions within the Bios Header Structure. This feature permits significantly greater functionality without sacrificing precious Transient Program Area. While the scheme employed in the initial distribution is subject to minor adjustments as the banked ZSDOS2 becomes more firmly developed, experimentation and suggestions into this realm are encouraged. diff --git a/Doc/CPM/BPBIOS/BPBIOS_3_Tailoring.md b/Doc/CPM/BPBIOS/BPBIOS_3_Tailoring.md new file mode 100644 index 00000000..af1bb0f7 --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_3_Tailoring.md @@ -0,0 +1,232 @@ +# 3 Tailoring a B/P Bios + +To customize a B/P Bios for your use, or adapt it to a new hardware set, you will need an editor and an assembler capable of producing standard Microsoft Relocatable files. Systems using the Hitachi HD64180 or Zilog Z180 must be assembled with either ZMAC or SLR180 which recognize the extended mnemonic set, or with a Z80 assembler and MACRO file which permits assembly of the extended instructions. For Z80 and compatible processors, suitable assemblers include ZMAC and Z80ASM. For any assembler, failure to produce standard Microsoft Relocatable code will preclude the ability of our Standard utilities to properly install B/P Bios systems. + + +## 3.1 Theory of Operation + +In order to understand the need for, and principles behind B/P Bios, you must understand the way in which CP/M 2.2, as modified by the Z-System, uses the available memory address space of a Z80 microprocessor. For standard versions of CP/M and compatible systems, the only absolute memory addresses are contained in the Base Page which is the range of 0 to 100H. All addresses above this point are variable (within certain limits). User programs are normally run from the Transient Program Area (TPA) which is the remaining space after all Operating System components have been allocated. The following depicts the assigned areas pictorially along with some common elements assigned to each memory area: + +```generic +FFFFH /------------------\ + | Z-System Buffers | ENV, TCAP, IOP, FCP, RCP + |------------------| + | Bios | Code + ALV, CSV, Sector Buffers + |------------------| + | Operating System | CP/M 2.2, ZRDOS, ZSDOS1 + |------------------| + | Command Processor| CCP, ZCPR3.x + |------------------| + | Transient | + | | + | Program | + | | + | Area | +0100H |------------------| + | Base Page | IOBYTE, Jmp WB, Jmp Dos, FCB, Buffer +0000H \------------------/ +``` + +As more and more functionality was added to the Z-System Buffers, bigger drives were added using more ALV space, and additional functionality was added to Bios code in recent systems, the available TPA space has become increasingly scarce. + +B/P Bios attacks this problem at the source in a manner which is easily adaptable to different hardware platforms. It uses additional memory for more than the traditional role of simple RAM Disks, it moves much of the added overhead to alternate memory banks. The generic scheme appears pictorially as: + +```generic +FFFFH /----------\ + | | + | BNK1 | + | | +8000H |----------| /----------\ /----------\ /----------\ + | | | |\ | |\ | |\ + | BNK0 | | BNK2 | | BNKU | | BNK3 ||\ + | | | || | || | ||| +0000H \----------/ \----------/ \----------/ \----------/ + \- - - - - / \- - - - - / \- - - - - /| + | BNKM | + \----------/ + TPA SYSTEM USER RAM DISK +``` + +As can be seen from the above diagram, multiple banks of memory may be assigned to different functional regions of memory, with each 32k bank (except for the one defined as BNK1) being switched in and out of the lower 32k of the processor's memory map. The bank defined as BNK1 is ALWAYS present and is referred to as the Common Bank. This bank holds the portions of the Operating System (Command Processor, Operating System, BIOS, and Z-System tables) which may be accessed from other areas, and which therefore must always be "visible" in the processor's memory. It also contains the code to control the Bank switching mechanisms within the B/P Bios. + +To illustrate this functional division, the memory map of a basic B/P Bios system is divided as: + +```generic +FFFFH /------------------\ + | Z-System Buffers | + |------------------| + | User Space | + |------------------| + | Bios | + |------------------| + | Operating System | + |------------------| + | Command Processor| /------------------\ 8000H + |------------------| / | Bios Buffers | +8000H | Transient | | Banked Bios Part | + | | |------------------| + | | | Banked Dos Part | + | Program | |------------------| + | | | Banked CCP Part | + | | |------------------| + | Area | | CCP Restoral | +0100H |------------------| |------------------| 0100H + | Base Page | | Base Page Copy | +0000H \------------------/ \------------------/ 0000H + TPA (BNK0/BNK1) System Bank (BNK2) +``` + +The B/P Bios banking concept defines a one byte Bank Number permitting up to 8 Megabytes to be directly controlled. Certain assumptions are made in the numbering scheme, the foremost of which is that BNK0 is the lowest physical RAM bank, BNK1 is the next incremental RAM bank, with others follow in incrementing sequential order. A couple of examples may serve to illustrate this process. The YASBEC is offered with a couple of options in the Memory Map. Units with the MEM-1, 2 or 3 decoder PALs assign the first 128k bytes of physical memory to the Boot ROM, so BNK0 is set to 4 (Banks 0-3 are the ROM). The MEM-4 PAL only uses the first 32k (Physical Bank 0) for the ROM which means that BNK0 is assigned to 1, BNK1 to 2 and so on up to the 1 Megabyte maximum where BNKM is 31. + +The Ampro Little Board equipped with MDISK, on the other hand, completely removes the Boot ROM from the memory map leaving a maximum of 1 MB of contiguous RAM space. In this system, BNK0 is set to 0 and BNKM to 31 of a fully equipped 1 MB MDISK board. + +The region beginning after BNK1 is referred to as the System Bank. It begins at the bank number assigned to BNK2 and ends at the bank number immediately before that assigned to the User Bank, BNKU if present, or BNK3 if no User Bank area is defined. + +If present, one or more 32k banks of memory may be defined with the BNKU equate for unique user programs or storage areas. This area begins with the bank number set to the label and ends at the bank number immediately before the BNK3 label. BNK3 defines a high area of physical memory which is most often used for a RAM Disk providing fast temporary workspace in the form of an emulated disk drive. + +B/P Bios contains protection mechanisms in the form of software checks to insure that critical portions of the memory map are enforced. In the case of Non-banked systems, a check is made to insure that the system size is not so great that the Bios may overwrite reserved Z-System areas in high memory (RCP, IOP, etc). If a possible overflow condition is detected, the message + +`++ mem ovfl ++` + +will be issued when the system is started. In Banked Bios systems, this message will be displayed if the top of the system portions in the SYStem Bank exceeds the 32k bank size. For most systems, this space still permits drives of several hundred megabytes to be accommodated. + +Since the Common portions of the operating system components must remain visible to applications, a similar check is made to insure that the lowest address used by the Command Processor is equal to or greater than 8000H. This factor is checked both in both MOVxSYS and BPBUILD with either a warning issued in the case of the former, or validity checks on entry in the case of the latter. + + +## 3.2 B/P Bios Files + +This BIOS is divided into a number of files, some of which depend highly on the specific hardware used on the computer, and some of which are generic and need not be edited to assemble a working system. Much use is made of conditional assembly to tailor the resulting Bios file to the desired configuration. The Basic file, `BPBIO-xx.Z80`, specifies which files are used to assemble the Bios image under the direction of an included file, `DEF-xx.LIB`. It is this file which selects features and contains the Hardware-dependent mnemonic equates. By maintaining the maximum possible code in common modules which require no alterations, versions of B/P Bios are relatively easy to convert to different machines. The independent modules used in the B/P Bios system are: + +| Filename | Description | +| :--- | :--- | +| `BOOTRAM.Z80` | (only needed in BOOT ROM applications) | +| `BOOTROM.Z80` | (only needed in BOOT ROM applications) | +| `BYTEIO.Z80` | Character IO per IOBYTE using IIO-xx routines | +| `DEBLOCK.Z80` | Disk Deblocking routines | +| `DPB.LIB` | 3.5/5.25" Floppy Format Definitions (if AutoSelect) | +| `DPB8.LIB` | 8"/Hi-Density Floppy Format Definitions (if AutoSelect) | +| `DPB2.LIB` | Additional Floppy Definitions (optional if AutoSelect) | +| `DPBRAM.LIB` | Fixed Floppy Format Definitions (if Not AutoSelect) | +| `DPH.LIB` | Disk Parameter Header Table & Floppy definitions | +| `FLOPPY.Z80` | Floppy Disk High-Level Control | +| `SECTRAN.Z80` | Sector Translate routines | +| `SELFLP1.Z80` | Floppy Select routine (if Not auto selecting) | +| `SELFLP2.Z80` | Floppy Select routine (if auto selecting) | +| `SELRWD.Z80` | Generic Read/Write routines | +| `Z3BASE.LIB` | ZCPR 3.x file equate for Environment settings | + +Other files are hardware version dependent to varying extents. These modules requiring customization for different hardware systems are given names which end with a generic "-xx" designator to identify specific versions. Tailoring these modules ranges from simple prompt line customization to complete re-writes. Versions of B/P Bios generated to date are identified as: + +| ID | Computer system | +| :---: | :--- | +| `-18` | MicroMint SB-180 | (64180 CPU, 9266 FDC, 5380 SCSI) | +| `-YS` | YASBEC | (Z180 CPU, 1772 FDC, DP8490 SCSI) | +| `-AM` | Ampro Little Board | (Z80 CPU, 1770 FDC, 1MB MDISK) | +| `-CT` | Compu/Time S-100 board set | (Z80 CPU, 1795 FDC, 1MB Memory) | +| `-TT` | Teletek | (Z80 CPU, 765 FDC) | + +Files associated with specific hardware versions or require tailoring are: + +| Filename | Description | +| :--- | :--- | +| `BPBIO-xx.Z80` | Basic file, tailored for included file names | +| `CBOOT-xx.Z80` | Cold Boot routines, Sign-on prompts | +| `DEF-xx.LIB` | Equates for option settings, mode, speed, etc. | +| `DPBHD-xx.LIB` | Hard Drive Partition Definitions (optional) | +| `DPBM-xx.LIB` | Ram Drive Definition (optional) | +| `DPHHD-xx.LIB` | Hard Drive DPH definitions (optional) | +| `DPHM-xx.LIB` | Ram Drive DPH Definition (optional) | +| `FDC-xx.Z80` | Floppy Disk Low-Level interface/driver routines | +| `HARD-xx.Z80` | Hard Drive Low-Level interface/driver routines (optional) | +| `IBMV-xx.Z80` | Banking Support Routines (if banked) | +| `ICFG-xx.Z80` | Configuration file for speed, Physical Disks, etc. | +| `IIO-xx.Z80` | Character IO definitions and routines | +| `RAMD-xx.Z80` | Ram Drive interface/driver routines (optional) | +| `TIM-xx.Z80` | Counter/Timer routines and ZSDOS Clock Driver | +| `WBOOT-xx.Z80` | Warm Boot and re-initialization routines | + + +## 3.3 B/P Bios Options + +The most logical starting point in beginning a configuration is to edit the `DEF-xx.LIB` file to select your desired options. This file is the basic guide to choosing the options for your system, and some careful choices here will minimize the Bios size and maximize your functionality. Some of the more important options and a brief description of them are: + +**MOVCPM** - Integrate into MOVCPM "type" loader? If the system is to be integrated into a MOVCPM system, the Environment descriptor contained in the CBOOT routine is always moved into position as part of the Cold Start process. If set to NO, a check will be made to see if an Environment Descriptor is already loaded, and the Bios copy will not be loaded if one is present. + +NOTE: When assembling a Bios for Boot Track Installation (MOVCPM set to YES), many options are deleted to conserve space and the Bios Version Number is forced to 1.1. + +**BANKED** - Is this a banked BIOS? If set to YES, the Bank control module, IBMV, is included in the assembly, and much of the code is relocated to the system bank. Note that a Banked system CANNOT be placed on the System Tracks, or integrated into a MOVCPM image. + +**IBMOVS** - Are Direct Inter-Bank Moves possible? If set to YES, direct transfer of data between banks is possible such as with the Zilog Z180/Hitachi 64180. If NO, a 256-byte transfer buffer is included in high Common Memory and Interbank moves require transfer of bytes through this buffer. + +**ZSDOS2** - Assemble this for a Banked ZSDOS2 system? If YES, the ALV and CSV buffers will be placed in the System bank invisible to normal programs. This has the side effect that many CP/M programs which perform sizing of files (Directory Listers, DATSWEEP, MEX, etc) which do not know about this function will report erroneous sizes. The advantage is that no sacrifice in TPA is required for large Hard Disks. Set this to NO if you want strict CP/M 2.2 compatibility. + +**FASTWB** - Restore the Command Processor from the System Bank RAM? If set to YES, Warm Boots will restore the Command Processor from a reserved area in the System RAM bank rather than from the boot tracks. For the maximum benefit of B/P Bios, always attempt to set this to YES. In systems without extended memory, it MUST be set to NO. + +**MHZ** - Set to Processor Speed in closest even Megahertz (e.g. for a 9.216 MHz clock rate, set to 9). The value entered here is used in many systems to compute Timing values and/or serial data rate parameters. + +**CALCSK** - Calculate Diskette Skew Table? If NO, a Skew table is used for each floppy format included in the image. Calculating Skew is generally more efficient from a size perspective, although slightly slower by factors which are so small as to be practically unmeasurable. + +**HAVIOP** - Include IOP code into Jump table? If the IOPINIT routine satisfies your IOP initialization requirements, you may turn this off by setting to NO and save a little space. This typically will be turned off when generating a system for MOVCPM integration to conserve space. + +**INROM** - Is the Alternate Bank in ROM? Set to NO for Normal Disk-based systems. Please contact the authors if you need additional information concerning ROM-based system components. + +**BIOERM** - Print BIOS error messages? Set this to YES if you desire direct BIOS printing of Floppy Disk Error Messages. If you are building a BIOS for placement on Boot Tracks, however, you will probably not have room and must turn this Off. Set to NO to simply return the normal Success/Fail error flag with no Message printout. + +**FLOPY8** - Include 8"/Hi-Density Floppy Formats? Some systems (SB-180, Compu/Time) can handle both 5.25" and 8" disks. If your hardware supports the capability and you want use 8" disks as well as the normal 3.5 and 5.25" diskettes, setting this to YES will add formats contained in `DPB8.LIB` and control logic to the assembly. Future systems may take advantage of the "High-Density" 3.5 and 5.25" Floppy Disks which use higher data rates. Their definitions will be controlled by this flag as well. + +NOTE: If AUTOSL is set to NO, this option will probably cause the BIOS to be larger than necessary since these additional formats may not be accessible. + +**MORDPB** - Use more Floppy DPB's (in addition to normal 4-5.25" and optional 8")? If YES, the file `DPB2.LIB` is included. Many of the formats are Dummies and may be filled with any non-conflicting formats you desire. + +NOTE: If AUTOSL if set to NO, this option will probably cause the BIOS to be larger than necessary since these additional formats may not be accessible. + +**MORDEV** - Include Additional Character Device Drivers? Is set to YES, user-defined drivers are added to the Character IO table, and associated driver code is assembled. Systems featuring expansion board such as the SB-180 and YASBEC may now take advantage of additional serial and parallel interfaces within the basic Bios. Set to NO to limit code to the basic 4 drivers. + +NOTE: When assembling a Bios for Boot Track Installation (MOVCPM set to YES), MORDEV is overridden to conserve space, and the Bios Version Number is forced to 1.1 in the distribution files. + +**BUFCON** - Use type ahead buffer for the Console? If set to YES, code is added to create and manage a type-ahead buffer for the driver assembled as the console. This device will be controlled by either interrupts (in systems such as the YASBEC and SB-180) or background polling (in Ampro and Compu/Time). This means that characters typed while the computer is doing something else will not be lost, but will be held until requested. + +**BUFAUX** - Use type ahead buffer on Auxiliary Port? As with BUFCON above, setting to YES will add code to create and manage a type ahead buffer for the auxiliary device. Since the AUX port typically is used for Modem connections, buffering the input will minimize the loss of characters from the remote end. + +**AUTOSL** - Auto-select floppy formats? If set to YES, selection of Floppy disks will use an algorithm in `SELFLP2.Z80` to identify the format of the disk from the DPB files included (`DPB.LIB`, optional `DPB8.LIB`, and optional `DPB2.LIB`) and log the disk if a match is found. There must be NO conflicting definitions included in the various files for this to function properly. See the notes in the various files to clarify the restrictions. If set to NO, the single file `DPBRAM.LIB` is included which may be tailored to contain only the fixed format or formats desired per disk drive. This results in the smallest code requirement, but least flexibility. + +**RAMDSK** - Include code for a RAM-Disk? If set to YES, any memory above the System or User bank may be used for a RAM Drive (default is drive M:) by including the file `RAMD-xx.Z80`. Parameters to determine the size and configuration are also included in the files `DPHM-xx.LIB` and `DPBM-xx.LIB`. In systems without extended memory, or to conserve space such as when building a system for the boot tracks, this may be disabled by setting to NO. + +**HARDDSK** - Include SCSI Hard Disk Driver? Set to YES if you wish to include the ability to access Hard Disk Drives. In a floppy-only system, a NO entry will minimize BIOS code. + +**HDINTS** - (System Dependent) In some systems such as the YASBEC, Interrupt-driven Hard Disk Controllers using DMA transfer capabilities may be used. If you wish to use this type of driver specified in the file `HARDI-xx.Z80` instead of the normal polled routines included in `HARD-xx.Z80`, set this option to TRUE. In most cases, this driver will require more Transient Program Area since the Interrupt Handling routine must be in Common Memory. + +**CLOCK** - Include ZSDOS Clock Driver Code? If set to YES, the vector at BIOS+4EH will contain a ZSDOS-compatible clock driver with the physical code contained in the `TIM-xx.Z80` module. If set to NO, calls to BIOS+4EH return an error code. + +**TICTOC** - (System Dependent) Use pseudo heartbeat counter? This feature is used in systems such as the Ampro Little Board and Compu/Time SBC880 which do not have an Interrupt scheme to control a Real Time Clock. Instead, a series of traps are included in the code (Character IO Status polls, Floppy Disk Status polls) to check for overflow of a 1-Second Counter. It is less desirable than an Interrupt based system, but suffices when no other method is available. Set to NO if not needed. + +**QSIZE** - Size in bytes of type ahead buffers controlled by BUFCON and BUFAUX. + +**REFRSH** - Activate Dynamic Refresh features of Z180/HD64180 processors? In some computers using these processors such as the YASBEC, refresh is not needed and merely slows down processing. Set to NO if you do not need this feature. If your processor uses dynamic memory, or needs the signal for other purposes (e.g. The SB180 uses Refresh for Floppy Disk DMA), Set this to YES. + +**Z3** - Include ZCPR init code? Since a Z3 Environment is mandatory in a B/P Bios (which now "owns" the Environment), this option has little effect. + +For assembly of a Banked version of B/P Bios, the identification of various banks of memory must be made so that the various system components "know" where things are located. Refer to Section 3.1 above for a description of these areas. The BNK0 value should be the first bank of RAM in the System unless other decoding is done. The following equates must be set: + +| Equate | Description | +| :--- | :--- | +| BNK0 | First 32k TPA Bank (switched in/out) | +| BNK1 | Second 32k TPA Bank (Common Bank) | +| BNK2 | Beginning of System Bank (BIOS, DOS, CPR) area | +| BNKU | Beginning of Bank sequence for User Applications | +| BNK3 | Beginning of Extra Banks (first bank to use for RAM Disk) | +| BNKM | Maximum Bank Number assigned | + + +## 3.4 Configuration Considerations + +When assembling a version of B/P Bios for integration into an IMG file, size of the resulting image is not much of a concern, so you need not worry about minor issues of size. For integration into a system for loading onto diskette boot tracks, however, the limitation is very real in order to insure that the CPR/DOS/BIOS and Boot Sector(s) can fit on the reserved system tracks. Typically, a limit of slightly under 4.5k exists for the Bios component. When the MOVCPM flag is set to YES for this type of assembly, warnings will be issued when the image exceeds 4352 bytes (the maximum for systems with 2 boot records), and 4480 bytes (the maximum for systems with a single boot record). Achieving these limits often requires disabling many of the features. + +The first thing you should do before assembling the BIOS is to back up the entire disk, then copy only the necessary files onto a work disk for any editing. After setting the options as desired, edit the hardware definitions in `ICFG-xx.Z80` to reflect the physical characteristics of your floppy and hard drives, as well as any other pertinent items. Then edit the logical characteristics for your Hard and Ram Drives (if any) in `DPBHD-xx.LIB` and `DPBM-xx.LIB`. If you do not desire any of the standard floppy formats or want to change them, edit `DPB.LIB` and/or `DPB2.LIB` (if using auto selection) or `DPBRAM.LIB` if you are using fixed floppy formats. Finally edit the DPH files to place the logical drives where desired in the range A..P. + +Decide whether you want to generate a system using the Image file construct developed in support of B/P Bios (BPBUILD/LDSYS), or for integration on a floppy disk's boot tracks. If the latter, you probably will not be able to have all options turned on. For example, with the MicroMint SB-180, the following options must be turned Off: BANKED, ZSDOS2, BIOERM, FLOPY8, MORDPB, BUFAUX and usually either CLOCK or RAMDSK. As an aid to space reduction, conditional assembly based on the MOVCPM flag automatically inhibits all but double-sided Floppy formats from `DPB.LIB`. If configuring for Floppy Boot tracks (MOVCPM flag set to TRUE), a warning will be printed during assembly if the size exceeds that available for a One or Two-sector boot record. Using the BPBUILD/LDSYS method, you may vary nearly all system parameters, even making different systems for later dynamic loading. + +If you are using a version of the B/P Bios already set for your type of computer, you are now ready to assemble, build a system and execute it. The only remaining task would be an optional tailoring of the sign on banner in the file `CBOOT-xx.Z80` and reassembly to a `.REL` file. + +For those converting a standard version of the B/P Bios to a new hardware system, we recommend that you begin with a Floppy-only system in Non-Banked mode then expand from there. The easiest way to test out new versions is to use the System Image (IMG file) mode, then advance to boot track installations if that is desired. Enhancements that can be added after testing previous versions may be to add Hard Drives, RAM Drive, and finally Banking. + diff --git a/Doc/CPM/BPBIOS/BPBIOS_4_Installation.md b/Doc/CPM/BPBIOS/BPBIOS_4_Installation.md new file mode 100644 index 00000000..b2b55a0a --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_4_Installation.md @@ -0,0 +1,200 @@ +# 4 Installing a B/P Bios + +The Distribution diskette(s) on which B/P Bios is furnished are configured for booting from the vanilla hardware for the version ordered. A 9600 bps serial terminal is standard, and will allow you to immediately bring up a minimal Non-Banked Floppy Disk system. Due to the variety of different system configurations and size restrictions in some versions, only the Floppy Disk Mass Storage capability can be assured on the initial boot disk. Where space remained on the boot tracks, limited Hard Drive support is also provided, and in some configurations, even RAM Drive support exists. + +After booting from either an established system, or the boot tracks of the distribution disk, format one or more fresh diskettes and copy the distribution diskette(s) contents to the backup diskette(s). Copy the boot tracks from the master to the copies using BPSYSGEN (see 6.6). Remove the master diskette(s) for safekeeping and work only with the copies you just made. + +Using the backup diskette with the B/P utilities on it, execute BPCNFG in the Boot Track configuration mode (see 6.2), adjusting all the options to your specific operating environment. When you have completed tailoring the system, it is ready for booting by placing the diskette in drive A: and resetting the system. + +The sample `STARTUP.COM` file on the distribution disk will automatically execute a sequence of instructions when the system is booted. It contains various instructions which further tailor the system and load portions of the operating system which are too big to fit on the boot tracks. The default instruction sequence is: + +| Command | Explanation | +| :--- | :--- | +| `LDDS` | Load the DateStamper style File Stamp routine and clock | +| `LDR SYS.RCP,SYS.FCP,SYS.NDR` | Load ZCPR 3 Environment segments for Resident Command Processor, Flow Control Pkg and Named Dirs | +| `IOPINIT` | Initialize the IO Processor Pkg | +| `TD S` | Prompt for Date and Time, Set Clk / Alternatives are to use `TDD` (6.21) or `SETCLOK` (6.18) | +| `IF ~EX MYTERM.Z3T` | If the file `MYTERM.Z3T` does Not exist... | +| `TCSELECT MYTERM.Z3T` | ..select which terminal you have creating a `MYTERM.Z3T` file | +| `FI` | ...end of the `IF` | +| `LDR MYTERM.Z3T` | Load the Terminal Definition data | + +If you wish to alter any of these initial instructions to, for example, initialize the RAM drive using INIRAMD, add File Time Stamp capabilities to it with INITDIR or PUTDS and copy some files there with COPY, these may be added with ALIAS, VALIAS, SALIAS or other compatible files available from the ZSYSTEM or ZCPR33 areas on Z-Nodes. + +After the initial system is up and running from the Default Boot Track system, you may expand the operation by generating systems for different purposes in order to gain the most advantage from your system. Many types of installation are possible, the simplest of which is a Non-Banked system using only 64k of the systems memory, all of which is in primary memory. Such a system uses a normal Command Processor such as the ZCPR3.x family, and a Non-Banked Operating System such as our ZSDOS Version 1. Non-Banked systems may be installed on a Disk's Boot Tracks, or created as an Image File for dynamic loading using the LDSYS Utility (see 6.15). + +Banked systems MUST be created with the BPBUILD Utility (see 6.1) and loaded with LDSYS (see 6.15). The techniques to manage different memory banks to form a complete Operating Environment are rather intricate and are best handled by our utilities. Many Image files may be created and loaded as needed to tailor your system for optimum performance. The following sections describe these various types of installations in detail. + + +## 4.1 Boot Track Installation + +For most of the existing CP/M compatible computers to begin executing a Disk Operating System, a program must be placed on a specified area of a Floppy or Hard Disk Drive. Normally, the first two or three tracks on the disk are reserved for this purpose and are referred to as the "Boot Tracks". Since the space so defined is generally restricted, neither a complete B/P Bios nor a Banked installation is possible. Instead, a scaled-down system roughly equivalent to those currently in use is used to start the computer and serve as the Operating System, with larger systems loaded later as needed. + +If you are using a pre-configured version of B/P Bios for your hardware, you may simply continue to use the Boot Track system from the distribution disk(s) by copying the system as described in Section 4 above using BPSYSGEN (see 6.6). If you elect to alter or otherwise customize the Boot Track system, you must assemble the B/P Bios source setting certain of the equates in the `DEF-xx.LIB` file to insure a correct type of system. To assemble a Boot Track system, the most important equates are: + +| Equate | | +| :---: | :--- | +| `MOVCPM` | Set to `YES` | +| `BANKED` | Set to `NO` | +| `ZSDOS2` | Set to `NO` | + +One element of Banked Systems is available in a Boot Track installation if additional memory is available, and your B/P Bios routines support such a feature. This feature reloads the Command Processor from Banked memory instead of from the Boot Tracks of a disk, and generally produces less code (taking less space on the Boot Tracks) and executes faster. It is set with: + +| Equate | | +| :---: | :--- | +| `FASTWB` | Set to `YES` if desired, `NO` if Warm Boot from disk | + +Some of the features that generally need to be disabled to scale a smaller system are set as: + +| Equate | | +| :---: | :--- | +| `MORDPB` | Set to `NO` | +| `DPB8` | Set to `NO` | +| `MORDEV` | Set to `NO` | + +When at least these equates and any others you desire to change (see section 4) have been made to the component files of the system, assemble your `BPBIO-xx` file to a Microsoft standard `.REL` file. This output file may be used to overlay the Bios portion of the `MOVxSYS.COM` system generation utility (see 6.16) furnished with your distribution disk, or an equivalent program provided with your computer. MOVxSYS or its equivalent (MOVCPM, MOVZSYS, etc) is a special program customized for your particular hardware containing all the Operating System components which will be placed on the Boot Tracks, along with a routine to alter the internal addresses to correspond to a specified memory size. + +To Add the new Bios you just assembled, execute INSTAL12 (see procedures in 6.13) specifying your computer's MOVxSYS or equivalent program and follow the prompts to overlay the new Bios. Once INSTAL12 has saved a relocatable or absolute file, you are ready to create a boot disk containing the modified system. + +If you used the command INSTAL12 to install system segments on MOVxSYS or equivalent program, you must first create an Absolute System Model file. Since the functional portion of your new program is identical to the original MOVxSYS or equivalent, use the method explained in your original documentation to generate a new system. With MOVxSYS, the command is: + +| Command | | +| :---: | :--- | +| `MOVxSYS nn *` | replace MOVxSYS with your version | + +Where `nn` is the size of the system (typically 51 for a moderate boot system). The asterisk tells the program to retain the image in memory and not write it to a disk file. You may now use BPSYSGEN to write the new image to the system tracks of your boot diskette. Do this by executing BPSYSGEN with no arguments and issue a single Carriage Return when asked for the source of the Image. + +If you used the command `INSTAL12 /A` to install replacement system segments over a System Image file, or used a utility which wrote the new image to a disk file, use BPSYSGEN to write the image file to the system tracks of your boot disk. The proper command is + +`BPSYSGEN filename` + +where filename is the name of the disk file you just created by executing MOVxSYS or equivalent with output to a disk file, or with INSTAL12 on an existing image file. + +If the system is written to a Hard Disk, and your system supports booting from a Hard Disk such as the YASBEC, you normally must alter the default Boot Sector from the default Floppy Disk Boot Sector contained in MOVxSYS or equivalent. This alteration is accomplished by HDBOOT (see 6.9) which must be customized to the specific Hardware System used. + +After the above actions have been completed as appropriate, tailor the Boot Track system to reflect the desired starting configurations with BPCNFG (see 6.2). Such items as the desired Startup file name, Bank Numbers (critical if FASTWB is used), and drive types and assignments are routinely tailored at this point. When the you have finished this step, test your new system by resetting the system, or cycling the power and you should be up and running! + + +## 4.2 Non-Banked Image Installation + +A Non-Banked system may be installed as an Image File as opposed to the basic Boot Track installation covered in 4.1 above. To create an Image File, you must have `.REL` or `.ZRL` versions of a Command Processor (ZCPR3.x or equivalent recommended), an Operating (`ZSDOS.ZRL` recommended), and a REL version of B/P Bios for your system assembled with the MOVCPM equate in `DEF-xx.LIB` set to NO. Other equates in this file may be set as described above for the Boot Track system. Since Image Files are not as constrained in size as is installation for Boot Tracks, more features may generally be activated such as Error Messages, RAM Drive, additional Hard Drive partitions, and complete Floppy Format suites. The main precaution here is that large Hard Drives will rapidly cause significant loss of Transient Program Area since all Drive parameters must be in protected high memory above the Bios. + +After the Bios has been assembled, an Image file must be produced. This is accomplished with the BPBUILD Utility (see 6.1). Set the File names in Menu 1 to reflect only Non-Banked files (or minimally banked Bios if FASTWB is set to YES), and let BPBUILD do the work. Since the standard Non-Banked System segments are normally set to the "standard" CP/M 2.2 sizes, you may answer the "autosize" query with a Y to obtain the maximum Transient Program Area in the resulting system. When BPBUILD completes its work, a file, normally with the default type of `.IMG`, will have been placed in the currently logged Drive/User area and you are ready to perform the next step in preparation of the Non-Banked Image. + +As with the Boot Track installation covered above, several system items must be tailored before the Image may be safely loaded and executed. This is done by calling BPCNFG with the Image file name as an argument, or specify Image configuration from the interactive menu (see 6.2). Set all items as you desire them in the operating system, particularly the Bank Numbers (if FASTWB is active), and the Disk Drive characteristics and assignments. When this has been satisfactorily completed, you are ready to load and execute the newly-created system. + +Installing an Image File (default file type of `.IMG`) is extremely easy. Only the utility `LDSYS.COM` (see 6.15) is needed. If the file type has not been changed from the default `.IMG`, only the basic name of the Image File need be passed to LDSYS when executed as: + +| Command | | +| :---: | :--- | +| `LDSYS IMGFILE` | where IMGFILE.IMG is your Image file name | + +The operating parameters of the currently-executing system are first examined for suitability of loading the Image File. If it is possible to proceed, the Image File is loaded, placed in the proper memory locations, and commanded to begin execution by calling the B/P Bios Cold Boot Vector. The Cold Boot (Bios Function 0) performs final installation, displays any desired opening prompt and transfers control to the Command Processor with any specified Startup file for use by a ZCPR3.x Command Processor Replacement. + +Since a non-banked Image File will probably closely resemble that contained on the Boot Tracks, the same STARTUP file may generally be used to complete the initial tailoring sequence. If a different file is desired, the Image File may be altered to specify a different file using BPCNFG. + + +## 4.3 Banked Bios, Non-banked System Installation + +With the B/P Bios system, an Image system may be created and loaded which places portions of the Bios Only in the System bank, retaining a non-banked Operating System and therefore maximum compatibility with existing applications software. A few thousand bytes can normally be reclaimed for Transient Programs in this manner, although large and/or increasing numbers of logical drives will still reduce TPA space because of the need to store Allocation Vector information in Common Memory. + +To prepare such a system, simply edit the needed Bios files if necessary with particular emphasis on the `DEF-xx.LIB` file where the following equates must be set as: + +| Equate | | +| :---: | :--- | +| `MOVCPM` | Set to `NO` | +| `BANKED` | Set to `YES` | +| `ZSDOS2` | Set to `NO` | + +Since banked memory MUST be available for this type of installation, you will probably want the Fast Warm Boot feature available to maximize system performance. To activate this option, set the following equate as: + +| Equate | | +| :---: | :--- | +| `FASTWB` | Set to `YES` | + +When the editing is complete, assemble the Bios to a Microoft `.REL` file with an appropriate assembler such as ZMAC and build an Image system with BPBUILD (see 6.1) changing the Bios file name in menu 1 to the name of the newly created Bios file. Next, configure the default conditions if necessary with BPCNFG (see 6.2) and you are ready to activate the new system in the same manner as all Image files by calling LDSYS with the Image file argument as: + +| Command | | +| :---: | :--- | +| `LDSYS BBSYS` | where BBSYS.IMG is your Image File Name | + +As with the completely Non-Banked system described above in Section 4.2, no new requirements are established for a Startup file over that used for the initial Boot System, since both the Command Processor and Disk Operating System are unbanked, and no data areas needed by application programs are placed in the System Bank. As with all Image Files, additional features such as full Bios Error Messages, more extensive Floppy Disk Formats and RAM drive may generally be included in the System definition prior to assembly since the size constraints of Boot Track systems do not apply. + + +## 4.4 Fully Banked Image Installation + +To create a system taking maximum advantage of banked memory, a special banked Operating System and Command Processor are needed. These have been furnished in initial form with this package as `ZSDOS20.ZRL` and `Z40.ZRL` respectively. They use the Banking features of B/P Bios and locate the maximum practicable amount of executable code and data in the System Bank. Of significant importance to maximizing the Transient Program Area is that the Drive Allocation Bit maps are placed in the System Bank meaning that adding large hard drives, or multiple drives produce only minimal expansion to the resident portion of the Bios. + +NOTE: The latest versions are `ZS203.ZRL`, `ZS227G.ZRL`, and `Z41.ZRL` as included in the public release of B/P Bios. See also sections 7 and 8. + +A Fully banked Bios is created by editing the B/P Bios files as needed to customize the system to your desires. Insure that the following `DEF-xx.LIB` equates are set as: + +| Equate | | +| :---: | :--- | +| `MOVCPM` | Set to `NO` | +| `BANKED` | Set to `YES` | +| `ZSDOS2` | Set to `YES` | + +Assemble the resultant B/P Bios to a Microsoft `.REL` file, Build an Image file with BPBUILD (see 6.1) and configure the produced Image file with BPCNFG (see 6.2). When you are confident that all default settings have been made, activate the file by entering: + +| Command | | +| :---: | :--- | +| `LDSYS FBANKSYS` | where FBANKSYS.IMG is your Image File Name | + +Several differences may exist in the Startup file used for a Fully banked system. Generally the changes amount to deleting items such as a File Stamp module for the Non-banked ZSDOS1 which is not necessary with the fully-banked ZSDOS 2 and Z40. Only the type of clock need be specified for ZSDOS2. Furthermore, since the Z40 Command Processor Replacement contains most commonly-used commands gathered from a number of Resident Command Processor (RCP) packages, there is normally no need to load an RCP. A simple Startup file found adequate during development of the fully-banked B/P system is: + +| Command | Explanation | +| :--- | :--- | +| `ZSCFG2 CB` | Set ZSDOS 2 clock to Bios+4EH | +| `LDR SYS.FCP,SYS.NDR` | Load ZCPR 3 Environment segments for Flow Control and Named Dirs | +| `IOPINIT` | Initialize the IO Processor Pkg | +| `TD S` | Prompt for Date and Time, Set Clk / Alternatives are to use `TDD` (6.21) or `SETCLOK` (6.18) | +| `IF ~EX MYTERM.Z3T` | If the file `MYTERM.Z3T` does Not exist... | +| `TCSELECT MYTERM.Z3T` | ..select which terminal you have creating a `MYTERM.Z3T` file | +| `FI` | ...end if the `IF` | +| `LDR MYTERM.Z3T` | Load the Terminal Definition data | + +Since the requirements for a fully-banked system differ significantly from a non-banked one, we recommend that you use a different name for the Startup file. For example, `STARTUP.COM` is the default name used with Boot Track systems for initial operation, and with Non-banked Image Files, while STARTB may be a suitable name for the script to be executed upon loading a fully-banked system. The name of the desired Startup file may be easily altered in either Boot Track or Image systems from Option 1 in BPCNFG (see 6.2). + +An option available to start from a large Image File is to configure a Startup file for execution by the Boot Track system containing a single command. The command would simply invoke LDSYS with the desired Banked Image File as an argument such as: + +| Command | | +| :---: | :--- | +| `LDSYS BANKSYS` | where BANKSYS.IMG is your Image file | + +In this case, none of the normal initialization sequences cited above would be executed by the Boot Track system, and only those contained in the Startup for `BANKSYS.IMG` would occur. Other options abound and are left to the community to invent new combinations and sequences. + + +## 4.5 In Case of Problems... + +While We attempted to outline procedures for the majority of installations we considered feasible, there may be occasions where you inadvertently find yourself in a position where you seem to have lost the ability to get your system up and running. + +**PROBLEM:** When loading an `.IMG` file with LDSYS, the screen displays the LDSYS banner, system addresses, and halts with the last screen displaying: "...loading banked system". + +_SOLUTION:_ Something is not set correctly in the Bios, since all lines after the last one displayed are printed from the newly-loaded Bios. One of the most common causes for this problem is incorrect bank number settings. Use the hidden selection in Menu 1 of BPCNFG (see 6.2) to verify that the correct bank numbers have been set for TPA and SYStem banks. Another common cause of this problem is incorrect settings for the Console port, or a setting in the IOBYTE which directs Console data to a device other than the one intended. Use Menu 2 BPCNFG to properly set the IOBYTE and the console parameters. + +**PROBLEM:** You boot from or load a B/P Bios system from a Hard Drive, and immediately after starting, the system attempts to log onto Floppy Drive 0. + +_SOLUTION:_ The most common cause for this symptom is that the desired Hard Drive and Floppy Drive definitions were not swapped to define a Hard Drive Partition as the A: drive. Use BPCNFG (see 6.2), Menu 5 to exchange drives to the desired configuration. A similar situation may exist where a Hard Drive is activated immediately after booting when a Floppy drive is desired as the A: Drive. + +**PROBLEM:** The computer seems to boot satisfactorily, but after a few programs or any program which executes a Warm Boot (or entering Control-C), the system goes into "Never-never Land" and must be reset. + +_SOLUTION:_ This symptom is most often caused by an inability to access and load the Command Processor. This is most probably caused by assembling B/P Bios with the FASTWB equate in `DEF-xx.LIB` set to YES when the system contains no extended memory, or incorrect settings of the Bank Numbers. To check Bank Number settings, use the hidden function in BPCNFG, Menu 1 (see 6.2). + +**PROBLEM:** When doing a Cold Boot from a Hard Drive (from Power up or Reset), the system goes to a Floppy Drive before displaying the initial sign on messages, and remains logged on the Floppy. + +_SOLUTION:_ This is most often due to your forgetting to run the HDBOOT utility on the Hard Drive Boot system after applying it with BPSYSGEN. Normally, systems created with MOVxSYS contain a Floppy Disk Boot sector which will load the initial Operating System from a Floppy. HDBOOT (see 6.9) modifies this record on a specified Hard Drive Unit so that the Operating System is loaded from a Hard Drive. Run HDBOOT on the Desired Hard Drive, then use BPCNFG (see 6.2) to insure that the logical drives are positioned as desired (Menu 5). + +**PROBLEM:** When Booting, the system console either doesn't display anything, or prints strange characters. + +_SOLUTION:_ This is most often due to incorrect settings for the current Console, most probably the Data rate, or CPU Clock Frequency. Boot from a good system, then use BPCNFG (see 6.2) to adjust the settings on the problem system. Pay particular attention to Menu 1 (CPU Clock Rate) and Menu 2 (IOBYTE and Serial Port Data Rates). + +**PROBLEM:** When running a fully-banked system with ZSDOS 2, some programs seem to "hang" or "lock up" the system on exit. + +_SOLUTION:_ One of the most common sources of this symptom is with the application program where the author used code which assumes that the BDOS and Command Processor are of a certain size, or bear a fixed relationship to the addresses in page 0. You may experience this most often when using an IMG system built by answering YES to the Autosizing query in BPBUILD (see 6.1). To compensate for such ill-behaved programs, you may use a two-step build process as: + +1. Use BPBUILD to create an IMG file answering YES to Autosizing on exit. This maximizes TPA placing the Resident Bios as high as possible in memory. + +2. Execute BPBUILD again with an argument of the name you gave to the file just created above. This loads the definition from the IMG file. Immediately exit with a Carriage Return, and answer NO to Autosizing, and YES to placing system segments at standard locations. This procedure keeps the Bios address constant, but will move the starting addresses of BDOS and Command Processor down, if possible, to simulate "standard" sizes used in CP/M 2.2. + + diff --git a/Doc/CPM/BPBIOS/BPBIOS_5_Programming.md b/Doc/CPM/BPBIOS/BPBIOS_5_Programming.md new file mode 100644 index 00000000..de4808c6 --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_5_Programming.md @@ -0,0 +1,1364 @@ +# 5. Programming for B/P Bios + +For most existing purposes, programming for B/P Bios is no different than for standard CP/M 2.2 BIOSes. Even adapting CP/M 3 programs for a B/P Bios should present no great hurdle due to the close similarity retained with the corresponding extended functions. The power of a B/P Bios interface, however, is in using the combined features to produce portable software across a wide variety of hardware platforms by exercising all of the B/P Bios features in concert. This section describes the interfaces available to the programmer of a system using the B/P Bios, and the functions available to ease direct floppy and hard drive accesses for specialized programming in a consistent manner. + +One of the architectural flaws which we considered in CP/M Plus was the odd way in which direct BIOS access was handled. We designed B/P Bios to be as compatible with CP/M 2.2 as possible, yet provide the expanded functionality needed in Banked applications. To that end, direct interface with BIOS calls follows CP/M 2.2 conventions as much as possible. + +The following pages on programming assume some familiarity with the basic CP/M fundamentals, and with Z80/Z180 assembly language, since it is beyond the intent of this manual, and our literary writing skills, to present an assembly programming tutorial. Should you need additional assistance in this area, please refer to the annotated bibliography for reference material. + + +## 5.1 Bios Jump Table + +The BIOS Jump table consists of 40 Jumps to various functions within the BIOS and provides the basic functionality. It includes the complete CP/M 2.2 sequence, most of the CP/M 3 (aka CP/M Plus) entry points (although some differ in parameter ordering and/or register usage), and new entry points needed to handle banking in a consistent and logical manner. + +Bios entry points consist of a Table of Absolute 3-byte jumps placed at the beginning of the executable Image. Parameters are passed to the Bios in registers as needed for the specific operation. To avoid future compatibility problems, some of the ground rules for Bios construction include; No alteration of Alternate or Index registers as a result of Bios calls, and all registers listed in the documentation as being Preserved/Unaffected MUST be returned to the calling program in their entry state. + + +## 5.2 Bios Reference Card + +| Number | Fcn Name | Input Parameters | Returned Values | Uses | +|:------:|:---------|:---------------------|:------------------------ |:------| +| 0 | CBOOT | None | None | All | +| 1 | WBOOT | None | None | All | +| 2 | CONST | None | A= FFH Ready, 0 No Char | AF | +| 3 | CONIN | None | A= Char from CON: (masked) | AF | +| 4 | CONOUT | C= Char to send (masked) | None | AF | +| 5 | LIST | C= Char to send (masked) | None | AF | +| 6 | AUXOUT | C= Char to Send (masked) | None | AF | +| 7 | AUXIN | None | A= Char from AUX: (masked) | AF | +| 8 | HOME | None | _[Status Code]_ | All | +| 9 | SELDSK | C= Drive (0=A .. 15=P) | HL= DPH addr, 0 No Drive | All | +| 10 | SETTRK | BC= Track Number | None | None | +| 11 | SETSEC | BC= Sector Number | None | None | +| 12 | SETDMA | BC= DMA Address | None | None | +| 13 | READ | None | _Status Code_ | All | +| 14 | WRITE | C= Write Type (0= Unalloc, 1= Dir, Force) | __ | All | +| 15 | LISTST | None | A= FFH Ready, 0 Busy | AF | +| 16 | SECTRN | BC= Logical Sect # | HL= Physical Sect # | All | +| **----** | **----** | **----------** |**<<< End of CP/M 2.2 Vectors >>>** | **----** | +| 17 | CONOST | None | A= 0FFH Ready, 0 Busy | AF | +| 18 | AUXIST | None | A= FFH Ready, 0 No Char | AF | +| 19 | AUXOST | None | A= 0FFH Ready, 0 Busy | AF | +| 20 | DEVTBL | None | HL-> Char IO Table | HL | +| 21 | DEVINI | None | None | All | +| 22 | DRVTBL | None | HL-> DPH Table if Ok, 0 No Drive | HL | +| 23 | | ***Reserved for MULTIO*** | | | +| 24 | FLUSH | None | _[Status Code]_ | All | +| 25 | MOVE | HL= Source adr, DE= Dest adr, BC= Length | None | All | +| 26 | TIME | C= 0(Read) / 1(Set), DE-> 6-byte Time | A= 1 if Ok, 0 Errs, E= Orig 6th byte, D= 1/10th Secs (Read) | All | +| 27 | SELMEM | A= Bank Number | None | None | +| 28 | SETBNK | A= Bank Number | None | None | +| 29 | XMOVE | C= Source bank, B= Dest bank | None | None | +| **----** | **----** | **----------** | **<<< End of CP/M 3 "Type" Vectors >>>** | **----** | +| 30 | RETBIO | None | A= Bios Vers, BC-> Bios base, DE-> Config area, HL-> Device Cnfg Table | A, BC, DE, HL | +| 31 | DIRDIO | B= Driver Type, C= Fnc # | _see below for Direct Device IO_ | | +| 32 | STFARC | A= Bank Number | None | None | +| 33 | FRJP | HL= Dest addr | ?? | ?? | +| 34 | FRCLR | HL= Return addr | ?? | None | +| 35 | FRGETB | HL-> Byte to Get, C= Bank # | A=Byte at (C:HL) | AF | +| 36 | FRGETW | HL-> Word to Get, C= Bank # | DE=Word at (C:HL) | F, DE | +| 37 | FRPUTB | HL-> Byte Dest, C= Bank #, A= Byte to Put | None | F | +| 38 | FRPUTW | HL-> Word Dest, C= Bank #, DE= Word to Put | None | F | +| 39 | RETMEM | None | A= Current Bank Number | AF | + +_Status Code:_ +A= 0, Zero Set (Z) if Operation successfully performed +A <> 0, Zero Clear (NZ) if Errors occured in Operation + + +**FLOPPY DISK SUBFUNCTIONS (Function 31)** +Input Parameters: B= 1 Floppy, C= Subfcn # +| Number | Fcn Name | Input Parameters | Returned Values | Uses | +|:------:|:---------|:---------------------|:------------------------ |:------| +| 0 | STMODE | A= 0 (Double Dens), FFH (Single) | None | AF | +| 1 | STSIZE | A= 0 (Normal Speed), 0FFH (Hi capable), D= 0 (Motor On Cont) 0FFH (Motor Contr), E= 0 (Hard), 1 (8"), 2 (5.25"), 3 (3.5") | None | AF | +| 2 | STHDRV | A= Unit (B0,1) Head (D2) | None | AF | +| 3 | STSECT | A=Phys Track #, D= 0..3 (128 .. 1024 Sctrs), E= Last Sector # | None | AF | +| 4 | SPEC | A= Step rate in mS (B7=1 for 8" Drv), D= Head Unload in mS, E= Head Load in mS | None | AF | +| 5 | RECAL | | _[Status Code]_ | AF | +| 6 | SEEK | A= Desired Trk #, D= 0FFH Verify, E= 0 (Single-step) <>0 (Double) | _[Status Code]_ | AF | +| 7 | SREAD | HL-> Read Buffer | _[Status Code]_ | AF, HL | +| 8 | SWRITE | HL-> Write Buffer | _[Status Code]_ | AF, HL | +| 9 | READID | | _[Status Code]_ | AF | +| 10 | RETDST | | A= Status Byte, BC= Controller Type, HL-> Status Byte | AF, BC, HL | +| 11 | FMTTRK | HL-> Format Data, D= Sctrs/Trk, E= Gap 3 Byte Count | _[Status Code]_ | AF | + + +**HARD DISK SUBFUNCTIONS (Function 31)** +Input Parameters: B= 2 HD, C= Subfcn +| Number | Fcn Name | Input Parameters | Returned Values | Uses | +|:------:|:---------|:---------------------|:------------------------ |:------| +| 0 | HDVALS | DE-> 512 byte Buff | A= # Bytes in CDB | AF, HL | +| 1 | HDSLCT | A= Device Byte | A= Physical Device Bit | AF | +| 2 | DOSCSI | DE-> Cmd Desc Blk, A= 0 (No Write Data) | H= Msg Byte, L= Status Byte, A= Masked Status Byte | All | + + +## 5.3 Bios Functions + +| Function 0 (xx00) | CBOOT Cold Boot | +|---:|:---| +| Enter: | None | +| Exit: | None | +| | Execution resumes at CPR | +| Uses: | All Registers | + +Execute Cold Start initialization on the first execution. The jump argument is later overwritten, and points to the IOP Device jump table. The reason for this is that code to perform the initialization is often placed in areas of memory which are later used to store system information as a memory conservation measure. Attempts to re-execute the initialization code would then encounter data bytes instead of executable instructions, and the system would most assuredly "crash". + +Among other functions performed during initial execution of the Cold Boot code are; Establishing an initial Z3 Environment if necessary, initializing any Z3 system segments such as an Extended Path, Flow Control Package, Named Directory Buffer and such; setting system-specific values such as the locations of Allocation Vector buffers for RAM and Hard Drives; and executing the Device Initialization routine (see Function 21). The Cold Boot routine usually exits by chaining to the Warm Boot Function (Function 1) to set vectors on Page 0 of the TPA memory bank. + +| Function 1 (xx03) | WBOOT Warm Boot | +|---:|:---| +| Enter: | None | +| Exit: | None | +| | Execution resumes at CPR | +| Uses: | All Registers | + +This function re-initializes the Operating System and returns to the Command Processor after reloading it from the default drive boot tracks, or banked memory if the Bios was assembled with the Fast Warm Boot option. + +Unless altered by an ill-behaved Resident System Extension (RSX) or other operating transient program, the Warm Boot Vector at location 0 in memory points to this vector. Well-behaved programs will not alter this address but should, instead, alter the destination argument of the Jump vector in the Bios header. There is a singular exception to this in the case of NZCOM where the Warm Boot vector points to the NZBIOS, and Not the "Real" Bios. In such a case, the address of the "Real" Bios must be separately determined (See Function 30). + +| Function 2 (xx06) | CONST Console Input Status | +|---:|:---| +| Enter: | None | +| Exit: | A = 0FFH if Char Ready, NZ | +| | A = 0 if No Char Ready, Z | +| Uses: | AF | + +This function returns a flag indicating whether or not a character has been entered from the Console device selected by the IOBYTE on Page 0 of the TPA Bank. The return status is often used by Transient Programs to determine if the user has attempted to start or stop program execution. + +| Function 3 (xx09) | CONIN Console Input | +|---:|:---| +| Enter: | None | +| Exit: | A = Masked Input Character | +| Uses: | AF | + +This function waits for a character to be entered from the Console device selected by the IOBYTE on Page 0 of the TPA Bank, and returns it to the calling routine. According to strict CP/M 2.2 standards, the Most Significant bit of the input byte must be set to Zero, but this may be altered by the input mask for the Console Device. + +| Function 4 (xx0C) | CONOUT Console Output | +|---:|:---| +| Enter: | C = Character to send to Console | +| Exit: | None | +| Uses: | AF | + +This function sends a specified character to the Console Device defined by theIOBYTE on Page 0 of the TPA Bank. It will wait for the device to become ready, if necessary, before sending the character, and will mask bits as specified in the Character Device Configuration for the device as an Output. + +| Function 5 (xx0F) | LIST List Output | +|---:|:---| +| Enter: | C = Character to send to List Device (Printer) | +| Exit: | None | +| Uses: | AF | + +This function will send a specified character to the List Device (Printer) defined by the IOBYTE on Page 0 of the TPA Bank. It will wait for the device to become ready, if necessary, before sending the character, and will mask it as specified in the Character Device Configuration for the Output device. + +| Function 6 (xx12) | AUXOUT Auxiliary Output | +|---:|:---| +| Enter: | C = Character to send to Auxiliary Device | +| Exit: | None | +| Uses: | AF | + +This function will send a specified character to the Auxiliary Output Device defined by the IOBYTE on Page 0 of the TPA Bank. It will wait for the device to become ready, if necessary, before sending the character, and will mask it as specified in the Character Device Configuration for the Output device. + +| Function 7 (xx15) | AUXIN Auxiliary Input | +|---:|:---| +| Enter: | None | +| Exit: | A = Masked Input Character | +| Uses: | AF | + +This function will read a character from the Auxiliary Input Device defined by the IOBYTE on Page 0 of the TPA Bank. It will wait for a character to be received, and will mask it as specified in the Character Device Configuration for the Input device. + +| Function 8 (xx18) | HOME Home Drive | +|---:|:---| +| Enter: | None | +| Exit: | None | +| | Heads on selected drive moved to Track 0 | +| Uses: | All Primary Registers | + +This function will position the head(s) on the selected drive to Track 0. In B/P Bios, This operation performs no useful action, and is simply a Return. Pending Write purges and head repositioning is handled by the individual device drivers (Specifically Select Drive functions). + +| Function 9 (xx1B) | SELDSK Select Logical Drive | +|---:|:---| +| Enter: | C = Desired Drive (A=0..P=15) | +| Exit: | (Success) A <> 0, NZ, HL = DPH Address | +| | (No Drive) A = 0, Zero (Z), HL = 0 | +| Uses: | All Primary Registers | + +This function selects a specified logical drive as the current drive to which disk operations refer. If the operation is successful, the Disk Parameter Header (DPH) address is returned for later determination of the unit parameters If the operation fails for any reason (non-existant drive, unknown or bad media, etc), a Zero value pointer is returned to signify that the drive cannot be accessed through the Bios. + +| Function 10 (xx1E) | SETTRK Select Track | +|---:|:---| +| Enter: | BC = Desired Track Number | +| Exit: | None | +| | Track Number saved | +| Uses: | No Registers | + +This function stores a specified Logical Track number for a future disk operation. The last value stored with this function will be the one used in Disk Reads and Writes. + +**NOTE:** While a 16-bit value is specified for this function, only the lower byte (8-bits) is used in most drivers. + +| Function 11 (xx21) | SETSEC Select Sector | +|---:|:---| +| Enter: | BC = Desired Sector Number | +| Exit: | None | +| | Sector Number saved | +| Uses: | No Registers | + +This function stores a specified Logical Sector Number for a future disk operation. The last value stored with this function will be the one used in Disk Reads and Writes. + +**NOTE:** While a 16-bit value is specified for this function, only the lower byte (8-bits) is used in all Floppy Disk and most Hard and RAM Disk drivers. + +| Function 12 (xx24) | SETDMA Set DMA Address for Transfer | +|---:|:---| +| Enter: | BC = Buffer Starting Addr | +| Exit: | None | +| | DMA Address saved | +| Uses: | No Registers | + +This Function stores a specified address to be used as the Source/Destination for a future disk operation. The last value stored with this function will be the one used in Disk Reads and Writes. In banked systems, the Bank selected for the transfer may be altered by Function 28. + +| Function 13 (xx27) | READ Disk Read | +|---:|:---| +| Enter: | None | +| Exit: | A = 0, Z if No Errors | +| | A = Non-Zero if Errors, NZ | +| Uses: | All Primary Registers | + +This function reads a Logical 128-byte sector from the Disk, Track and Sector set by Functions 9-11 to the address set with Function 12. On return, Register A=0 if the operation was successful, Non-Zero if Errors occurred. + +| Function 14 (xx2A) | WRITE Disk Write | +|---:|:---| +| Enter: | C = 1 for immediate write | +| | C = 0 for buffered write | +| Exit: | A = 0, Z if No Errors | +| | A = Non-Zero if Errors, NZ | +| Uses: | All Primary Registers | + +This function writes a logical 128-byte sector to the Disk, Track and Sector set by Functions 9-11 from the address set with Function 12. If Register C=1, an immediate write and flush of the Bios buffer is performed. If C=0, the write may be delayed due to the deblocking. + +| Function 15 (xx2D) | LISTST List Output Status | +|---:|:---| +| Enter: | None | +| Exit: | A = 0FFH, NZ if ready for Output Character | +| | A = 0, Z if Printer Busy | +| Uses: | AF | + +This function returns a flag indicating whether or not the printer is ready to accept a character. It uses the IOBYTE on Page 0 of the TPA Bank to determine which physical device to access. + +| Function 16 (xx30) | SECTRN Perform Sector Translation | +|---:|:---| +| Enter: | BC = Logical Sector Number | +| | DE = Addr of Translation Table | +| Exit: | HL = Physical Sector Number | +| Uses: | All Primary Registers | + +This function translates the Logical Sector Number in register BC (Only C used at present) to a Physical Sector number using the Translation Table obtained from the DPH and addressed by DE. + +----- + +This ends the strict CP/M 2.2-compliant portion of the Bios Jump Table. The next series of entry Jumps roughly follows those used in CP/M 3, but with corrections to what we perceived to be deficiencies and inconsistencies in the calling parameters and structures. + +----- + +| Function 17 (xx33) | CONOST Console Output Status | +|---:|:---| +| Enter: | None | +| Exit: | A = 0FFH, NZ if Console ready for output char | +| | A = 0, Z if Console Busy | +| Uses: | AF | + +This function returns a flag indicating whether or not the Console Device selected by the IOBYTE on Page 0 of the TPA Bank is ready to accept another output character. + +| Function 18 (xx36) | AUXIST Auxiliary Input Status | +|---:|:---| +| Enter: | None | +| Exit: | A = 0FFH, NZ if Aux Input has character waiting | +| | A = 0, Z if No char ready | +| Uses: | AF | + +This function returns a flag indicating whether or not the Auxiliary Input selected by the IOBYTE on Page 0 of the TPA Bank has a character waiting. + +| Function 19 (xx39) | AUXOST Auxiliary Output Status | +|---:|:---| +| Enter: | None | +| Exit: | A = 0FFH, NZ if Aux Output ready for output char | +| | A = 0, Z if Aux Out Busy | +| Uses: | AF | + +This function return a flag indicating whether or not the Auxiliary Output selected by the IOBYTE on Page 0 of the TPA Bank is ready to accept another character for output. + +| Function 20 (xx3C) | DEVTBL Return Pointer to Device Table | +|---:|:---| +| Enter: | None | +| Exit: | HL = Address of Device Table | +| Uses: | HL | + +This function roughly corresponds to an analogous CP/M Plus function although precise bit definitions vary somewhat. The Character IO table consists of four devices; COM1, COM2, PIO, and NUL. Each has an input and output mask, data rate settings and protocol flags. Not all defined settings (e.g. ACK/NAK and XON/XOFF handshaking, etc) may be fully implemented in each version, but are available for later expansion and use. + +| Function 21 (xx3F) | DEVINI Initialize Devices | +|---:|:---| +| Enter: | None | +| Exit: | None | +| | Initialization done | +| Uses: | All Primary Registers | + +This function initializes Character IO settings and other functions which may be varied by a Configuration Utility. It is an extended version of the corresponding CP/M Plus function. Its primary use is to restore IO configurations, system parameters such as clock rate, wait states, etc, after alteration by programs which directly access hardware such as many modem programs and the configuration utility, BPCNFG (see 6.2). + +| Function 22 (xx42) | DRVTBL Return DPH Pointer | +|---:|:---| +| Enter: | None | +| Exit: | HL = Address of start of Table of DPH Pointers | +| Uses: | HL | + +This function returns a Pointer to a table of 16-bit pointers to Disk Parameter Headers for Drives A-P. A Null (0000H) entry means that no drive is defined at that logical position. + +| Function 23 (xx45) | reserved | +|---:|:---| +| Enter: | None | +| Exit: | None | +| Uses: | No Registers | + +This function is reserved in the initial B/P Bios release and simply returns. + +| Function 24 (xx48) | FLUSH Flush Deblocker | +|---:|:---| +| Enter: | None | +| Exit: | None | +| | Pending Disk Writes executed | +| Uses: | All Primary Registers | + +This function writes any pending Data to disk from deblocking buffers as mentioned in Function 14 above. This function should be called in critical areas where tasks are being swapped, or media is being exchanged when it is possible that the Operating System will not detect the change. + +| Function 25 (xx4B) | MOVE Perform Possible Inter-Bank Move | +|---:|:---| +| Enter: | HL = Start Source Address | +| | DE = Start Dest Address | +| | BC = Number Bytes to Move | +| Exit: | None | +| | Data is moved | +| Uses: | All Primary Registers | + +This function moves the specified number of bytes between specified locations. For banked moves, the Source and Destination banks must have been previously specified with an XMOVE call (function 29). Note that the B/P implementation of this function reverses the use of the DE and HL register pairs from the CP/M 3 equivalent function. + +| Function 26 (xx4E) | TIME Get/Set Date and Time | +|---:|:---| +| Enter: | DE = Start of 6-byte Buffer | +| | C = 0 (to Get Date/Time) | +| | C = 1 (to Set Date/Time) | +| Exit: | A = 1 of Successful | +| | A = 0 if Error or No Clock | +| Uses: | All Primary Registers | + +This function provides an interface to programs for a Real-Time Clock driver in the Bios. The function uses a 6-byte Date/Time string in ZSDOS format as opposed to Digital Research's format used in CP/M Plus for this function. Also, This function must conform to additional requirements of DateStamper(tm) in that on exit, register E must contain the entry contents of (DE+5) and HL must point to the entry (DE)+5. If the actual hardware implementing the clock supports 1/10 second increments, the current 1/10 second count may be returned in register D. + +| Function 27 (xx51) | SELMEM Select Memory Bank | +|---:|:---| +| Enter: | A = Desired Memory Bank | +| Exit: | None | +| | Bank is in Context in range 0..7FFFH | +| Uses: | AF | + +This function selects the Memory Bank specified in the A register and make it active in the address range 0-7FFFH. Since character IO may be used when a bank other than the TPA (which contains the IOBYTE) is activated with this function, the B/P Bios automatically obtains the IOBYTE from the TPA bank to insure that Character IO occurs with the desired devices. + +| Function 28 (xx54) | SETBNK Select Memory Bank for DMA | +|---:|:---| +| Enter: | A = Memory Bank for Disk DMA Transfers | +| Exit: | None | +| | Bank Number saved for later Disk IO | +| Uses: | No Registers | + +This function selects a memory Bank with which to perform Disk IO. Function 12 (Set DMA Transfer Address) operates in conjunction with this selection for subsequent Disk IO. + +| Function 29 (xx57) | XMOVE Set Source and Dest Banks for Move | +|---:|:---| +| Enter: | B = Destination Bank Num | +| | C = Source Bank Number | +| Exit: | None | +| | Bank Nums saved for MOVE operation | +| Uses: | No Registers | + +This function sets the Source and Destination Bank numbers for the next Move (Function 25). After a Move is performed, the Source and Destination Banks are automatically reset to TPA Bank values. + +----- + +This marks the end of the CP/M Plus "Type" jumps and begins the unique additions to the B/P Bios table to support Banking, Direct IO and interfacing. + +----- + +| Function 30 (xx5A) | RETBIO Return BIOS Addresses | +|---:|:---| +| Enter: | None | +| Exit: | A = Bios Version (Hex) | +| | BC = Addr of Bios Base | +| | DE = Addr of Bios Config | +| | HL = Addr of Device Table | +| Uses: | All Primary Registers | + + +This function returns various pointers to internal BIOS data areas and the Bios Version Number as indicated above. The Bios Version may be used to determine currency of the system software, and will be used by various support utilities to minimize the possibility of data corruption and/or as an indicator of supported features. + +The Base Address of the Bios Jump Table returned in register BC is often used to insure that the proper indexing is achieved into the B/P data structures in the event that a Bios "shell" has been added such as when running NZCOM. While the Warm Boot jump at memory location 0000H normally points to the Bios Base+3, it is not always reliable, whereas this function will always return a true value with B/P Bios. + +Registers DE and HL return pointers which are of value to programs which alter or configure various Bios parameters. The pointer to the configuration area of the Bios should be used in utilities as opposed to indexing from the start of the Bios Jump Table since additions to the Jump Table or insertion of other data will affect the Configuration Area starting address. The pointer in HL is available for use in systems which may contain more than four character IO devices. This pointer enables exchanges of devices to place desired devices in the first four positions of the table making them available for selection via the IOBYTE. After any alterations are made to the devices, a call to the Device Configuration Bios Function 21 should be made to activate the features. + +| Function 33 (xx5D) | Floppy Disk and Hard Disk Subfunctions | +|---:|:---| +| _see below_ | | + + +| Function 32 (xx60) | STFARC Set Bank for Far Jump/Call | +|---:|:---| +| Enter: | A = Desired Bank Number | +| Exit: | None | +| Uses: | No Registers | + +This Function sets the bank number for a later Function 33 Jump to a routine in an alternate Memory Bank. + +| Function (xx63) | FRJP Jump to (HL) in Alternate Bank | +|---:|:---| +| Enter: | HL = Address to execute in Bank set w/Fn 32 | +| Exit: | | +| | Called routine sets return status | +| Uses: | All Primary Regs (assumed) | + +This Function switches to the bank number previously specified with Function 32, then calls the routine addressed by HL. Upon completion, operation returns to the bank from which called, and the address on the top of the stack. + +| Function 34 (xx66) | FRCLR Clear Stack Switcher | +|---:|:---| +| Enter: | HL = Addr to resume exec in entry bank | +| Exit: | None | +| | Execution resumes at addr in HL in entry bank | +| Uses: | No Registers | + +This Function is used for error exits from banked routines to return to the entry bank. + +| Function 35 (xx69) | FRGETB Load A,(HL) from Alternate Bank | +|---:|:---| +| Enter: | HL = Addr of desired byte | +| | C = Desired Bank Number | +| Exit: | A = Byte from C:HL | +| Uses: | AF | + +This Function gets a byte (8-bits) from the specified Bank and Address. The bank is temporarily switched in context for the access (if required), then restored to entry conditions. Interrupts are temporarily disabled during the brief access time. + +| Function 36 (xx6C) | FRGETW Load DE,(HL) from Alternate Bank | +|---:|:---| +| Enter: | HL = Addr of desired word | +| | C = Desired Bank Number | +| Exit: | DE = Word from C:HL | +| Uses: | AF, DE | + +This Function gets a Word (16-bits) from the specified Bank and Address. The bank is temporarily switched in context for the access (if required), then restored to entry conditions. Interrupts are temporarily disabled during the brief access time. + +| Function 37 (xx6F) | FRPUTB Load (HL),A to Alternate Bank | +|---:|:---| +| Enter: | HL = Addr of Dest Byte | +| | C = Desired Bank Number | +| | A = Byte to save at C:HL | +| Exit: | None | +| | Byte stored at C:HL | +| Uses: | AF | + +This Function saves a Byte (8-bits) to the specified Address and Bank. The bank is temporarily switched in context for the access (if required), then restored to entry conditions. Interrupts are temporarily disabled during the brief access time. + +| Function 38 (xx72) | FRPUTW Load (HL),DE to Alternate Bank | +|---:|:---| +| Enter: | DE = Word to store at C:HL | +| | HL = Addr of Dest Byte | +| | C = Desired Bank Number | +| Exit: | None | +| | Word stored at C:HL | +| Uses: | AF | + +This Function saves a Word (16-bits) to the specified Address and Bank. The bank is temporarily switched in context for the access (if required), then restored to entry conditions. Interrupts are temporarily disabled during the brief access time. + +| Function 39 (xx75) | RETMEM Return Current Bank in Context | +|---:|:---| +| Enter: | None | +| Exit: | A = Bank currently active in Addr 0..7FFFH | +| Uses: | AF | + +This Function returns the Memory Bank currently in Context in the address range of 0..7FFFH. It may be used in the "where am I" role in application programs to track memory accesses. + + +----- + +### Function 31 - FLOPPY DISK SUBFUNCTIONS + +Function 31 permits low-level access to Floppy and Hard Disks (via SCSI interface) by specifying a Driver Number and desired Function. While some hardware types do not support all of the parameters specified, particularly for Floppy Drives, this architecture supports all types, although specific systems may ignore certain functions. In this manner, for example, a single Format program supports NEC765, SMC9266, WD1770/1772/179x and other controller types with widely differing interfaces. Floppy Disk functions are accessed by entering a 1 value into Register B (Floppy Driver Number) and the desired function number in Register C, then jumping to or calling BIOS Entry jump number 31. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 0 | +|---:|:---| +| | **Set Floppy Read/Write Mode** | +| Enter: | A = 0 for Double Density, | +| | FF for Single Density | +| | B = 1 (Floppy Driver) | +| | C = 0 (Subfunction #) | +| Exit: | None | +| Uses: | AF | + +This routine establishes the Density mode of operation of the Floppy Disk Controller for Read and Write accesses. It assumes that SubFunctions 1 (Set Size and Motor) and 3 (Set Sector) have been called first. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 1 | +|---:|:---| +| | **Set Floppy Disk & Motor Parms** | +| Enter: | A = 0 for 300 rpm (normal), | +| | FF for 360 rpm (8"/HD) | +| | D = FF for Motor Control, | +| | 0 if Motor always on | +| | B = 1 (Floppy Driver) | +| | C = 1 (Subfunction #) | +| Exit: | None | +| Uses: | AF | + +This routine establishes some of the physical parameters for a Floppy Drive. The normal 5.25" and 3.5" disk drives holding 400 or 800 kb or less rotate at 300 rpm. Many of the newer drives can increase this speed to 360 rpm which is the rate used on older 8" floppy drives. This is the speed used on the "High Density" 1.2 MB (IBM formatted) 5.25" drives. The A register is used to indicate the fastest speed capable on the specified drive. Register D is used to indicate whether the Motor is always On, or will start and stop periodically. This is normally used by the Bios to delay for a period before writing if the motor is stopped to allow the diskette to come up to speed thereby minimizing chances of data corruption. Register E is used to indicate the physical media size as; 0=Hard Disk, 001B=8" Drive, 010B=5.25" Drive, and 011B=3.5". Nothing is returned from this command. + +While all of these functions may not be supported on any specific computer type, the interface from using programs should always pass the necessary parameters for compatibility. + +**NOTE:** This routine assumes that SubFunction 2 (Set Head and Drive) has been called first. Call this routine before calling Function 0 (Set Mode). + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 2 | +|---:|:---| +| | **Set Head and Drive** | +| Enter: | A = Drive # (Bits 0,1), | +| | Head # (Bit 2) | +| | B = 1 (Floppy Driver) | +| | C = 2 (Subfunction #) | +| Exit: | None | +| Uses: | AF | + +This routine is entered with register A containing the Floppy unit number coded in bits 0 and 1 (Unit 0 = 00, 1 = 01 .. 3 = 11), and the Head in Bit 2 (0 = Head 0, 1 = Head 1). Nothing is returned from this function. Call this Subfunction before most of the others to minimize problems in Floppy accesses. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 3 | +|---:|:---| +| | **Set Floppy Disk Mode** | +| Enter: | A = Physical Sector Number | +| | D = Physical Sector Size | +| | E = Last Sctr # on Side | +| | B = 1 (Floppy Driver) | +| | C = 3 (Subfunction #) | +| Exit: | None | +| Uses: | AF | + +This routine establishes information needed to properly access a specified sector unambiguously with a number of different controller types. On entry, Register A contains the desired physical sector number desired, D contains the sector size where 0 = 128 byte sectors, 1 = 256 .. 3 = 1024 byte sectors, and E contains the last sector number on a side. Normally register E is unused in Western Digital controllers, but is needed with 765 and 9266 units. Nothing is returned from this subfunction. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 4 | +|---:|:---| +| | **Specify Drive Times** | +| Enter: | A = Step Rate in milliSec | +| | D = Head Unload Time in mS | +| | E = Head Load Time in mS | +| | B = 1 (Floppy Driver) | +| | C = 4 (Subfunction #) | +| Exit: | None | +| Uses: | AF | + +This subfunction set various timing values used for the physical drive selected. On entry, the A register contains the drive step rate in milliseconds. Within the Bios, this rate is rounded up to the nearest controller rate if the specified rate is not an even match. Register D should contain the desired Head Unload time in milliseconds, and E to the desired Head Load time in mS. + +NOTE: With Western Digital type controllers, only the Step Rate is universally variable. In these systems, rates signaled by the Bios settings are rounded up to the closest fixed step rate such as the 2, 3, 5, or 6 milliSecond rates in the WD1772 or 6, 10, 20, or 30 milliSecond rates used in the older WD1770 and WD1795. Nothing is returned from this function. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 5 | +|---:|:---| +| | **Home Disk Drive Heads** | +| Enter: | B = 1 (Floppy Driver) | +| | C = 5 (Subfunction #) | +| Exit: | A = 0, Zero Set (Z) if Ok | +| | A <> 0, NZ if Errors | +| Uses: | AF | +| **NOTE:** | Subfcns 1, 2, & 4 Needed | + +This subfunction moves the head(s) on the selected drive to track 0 (home). Only success/failure is indicated by the value in the A register. No other registers may be altered by this function (especially BC). + +**NOTE:** This function requires that Subfunctions 1 (Set Disk and Motor Parameters), 2 (Set Head and Drive) and 4 (Specify Drive Times) be called first in order to establish the physical characteristics of the Drive. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 6 | +|---:|:---| +| | **Seek Track** | +| Enter: | A = Desired Track Number | +| | D = 0FFH to Verify, | +| | 0 for No Verification | +| | E = 0 for No Double-Step | +| | <>0 for Double-Step | +| | B = 1 (Floppy Driver) | +| | C = 6 (Subfunction #) | +| Exit: | A = 0, Zero Set (Z) if Ok | +| | <> 0, NZ if Error | +| Uses: | AF | +| **NOTE:** | Subfcns 2, 3 & 4 Needed | + +This subfunction moves the head(s) for the selected drive to a specified track on the media. If the Double-Step flag (Register E) is set to a Non-Zero value, then the controller will issue two step pulses for every track increment or decrement which is required. After the Seek, a Read ID function will be performed to verify that the desired track was found if the Verification Flag (Register D) is set to a Non-Zero Number, preferably 0FFH. Only the AF registers may be altered by this function. + +**NOTE:** This function requires that Subfunctions 2 (Set Head and Drive), 3 (Set Floppy Disk Mode) and 4 (Specify Drive Times) be called first in order to establish the physical characteristics of the Drive. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 7 | +|---:|:---| +| | **Read Floppy Disk Sector** | +| Enter: | HL = Dest Buffer Address | +| | B = 1 (Floppy Driver) | +| | C = 7 (Subfunction #) | +| Exit: | A = 0, Zero Set (Z) if Ok | +| | <> 0, NZ if Error | +| Uses: | AF, HL | +| **NOTE:** | Subfcns 0, 1, 2, 4 & 6 Needed | + +This subfunction Reads a physical sector of data from the selected drive and places it in the buffer at the specified address. It is important that an appropriately sized buffer is provided for this task. The Value in the A register will indicate the success or failure of the function as indicated in the above chart. Only the AF and HL registers may be altered by this function. + +**NOTE:** This function requires that Subfunctions 0 (Set Read/Write Mode), 1 (Set Disk & Motor Parms), 2 (Set Head & Drive), 4 (Specify Drive Times) and 6 (Seek Track) be called first in order to establish the physical and logical characteristics of the data transfer. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 8 | +|---:|:---| +| | **Write Floppy Disk Sector** | +| Enter: | HL = Source Buffer Address | +| | B = 1 (Floppy Driver) | +| | C = 8 (Subfunction #) | +| Exit: | A = 0, Zero Set (Z) if Ok | +| | A <> 0, NZ if Error | +| Uses: | AF, HL | +| **NOTE:** | Subfcns 0, 1, 2, 4 & 6 Needed | + +This subfunction writes data from the buffer beginning at the specified address to the track, sector and head selected by other subfunctions. The value in the A register along with the setting of the Zero Flag will indicate whether the operation succeeded or not. Only the AF and HL registers may be altered by this function. + +**NOTE:** This function requires that Subfunctions 0 (Set Read/Write Mode), 1 (Set Disk & Motor Parms), 2 (Set Head & Drive), 4 (Specify Drive Times) and 6 (Seek Track) be called first in order to establish the physical and logical characteristics of the data transfer. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 9 | +|---:|:---| +| | **Read Disk Sector ID** | +| Enter: | B = 1 (Floppy Driver) | +| | C = 9 (Subfunction #) | +| Exit: | A = 0, Zero Set (Z) if Ok | +| | A <> 0, NZ if Error | +| Uses: | AF | +| **NOTE:** | Subfcns 0 & 2 Needed | + +This Subfunction reads the first correct ID information encountered on a track. There are no entry parameters for this function other than the Driver and Subfunction number. A flag is returned indicating whether or not errors occurred. An error indicates that no recognizable Sector ID could be read on the disk. In most cases, this is due to an incorrect Density setting in the Bios. + +**NOTE:** This function requires that Subfunctions 2 (Set Head & Drive) and 3 (Set Floppy Disk Mode) are called first in order to establish the physical characteristics of the disk. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 10 | +|---:|:---| +| | **Return Floppy Drive Status** | +| Enter: | B = 1 (Floppy Driver) | +| | C = 10 (Subfunction #) | +| Exit: | A = Status Byte of last Opn | +| | BC = FDC Controller Type | +| | HL = Address of Status Byte | +| Uses: | AF, BC, HL | +| **NOTE:** | Subfcn 2 Needed | + +This function returns the status of the currently-selected drive. There are no entry parameters for this function other than the Floppy Driver and Function number. On exit, the raw unmasked status byte of the drive, or the last operation depending on the controller type, is returned along with a binary number representing the FDC controller type (e.g. 765, 9266, 1772, etc). + +**NOTE:** This routine assumes that Subfunction 2 (Set Head & Drive) has been called before this routine to select the Physical Parameters. + + +| Function 31 (xx5D) | DIRDIO Floppy SubFunction 11 | +|---:|:---| +| | **Format Floppy Disk Track** | +| Enter: | HL = Pointer to Data Block | +| | D = # of Sectors/Track | +| | E = # of Bytes in Gap 3 | +| | B = 1 (Floppy Driver) | +| | C = 11 (Subfunction #) | +| Exit: | A = 0, Zero Set (Z) if Ok | +| | A <> 0, NZ if Error | +| Uses: | AF, BC, DE, HL | +| **NOTE:** | Use Subfcn 10 for Cont Type | + +This Sub function formats a complete track on one side of a Floppy Disk. It assumes that the Mode, Head/Drive, Track, and Sector have already been set. On entry, HL points to data required by the controller to format a track. This varies between controllers, so RETDST should be called to determine controller type before setting up data structures. On entry, D must also contain the number of Sectors per Track, and E must contain the number of bytes to use for Gap 3 in the floppy format. On exit, A=0 and the Zero flag is Set (Z) if the operation was satisfactorily completed, A <> 0 and the Zero flag cleared (NZ) if errors occurred. This routine may alter all primary registers (AF, BC, DE, HL). + +**NOTE:** This routine assumes that Subfunction 10 (Return Floppy Drive Status) has been called first to determine the Controller type and insert the correct information in the Format Data Block. + +----- + +### Function 31 - HARD DISK SUBFUNCTIONS + +These functions are available to directly access Hard Drives connected by a SCSI type interface. They are accessed by loading the desired function number in the C register, loading a 2 (SCSI driver) into the B register and calling or jumping to Jump number 31 in the Bios entry jump table. Since this interface is not as standardized as Floppy functions in order to handle SASI as well as SCSI devices, the interface has only basic functions with the precise operations specified by the User in the Command Descriptor Block passed with Function 2. While this places a greater burden on User programs, it allows more flexibility to take advantage of changing features in the newer SCSI drives. + + +| Function 31 (xx5D) | DIRDIO Hard Disk SubFunction 0 | +|---:|:---| +| | **Set Hard Disk Addresses** | +| Enter: | DE = Address of Data Area | +| | B = 2 (Hard Disk Driver) | +| | C = 0 (Subfunction #) | +| Exit: | A = # Bytes in Comnd Block | +| Uses: | AF | + +This Subfunction sets the User Data Area Address for Direct SCSI IO, and returns the number of bytes available in the SCSI Command Descriptor Block. The Data Area must be AT LEAST 512 bytes long and is used to store data to be written, and to receive data read from the selected drive. This Data Area size is mandatory since 512 bytes are always returned from a direct access in order to handle the wide variety of controller types recognized in the B/P Bios drivers. The number of bytes available in the Command Descriptor Block within the physical driver is usually 10 in order to handle the extended SCSI commands, but may be scaled back to 6 in limited applications. + + +| Function 31 (xx5D) | DIRDIO Hard Disk SubFunction 1 | +|---:|:---| +| | **Set Physical & Logical Drive** | +| Enter: | A = Device Byte (5.2.1) | +| | B = 2 (Hard Disk Driver) | +| | C = 1 (Subfunction #) | +| Exit: | A = Physical Device Bit | +| Uses: | AF | + +This Subfunction sets the Physical Device bit in the Bios for SCSI accesses and the Logical Unit Number in the SCSI Command Block (Byte 1, bits 7-5). The format of the Device Byte provided to this routine is defined in the Configuration Data, Section 5.2.1, CONFIG+61, and is available from the Extended Disk Parameter Header at DPH-1. On exiting this routine, a byte is returned with a "One" bit in the proper position (Bit 7 = Device 7...Bit 0 = Device 0) to select the desired unit via a SCSI command. + + +| Function 31 (xx5D) | DIRDIO Hard Disk SubFunction 2 | +|---:|:---| +| | **Direct SCSI Driver** | +| Enter: | DE = Ptr to Comnd Desc Blk | +| | A = 0 if No Write Data | +| | A = FF if Data to Write | +| | B = 2 (Hard Disk Driver) | +| | C = 2 (Subfunction #) | +| Exit: | A = Bit1 Status, Flags Set | +| | H= Message Byte Value | +| | L = Status Byte Value | +| Uses: | AF, BC, DE, HL | +| **NOTE:** | Subfcns 0 & 1 Needed | + +This Subfunction performs the actions required by the command in the specified Command Descriptor Block. The flag provided in Register A signifies whether or not user data is to be written by this command. If set to a Non-Zero value, Data from the area specified with Function 0 will be positioned for SCSI Write operations. At the end of the routine, 512 bytes are always transferred from the Bios IO Buffer to the Users Space set by Subfunction 0. This may be inefficient, but was the only way we could accommodate the wide variety of different SASI/SCSI controllers within reasonable code constraints. The status returned at completion of this function is the Status byte masked with the Check Bit, Bit 1. The full Status Byte and Message Byte from SCSI operations are also provided for more definition of any errors. + +**NOTE:** This routine assumes that the Command Descriptor Block has been properly configured for the type of Hard Disk Controller set in B/P Bios, and that the selected disk is properly described (if necessary) in the Bios Unit definitions. Errors in phasing result in program exit and Warm Boot. It assumes the user has called Functions 0 (Set Hard Disk Addresses) and 1 (Set Physical & Logical Drives) before using this Subfunction. + +---- + +## 5.2 Bios Data Structures + +### 5.2.1 Configuration Area + +Much of the ability to tailor B/P Bioses to your specific operating needs is due to the standardized location of many discrete elements of data, and a facility to easily locate and change them, regardless of the particular hardware platform in operation. Bios Function 30, Return Bios Addresses, reports the base address of the Configuration Area in the DE register pair. In this section, we will review each of the specified elements, their functions, and which parts of the data must be rigidly controlled to insure that the supplied utilities continue to function, as well as guarantee the portability of other programs. + + +| Offset (hex) | (dec) | Description | Data type | +| :---: | :---: | :--- | :--- | +| -0x06 / 0xFA | -6 | Bios ID | String, 6 bytes | +| +0x00 | +0 | IOBYTE | Byte | +| +0x02 | +2 | Bios Option Flags | Byte | +| +0x03 | +3 | User Bank | Byte | +| +0x04 | +4 | TPA Bank | Byte | +| +0x05 | +5 | SYStem Bank | Byte | +| +0x06 | +6 | RAM Drive Bank | Byte | +| +0x07 | +7 | Maximum Bank Number | Byte | +| +0x08 | +8 | Common Page Base | Byte | +| +0x09 | +9 | DPB Size | Byte | +| +0x0A | +10 | Number of DPBs in Common RAM | Byte | +| +0x0B | +11 | Number of DPBs in System Bank | Byte | +| +0x0C | +12 | Pointer to first Common DPB | Word | +| +0x0E | +14 | Pointer to first Banked DPB | Word | +| +0x10 | +16 | Initial Startup Command | String, 10 bytes | +| +0x1A | +26 | Pointer to Environment Descriptor | Word | +| +0x1C | +28 | Banked User Flag/Bank Number | Byte | +| +0x1D | +29 | Pointer to Start of Banked User Area | Word | +| +0x1F | +31 | CPU Clock Rate in Megahertz | Byte | +| +0x20 | +32 | Additional Wait State Requirements | Byte | +| +0x21 | +33 | Timer Reload Value | Word | +| +0x23 | +35 | Floppy Disk Physical Parameters | Table | +| +0x37 | +55 | Motor On Time in 1/10th Seconds | Byte | +| +0x38 | +56 | Motor Spinup Time in 1/10th Seconds | Byte | +| +0x39 | +57 | Maximum Number of Retries | Byte | +| +0x3A | +58 | Pointer to Interrupt Vector Table | Word | +| +0x3C | +60 | SCSI Controller Type | Byte | +| +0x3D | +61 | Hard Drive Physical Parameters | Table | +| +0x58 | +88 | (Reserved Bytes) | 5 Bytes | +| +0x5D | +93 | Character Device Definitions | Table | + + +`CONFIG-6` Bios ID (Character String, 6 bytes) + +This character string **MUST** begin with the three characters "B/P" in Uppercase Ascii, followed by three Version-specific identifying characters. As of March 1997, the following identifiers have been assigned to systems: + +| ID | Computer system | +| :---: | :--- | +| `"B/P-YS"` | YASBEC | +| `"B/P-AM"` | Ampro Little Board 100 | +| `"B/P-18"` | MicroMint SB-180 | +| `"B/P-CT"` | Compu/Time S100 Board Set | +| `"B/P-TT"` | Teletek | +| `"B/P-XL"` | Intelligent Computer Designs XL-M180 | +| `"B/P-DX"` | D-X Designs Pty Ltd P-112 | + + +`CONFIG+0` IOBYTE (Byte) + +This byte contains the initial definition of the byte placed at offset 3 on the Base Page (0003H) during a Cold Boot and determines which of the four defined character IO devices will be used as the Console, Auxiliary and Printer devices. The default setting may be altered by BPCNFG to reflect changed device configurations, or by reassembly of the Bios. The bit definitions in this byte are: + +```generic +Bit 7 6 5 4 3 2 1 0 + | | | | | | \------ Console Device + | | | | \---------- Auxiliary Input Device + | | \-------------- Auxiliary Output Device + \------------------ Printer Device +``` + +`CONFIG+2` Bios Option Flags (Byte) + +This byte consists of individually mapped bits which display which options are active in the assembled Bios. The bits listed as should not be defined without prior coordination with the system developers to preclude conflicts with planned enhancements. The byte is currently defined as: + +```generic +Bit 7 6 5 4 3 2 1 0 + | | | | | | | \---- 0 = Unbanked Bios 1 = Banked Bios + | | | | | | \------ 0 = Bank in RAM 1 = Bank in ROM + | | | | | \-------- 0 = DPBs Fixed 1 = DPBs Assignable + | | | | \---------- 0 = ALV/CSV in TPA 1 = ALV/CSV in Bank (ZSDOS2) + | \---------------- + \------------------ 0 = Not Locked 1 = Locked, Can't Reload +``` + +The next five bytes define the memory map of a banked system in 32k slices. For a complete description of Bank allocations, please refer to Section 4. In non-banked systems, all except the RAM Drive Bank should all be set to 0. If no memory is available for re-assignment as a RAM drive, this byte as well should be set to 0. + +`CONFIG+3` User Bank (Byte) + +This Byte reflects the Bank number reserved for User Applications. + +`CONFIG+4` TPA Bank (Byte) + +This Byte reflects the Bank number reserved for the Transient Program Area in the address range of 0..7FFFH. The next sequential bank number is normally the Common Bank which always remains in Context in the addressing range of 8000..FFFFH and contains the Operating System, Bios and Z-System tables. + +`CONFIG+5` SYStem Bank (Byte) + +This byte reflects the Bank number containing any executable code and data specified for the System Bank. + +`CONFIG+6` RAM Drive Bank (Byte) + +This byte reflects the starting Bank number available for use as a RAM Drive. It is assumed that all RAM from this Bank through the Maximum Bank Number is contiguous and available as a RAM Drive. + +`CONFIG+7` Maximum Bank Number (Byte) + +This byte reflects the number of the last available bank of RAM in the system. In many systems, it may be set to different numbers depending on the number of RAM chips installed in the system. + +`CONFIG+8` Common Page Base (Byte) + +This byte reflects the Base Page of the Common area in systems which do not fully comply with the 32k Memory Banking architecture of B/P Bios, but can be made somewhat compliant. This Byte must be AT LEAST 80H, but may be higher if needed. + +`CONFIG+9` DPB Size (Byte) + +This byte contains the length of Disk Parameter Block allocations within the Bios. Since more information is needed than the 15 bytes defined by Digital Research in CP/M 2.2, an extended format is used. All re-assignments of Disk Parameter data should use this byte to determine the size of records. + +`CONFIG+10` Number of DPBs in Common RAM (Byte) +`CONFIG+11` Number of DPBs in System Bank (Byte) + +These two bytes indicate the complete complement of Floppy Disk formats available within the Bios. In most cases, one of these two bytes will reflect a zero value with all Disk Parameter Blocks resident either in the Common area or in the System Bank. The provisions are available, however with these two bytes to split the definitions for custom versions without voiding the support tools provided. + +`CONFIG+12` Pointer to first Common DPB (Word) +`CONFIG+14` Pointer to first Banked DPB (Word) + +These two words point to the first DPB in a sequential list within the respective memory banks for Disk Parameter Blocks defined in the preceding bytes. In most cases one of these two words will be a Null pointer (0000H) corresponding to no data as described in the count bytes above. + +`CONFIG+16` Initial Startup Command (String, 10 Bytes) + +This string contains the first command which will be initiated on a Cold Boot. It is loaded into the Multiple Command Buffer defined in the Environment Descriptor (See 5.2.4) and calls a file of the specified name with a type of "COM". The string may have up to eight characters and must be Null-terminated (end with a Binary 0). The string is defined as: + +| | Initial Startup Command String | +| :---: | :--- | +| Byte | Number of Characters (0..8) | +| String | 8 bytes for Ascii characters (usually Uppercase) | +| Byte | Terminating Null (binary 0) | + +`CONFIG+26` Pointer to Environment Descriptor (Word) + +This Word points to the first byte of an extended Z34 Environment which **MUST** begin on a Page boundary (xx00H). See Section 5.3.1 for a complete description of the Environment Descriptor and B/P Bios unique features. + +`CONFIG+28` Banked User Flag/Bank Number (Byte) + +This Byte may be used as a flag to indicate whether or not a User Bank is defined. Bank 0 cannot be used as a User bank by decree of the system authors. Therefore, if this byte contains a binary 0, no User Bank is available. + +`CONFIG+29` Pointer to Start of Banked User Area (Word) + +This word contains the address of the first available byte in the Banked User Area, if one exists. Routines loaded into the User Bank should contain a standard RSX header structure to link sequential programs and provide a primitive memory management function. + +`CONFIG+31` CPU Clock Rate in Megahertz (Byte) + +This byte must contain the processor speed rounded to the nearest Megahertz. It may be used by software timing loops in application and utility programs to adapt to the clock speed of the host computer and provide an approximate time. This byte is reflected in the Environment Descriptor (see 5.2.4) as well for programs which are Z-System "aware". + +`CONFIG+32` Additional Wait State Requirements (Byte, nybble-mapped) + +This byte is "nybble-mapped" to reflect the number of wait states needed for memory and IO accesses when these functions can be set via software. In the Z80/Z180, IO port accesses have one wait state inserted within the processor. This byte does not account for this fact, and reflects wait states **IN ADDITION TO** any which are built into the hardware. For older processors such as the Z80, these bytes normally have no effect since additional wait states must be added with hardware. + +`CONFIG+33` Timer Reload Value (Word) + +In many systems, Interrupts or Timer values are set by software-configurable countdown timers. the 16-bit value at this location is reserved for setting the timer value and may be "fine tuned" to allow the system to maintain correct time in the presence of clock frequencies which may deviate from precise frequencies needed for accurate clocks. + +`CONFIG+35` Floppy Disk Physical Parameters (Table) + +This table consists of four 5-byte entries which contain information on up to four physical drives. Each entry is defined as: + +| Byte | Description | +| :---: | :--- | +| 0 | Provides base for XDPH byte, _see bit mapping below_ | +| 1 | Step Rate in milliseconds | +| 2 | Head Load Time in milliseconds | +| 3 | Head Unload Time in milliseconds | +| 4 | Number of Tracks (Cylinders) on drive | + +```generic +XDPH Base +Bit 7 6 5 4 3 2 1 0 + | | | | | \-------- Disk Size 000=Fixed Disk, 001=8", 010=5.25", 011=3.5" + | | | | \---------- 0 = Single-Sided, 1 = Double-Sided + | | | \------------ + | | \-------------- 0 = Motor Always On 1 = Motor Control Needed + | \---------------- 0 = 300 RPM Max Speed 1 = 360 RPM (8" & HD) + \------------------ +``` +Those bits in Byte 0 which are listed as unused must be set to 0 since this byte provides the initial value stored in the XDPH when assignable drives are used. For controllers which do not need the available information (e.g. Western Digital controllers do not need Byte 3), these values may be set to any arbitrary value, but **MUST** remain present in the structure to prevent changing subsequent addresses. + +`CONFIG+55` Motor On Time in 1/10th Seconds (Byte) + +This time may be used in some types of Floppy Disk controllers to keep the drive motors spinning for a specified time after the last access to avoid delays in bringing the spindle up to speed. Some controllers, notably the Western Digital 17xx and 19xx series to not support this feature. In this case, the byte may be set to any arbitrary value, but **MUST** remain present. + +`CONFIG+56` Motor Spinup Time in 1/10th Seconds (Byte) + +This time is the delay which will be imposed by the Bios before attempting to access a Floppy Disk drive when it senses that the motor is in a stopped condition. Providing such a delay will minimize the probability of data corruption by writing to disk which is rotating at the incorrect speed. + +`CONFIG+57` Maximum Number of Retries (Byte) + +This byte specifies the number of attempts which will be made on a Floppy Disk access before returning an error code. In some cases, such as diagnostic programs, it may be desirable to set this value to 1 to identify soft errors, or ones which fail on the first attempt, but succeed on a subsequent try. We recommend a value of 3 or 4 based on our experience. Larger values may result in inordinately long delays when errors are detected. + +`CONFIG+58` Pointer to Interrupt Vector Table (Word) + +This Word contains the address of the base of an Interrupt Vector Table which, when used, contains pointers to service routines. The precise definition of the table is not standardized and may vary considerably between systems. This pointer serves only to provide an easy and standardized method of locating the table for re-definition of services or system features. + +`CONFIG+60` SCSI Controller Type (Byte) + +To accommodate the widest variety of different controllers including the older SASI models, this byte is defined as containing a byte code to the specific model being used. In most cases, this byte has little if any effect within the Bios, but may have significant effects on Hard Disk Diagnostic programs, or User-developed utilities. Any additions to this table should be coordinated with the authors to insure that the standard support utilities continue to function. Current definitions are: + +| ID | Controller type | +| :---: | :--- | +| 0 | Owl | +| 1 | Adaptec ACB-4000A | +| 2 | Xebec 1410A/Shugart 1610-3 (SASI) | +| 3 | Seagate SCSI | +| 4 | Shugart 1610-4 (Minimal SCSI subset) | +| 5 | Conner SCSI | +| 6 | Quantum SCSI | +| 7 | Maxtor SCSI | +| 8 | Syquest SCSI | +| 9 | GIDE (IDE/ATA) | + +`CONFIG+61` Hard Drive Physical Parameters (Table) + +This table consists of three 9-byte entries defining up to three physical Hard Drives. While the SCSI definition allows for more units, three was considered adequate for most systems. If additional drives are needed, please contact the authors for methods of including them without invalidating any of the standard utilities or interfaces. Each of the three entries is defined as: + +| Entry | Description | +| :--- | :--- | +| Byte | Physical and Logical Address, _see bit mapping below_ | +| Word | Number of Physical Cylinders on Drive | +| Byte | Number of Usable Physical Heads on Drive | +| Word | Cylinder Number to begin Reduced Write Current | +| Word | Cylinder Number to begin Write Precompensation | +| Byte | Step Rate. This byte may either be an absolute rate in mS or a code based on controller-specific definitions | + +```generic +Physical and Logical Address + Bit 7 6 5 4 3 2 1 0 + | | | | | \-------- Physical Device (000-110B, 111B reserved for Host) + | | | | \---------- + | | | \------------ 0 = Drive NOT Present, 1 = Drive Present + \------------------ Logical Unit Number (000-111B) for controllers +``` + +For many of the newer controllers, the last three items may not have any meaning in which case they can be set to any arbitrary value. Also in newer drives, the physical characteristics such as the number of cylinders and heads may be hidden within the drive electronics with re-mapped values provided to the controller via various SCSI commands. As with the last three entries, in this case, they may be set to any arbitrary value. + +`CONFIG+88` Reserved (5 Bytes) + +Five Bytes are reserved for future expansion. + +`CONFIG+93` Character Device Definitions (Table) + +This table consists of four or more 16-byte (8-byte in B/P versions prior to 1.1) entries and must be terminated by a Null (binary Zero) byte. Each entry defines the name and characteristics of a character device in the system. The first four of these are directly available for selection by the IOBYTE as the Console, Auxiliary IO and Printer. Other entries may be defined and exchanged with the first four to make them accessible to the system. The entries are defined as: + +| Entry | Description | +| :---: | :--- | +| String | Four Ascii character Name as: COM1, PIO1, NULL, etc. | +| Byte | Data Rate capabilities, _see bit mapping below_ | +| Byte | Configuration Byte, _see bit mapping below_ | +| Byte | Input Data Mask | +| | Bit-mapped byte used to logically AND with bytes read from Device Input | +| Byte | Output Data Mask | +| | Bit-mapped byte used to logically AND with bytes before being output to device | +| Word | Pointer to Character Output routine | +| Word | Pointer to Output Status routine | +| Word | Pointer to Character Input routine | +| Word | Pointer to Input Status routine | + +**NOTE:** The last four pointers are not at these locations in B/P Bios versions prior to 1.1, but were accessed by a pointer returned by Bios Function 30. + +```generic +Data Rate capabilities +Bit 7 6 5 4 3 2 1 0 + | | | | \---------- Current Data Rate Setting + \------------------ Maximum Rate Available (Bits-per-Second) as: + 0000 = None 0001 = 134.5 0010 = 50 0011 = 75 + 0100 = 150 0101 = 300 0110 = 600 0111 = 1200 + 1000 = 2400 1001 = 4800 1010 = 9600 1011 = 19200 + 1100 = 38400 1101 = 76800 1110 = 115200 1111 = Fixed +``` + +```generic +Configuration Byte +Bit 7 6 5 4 3 2 1 0 + | | | | | | | \---- 0 = 2 Stop Bits, 1 = 1 Stop Bit + | | | | | | \------ 0 = No Parity, 1 = Parity Enabled + | | | | | \-------- 0 = Odd Parity, 1 = Even Parity + | | | | \---------- 0 = 8-bit Data, 1 = 7-bit Data + | | | \------------ 0 = No XON/XOFF, 1 = XON/XOFF Control Enabled + | | \-------------- 0 = No CTS/RTS, 1 = CTS/RTS Control Enabled + | \---------------- 0 = Device NOT Input, 1 = Device can be read + \------------------ 0 = Device NOT Output, 1 = Can Write Device +``` + + +### 5.2.2 Disk Parameter Header + +The Disk Parameter Header (DPH) is a logical data structure required for each disk drive in a CP/M compatible Disk Operating System. It consists of a series of eight pointers which contain addresses of other items needed by the DOS as well as some scratchpad space. The Address of the DPH associated with a given drive is returned by the Bios after a successful selection with Bios Function 9. If Errors occur during selection, or the drive does not exist, a Null Pointer (0000H) is returned. + +For B/P Bios, it was necessary to add an additional four bytes to each DPH which contain additional information on physical and logical parameters as well as flag information. These additional bytes are referred to as the Extended DPH, or XDPH. While similar in concept to the extension added to CP/M 3, the implementation is different. The XDPH prepends the DPH and may be accessed by decrementing the returned address. As a convention, DPHs in B/P Bios source code have reserved certain label sequences for specific types of units with DPH00-DPH49 used for Floppy Drives, DPH50-DPH89 for Hard Drive Partitions and DPH90-DPH99 for RAM Drives. + +An entire DPH/XDPH block is required for each logical drive in a B/P Bios system. While some pointers, such as the pointer to the Directory Buffer, may be common across a number of drives, for most systems, the other items will point to unique areas. + + +| Offset (hex) | (dec) | Description | Data type | +| :---: | :---: | :--- | :--- | +| -0x04 / 0xFC| -4 | Format Lock Flag | Byte | +| -0x03 / 0xFD | -3 | Disk Drive Type | Byte | +| -0x02 / 0xFE | -2 | Driver ID Number | Byte | +| -0x01 / 0xFF | -1 | Physical Drive/Unit Number | Byte | +| +0x00 | +0 | Skew Table Pointer | Word | +| +0x02 | +2 | Dos Scratch Area | 3 Words | +| +0x08 | +8 | Directory Buffer Pointer | Word | +| +0x0A | +10 | DPB Pointer | Word | +| +0x0C | +12 | Disk Checksum Buffer | Word | +| +0x0E | +14 | Allocation Vector (ALV) Buffer | Word | + + +The DPH/XDPH elements as indexed from the DPH addresses accessible to application programs are: + +`DPH-4` Format Lock Flag (Byte) + +A Zero value indicates that the format of the disk is not fixed, but may be changed. If the Bios was assembled with the Auto-select option, the Bios will scan a number of different formats in order to identify the disk. If a 0FFH value is placed in this byte, it indicates that the format is fixed and cannot be changed. This is normally the case for RAM and Hard disk drives, as well as for alien floppy formats which have been selected in the emulation mode. If the Auto-select option was not chosen during assembly of the Bios, all Floppy Disk drives will also have a 0FFH byte in this position showing that the formats cannot be changed. + + +`DPH-3` Disk Drive Type (Byte) + +This byte is bit mapped and contains flags indicating many parameters of the drive. For Floppy Drives, this byte contains a copy of the first byte in the Physical Drive Table (See 5.2.1, CONFIG+35) with the two reserved bytes set during the drive selection process. The byte is then defined as: + +```generic +Bit 7 6 5 4 3 2 1 0 + | | | | | \-------- Disk Size 000=Fixed Disk, 001=8", 010=5.25", 011=3.5" + | | | | \---------- 0 = Single Sided 1 = Double Sided + | | | \------------ 0 = Single Step Drive 1 = Double Step Drive + | | \-------------- 0 = Motor Always On 1 = Drive Motor Control Needed + | \---------------- 0 = Max Speed 5.25" (300 rpm) 1 = 8" & HD Max Speed (360 rpm) + \------------------ 0 = Double Density 1 = Single Density +``` + +For Hard Disk Partitions and the RAM Drive, this byte is not used and is set to all Zeros indicating a Fixed Drive type. + +`DPH-2` Driver ID Number (Byte) + +Three Driver Types are used in the basic B/P Bios configuration. A Zero value indicates a Non-existent driver, with other values used to direct disk accesses to the respective code appropriate to the device. Basic defined driver types exist for Floppy Disk (1), Hard Disk via the SCSI interface (2), and RAM Disk (3). If you wish to extend this table to include tailored drivers, please consult with the authors to preclude possible conflicts with planned extensions. + +`DPH-1` Physical Drive/Unit Number (Byte) + +This byte contains the Physical Drive or Unit Number hosting the logical drive. For Floppy Drives, this will usually be in the range of 0 to 3 for four drives. Hard drives may have several DPHs sharing the same physical drive number, while this field is ignored in the single RAM drive supported in the distribution B/P Bios version. + +**NOTE:** The Physical Drive Number byte for Hard Drives is comprised of two fields to ease handling of SCSI devices. Up to seven devices (device 111B is reserved for the Host Computer) each having up to 8 Logical Units may be defined. The Byte is configured as: + +```generic +Bit 7 6 5 4 3 2 1 0 + | | | | | \-------- Physical Device (000-110B, 111B reserved for Host) + | | | | \---------- + | | | \------------ 0 = Unit Not Available, 1 = Unit Active + \------------------ Logical Unit Number (000-111B) +``` + +`DPH+0` Skew Table Pointer (Word) + +This word contains a pointer to the Skew table indicator. It rarely is used for Hard and RAM drives, but is required in Floppy Disk drives. If the Bios was assembled using the Calculated Skew option, the address is of a Byte whose absolute value indicates the numerical value of skew (normally in the range of 1 to 6) used for disk accesses. This term is often replaced with Interleave, and is synonymous for this purpose. If the value of the byte is negative, it means that the sectors are recorded in a skewed form on the disk and that Reads and Writes should be sequential. If the value is positive, then an algorithm is called to compute a physical sector number based on the desired logical sector and the skew factor. For systems assembled without Calculated skew, this word points to a table of up to 26 bytes which must be indexed with the desired Physical Sector number (0..Maximum Sector Number) to obtain the corresponding Disk Sector number. + +`DPH+2` Dos Scratch Area (3 Words) + +These three words are available for the Dos to use as it requires. No fixed values are assigned, nor are meanings for the data stored there of any value. + +`DPH+8` Directory Buffer Pointer (Word) + +This word points to a 128-byte Data area that is used for Directory searches. It is usually a common area to all DPH's in a system and is frequently updated by the Dos in normal use. + +`DPH+10` DPB Pointer (Word) + +This word points to another data structure which details many of the logical parameters of the selected drive or partition. Its structure is detailed in Section 5.2.3 below. Drives of the same type and logical configuration may share DPB definitions, so it is not uncommon to find the DPB pointers in different DPH structures pointing to the same area. + +`DPH+12` Disk Checksum Buffer (Word) + +This word points to a scratch RAM buffer area for removable-media drives used to detect disk changes. Normally this feature is used only for Floppy Disk Drives, and is disabled by containing a Zero word (0000H) for Hard and RAM drives. For Floppy Drives, a RAM area with one byte for every four directory entries (128-byte sector) is needed (See 5.2.3, DPH+11/12). This scratch area cannot be shared among drives. + +It should be noted that in a fully Banked B/P Bios system with ZSDOS2, the Checksum Buffer is placed in the System Bank and not directly accessible by applications programs. + +`DPH+14` Allocation Vector (ALV) Buffer (Word) + +This word points to a bit-mapped buffer containing one bit for each allocation block on the subject drive (See 5.2.3, DPB+5/6). A "1" bit in this buffer means that the corresponding block of data on the device is already allocated to a file, while a "0" means that the block is free. This buffer is unique to each logical drive and cannot be shared among drives. + +It should be noted that in a fully Banked B/P Bios system with ZSDOS2, the ALV Buffer is placed in the System Bank and not directly accessible by applications programs. Since access to the ALV buffer is frequently needed to compute free space on drives, ZSDOS2 contains an added function to return disk free space. Using this call allows applications access to the information without directly accessing the data structure. + + +### 5.2.3 Disk Parameter Block + +The Disk Parameter Block (DPB) is a data structure defined by Digital Research for CP/M which defines the logical configuration of storage on mass storage. It has been expanded in B/P Bios to include additional information to provide enhanced flexibility and capability. The expansion is referred to as the Extended DPB or XDPB, and prepends the actual DPB structure. The address of the DPB may be obtained from the DPH pointer returned by the Bios or Dos after a disk selection (See 5.2.2 above). All DPBs reside in the Common Memory area and are available to applications programs whether in a Banked or Unbanked system. For the sake of a convention, the DPBs are labeled in the same manner as DPHs with DPB00-DPB49 used for Floppy Drives, DPB50-DPB89 for Hard Drive Partitions, and DPB90-99 for RAM Drives. + + +| Offset (hex) | (dec) | Description | Data type | +| :---: | :---: | :--- | :--- | +| -0x10 / 0xEA | -16 | Ascii ID String | 10 Bytes | +| -0x06 / 0xFA | -6 | Format Type Byte 0 | Byte | +| -0x05 / 0xFB | -5 | Format Type Byte 1 | Byte | +| -0x04 / 0xFC | -4 | Skew Factor | Byte | +| -0x03 / 0xFD | -3 | Starting Sector Number | Byte | +| -0x02 / 0xFE | -2 | Physical Sectors per Track | Byte | +| -0x01 / 0xFF | -1 | Physical Tracks per Side | Byte | +| +0x00 | +0 | Sectors per Track | Word | +| +0x02 | +2 | Block Shift Factor | Byte | +| +0x03 | +3 | Block Mask | Byte | +| +0x04 | +4 | Extent Mask | Byte | +| +0x05 | +5 | Disk Size (Capacity) | Word | +| +0x07 | +7 | Maximum Directory Entry | Word | +| +0x09 | +9 | Allocations 0 and 1 | Word | +| +0x0B | +11 | Check Size | Word | +| +0x0D | +13 | Track Offset | Word | + + +The layout of the Disk Parameter Block as indexed from the available DPB pointer is: + +`DPB-16` Ascii ID String (10 Bytes) + +This string serves as an identification which may be printed by applications programs such as our BPFORMAT. This string may be a mixed alphanumeric Ascii set of up to ten characters, but the last valid character must have the Most Significant Bit (Bit 7) Set to a "1". + +`DPB-6` Format Type Byte 0 (Byte) + +This byte contains some of the information about the format of the drive, and the logical sequencing of information on the physical medium. The bits in the byte have the following significance: + +```generic +Bit 7 6 5 4 3 2 1 0 + | | | | | \-------- Disk Size: 000 = Fixed Disk, 001 = 8", 010 = 5.25", 011 = 3.5" + | | \-------------- Track Type + | | 000 = Single Side 001 = Reserved + | | 010 = Sel by Sec, Cont 011 = Sel by Sec, Sec # Same + | | 100 = S0 All, S1 All 101 = S0 All,S1 All Reverse + | | 110 = Sel by Trk LSB 111 = Reserved + | \---------------- 0 = Track 0 Side 0 is Double Density, 1 = Single Density + \------------------ 0 = Data Tracks are Double Density, 1 = Single Density +``` + +For Hard Drives and RAM Drives, this byte contains all Zero bits to signify Fixed Media and format. + +`DPB-5` Format Type Byte 1 (Byte) + +This byte contains additional information about the format of information. The bits have the following meanings: + +```generic +Bit 7 6 5 4 3 2 1 0 + | | | | | \--------- Sector Size: 000 = 128, 001 = 256, 010 = 512, 011 = 1024 + | | \--------------- Allocation Size: 000=1K, 001=2K, 010=4K, 011=8K, 100=16K + | | (NOTE: This should match the definition in DPH) + | \----------------- + \------------------- 0 = Normal Speed (300 rpm) + 1 = 8" & HD Floppy (360 rpm) or Hard Drive +``` + +For Hard Drives, The distribution version of B/P Bios and the support utilities assume that the Sector size is always 512 bytes. The remaining bits should be set as indicated. + +`DPB-4` Skew Factor (Byte) + +This byte is a signed binary value indicating the skew factor to be used during Format, Read and Write. It is normally used only with Floppy Drives and usually set to -1 (0FFH) for Hard and RAM drives to indicate that Reads and Writes should be done with No skew. If the option to calculate skew is in effect during Bios assembly, the Skew pointer in the DPH (BPH+0/1) points to this byte. If a skew table is used, this byte has no effect and should be set to 80H. + +`DPB-3` Starting Sector Number (Byte) + +This byte contains the number of the first Physical Sector on each track. Since most Disk Operating Systems use a Zero-based sequential scheme to reference sectors, this value provides the initial offset to correct logical to physical sector numbers. + +`DPB-2` Physical Sectors per Track (Byte) + +This byte contains the number of Physical (as opposed to logical) Sectors on each track. For example, CP/M computes sectors based on 128-byte allocations which are used on single-density 8" Floppy Disks. One of the popular five- inch formats uses five 1k physical sectors which equates to 40 logical CP/M sectors. This byte contains 5 in this instance for the number of 1k Physical Sectors. + +`DPB-1` Physical Tracks per Side (Byte) + +This byte contains the number of Physical Tracks per Side, also called the Number of Cylinders. It reflects the Disk, as opposed to the Drive capabilities and is used to establish the requirements for double-stepping of Floppy Drives. In the case of a 40-track disk placed in an 80-track drive, this byte would contain 40, while the Drive parameter in the Configuration Section contains 80 as the number of tracks on the drive. This byte has no meaning for Hard Drive partitions or RAM drives and should be set to Zero, although any arbitrary value is acceptable. + +`DPB+0` Physical Tracks per Side (Word) + +This value is the number of Logical 128-byte sectors on each data track of the disk. It is equivalent to the number of Physical Sectors times the Physical Sector Size MOD 128. + +`DPB+2` Block Shift Factor (Byte) +`DPB+3` Block Mask (Byte) +`DPB+4` Extent Mask (Byte) + +These three bytes contain values used by the Operating System to compute Tracks and Sectors for accessing logical drives. Their values are detailed in various references on CP/M and ZSDOS programming and should not be varied without knowledge of their effects. + +`DPB+5` Disk Size / Capacity (Word) + +This Word contains the number of the last allocation block on the drive. It is the same as the capacity in allocation blocks - 1. For example, if 4k allocation blocks are being used and a 10 Megabyte drive is being defined, this word would contain 10,000,000/4000 - 1 or 2499. + +`DPB+7` Maximum Directory Entry (Word) + +This Word contains the number of the last Directory Entry and is the same as the Number of Entries - 1. For example, if 1024 directories are desired, this word would be set to 1024 - 1 = 1023. + +`DPB+9` Allocations 0 and 1 (2 Bytes) + +These two Bytes hold the initial allocations stored in the first two bytes of the ALV Buffer (See 5.2.2, DPH+14/15) during initial drive selection. Their primary use is to indicate that the Directory Sectors are already allocated and unavailable for data storage. They are bit-mapped values and are used in Hi-byte, Lo-byte form as opposed to the normally used Lo-byte, Hi-byte storage used in Z80 type CPUs for Word storage. The bits are allocated from the MSB of the first byte thru the LSB, then MSB thru LSB of the second byte based on one bit per allocation block or fraction thereof used by the Directory. The bits may be calculated by first computing the number of entries per allocation block, then dividing the desired number of entries by this number. Any remainder requires an additional allocation bit. + +For example, if 4k allocation blocks are used, each block is capable of 4096/32 bytes per entry = 128 Directory Entries. If 512 entries are desired, then 512/128 = 4 allocation blocks are needed which dictates that Allocation byte 0 would be 11110000B (0F0H) and Allocation Byte 1 would be 00000000B. + +`DPB+11` Check Size (Word) + +This Word is only used in removable media (normally only Floppy Drives) and indicates the number of sectors on which to compute checksums to detect changed disks. It should be set to 0000H for Fixed and RAM Disks to avoid the time penalty of relogging after each warm boot. + +`DPB+13` Track Offset (Word) + +This Word indicates the number of Logical Tracks to skip before the present DPB is effective. It is normally used to reserve boot tracks (usually 1 to 3), or to partition larger drives into smaller logical units by skipping tracks used for other drive definitions. + + +### 5.3.1 Environment Descriptor + +The Environment Descriptor, referred to as simply the ENV, is the heart of what is now known as The Z-System. The most recent additions to the system by Joe Wright and Jay Sage replaced some relatively meaningless elements in the ENV with system dependent information such as the location of the Operating System components. Consequently, the ENV is not just a feature of the ZCPR 3.4 Command Processor Replacement, but is an Operating System Resource which allows other programs such as ZCPR 3.4 to access its information. + +The B/P Bios requires an ENV to be present, and uses several items of information contained in it. The banked ZSDOS2 and Z40 Command Processor Replacement use even more ENV features. A few remaining bytes have been re-defined for support to B/P Bios-based systems. To denote the definition of B/P Bios data elements, a new Type, 90H, has been reserved. Using this "Type" byte, user programs can access and take advantage of the new definitions and features. + +A template for the Environment Descriptor used in B/P Bios which takes its values from the Z3BASE.LIB file included in the distribution disk is: + + +### 5.3.2 Terminal Capabilities + +In addition to the Basic Environment Descriptor described above, a dummy Terminal Capability record structure (TCAP, also known as TERMCAP) is attached to reserve space for, and define default capabilities of the computer terminal. The default TERMCAP is fully compliant with the VLIB routines used in the Z-System Community after VLIB4D. The skeleton record structure is: + + +## 5.4 ZSDOS2 Function Reference + +| Number | Fcn Name | Input Parameters | Returned Values | +|:------:|:---------|:---------------------|:------------------------| +| 0 | Boot | None | None | +| 1 | Console Input | None | A=Character | +| 2 | Console Output | E=Character | A=00H | +| 3 | Reader Input | None | A=Character | +| 4 | Punch Output | E=Character | A=00H | +| 5 | List Output | E=Character | A=00H | +| 6 | Direct Console I/O | E=0FFH (In) | A=Input Character | +| | | E=0FEH (In) | A=Console Status | +| | | E=0FDH (In) | A=Input Character | +| | | E=00H..0FCH (Out) | A=00H | +| 7 | Get I/O Byte | None | A=I/O Byte (0003H) | +| 8 | Set I/O Byte | E=I/O Byte | A=00H | +| 9 | Print String | DE=Address String | A=00H | +| 10 | Read Console Buffer | DE=Address Buffer | A=00H | +| 11 | Get Console Status | None | A=00H = No character | +| | | | A=01H = Char. present | +| 12 | Get Version Number | None | A=Version Number (22H) | +| 13 | Reset Disk System | None | A=00H No $*.* on A | +| | | | A=FFH $*.* on A | +| 14 | Select Disk | E=Disk Number | A=00H No $*.* File | +| | | | A=FFH $*.* File | +| 15 | Open File | DE=Address of FCB | A=Directory Code | +| 16 | Close File | DE=Address of FCB | A=Directory Code | +| 17 | Search for First | DE=Address of FCB | A=Directory Code | +| 18 | Search for Next | DE=Address of FCB | A=Directory Code | +| 19 | Delete File | DE=Address of FCB | A=Error Code | +| 20 | Read Sequential | DE=Address of FCB | A=Read/Write Code | +| 21 | Write Sequential | DE=Address of FCB | A=Read/Write Code | +| 22 | Make File | DE=Address of FCB | A=Directory Code | +| 23 | Rename File | DE=Address of FCB | A=Error Code | +| 24 | Get Login Vector | None | HL=Login Vector | +| 25 | Get Current Disk | None | A=Current Disk | +| 26 | Set DMA Address | DE=DMA Address | A=00H | +| 27 | Get Alloc. Address | None | HL=Addr Alloc Vector | +| 28 | Write Protect Disk | None | A=00H | +| 29 | Get R/O Vector | None | HL=R/O Vector | +| 30 | Set File Attributes | DE=Address FCB | A=Error Code | +| 31 | Get DPB Address | None | HL=Address of DPB | +| 32 | Set/Get User Code | E=FFH (Get) | A=User Number | +| | | E=User Number (Set) | A=00H |< +| 33 | Read Random | DE=Address of FCB | A=Read/Write Code | +| 34 | Write Random | DE=Address of FCB | A=Read/Write Code | +| 35 | Compute File Size | DE=Address of FCB | A=Error Code | +| 36 | Set Random Record | DE=Address of FCB | A=00H | +| 37 | Reset Mult Drive | DE=Mask | A=00H | +| 38 | Not Implemented | | | +| 39 | Get fixed disk vector | None | HL=Fixed Disk Vector | +| 40 | Write random, 00 fill | DE=Addr of FCB | A=Read/Write Code | +| 41-44 | Not Implemented | | | +| 45 | Set error mode | E=FFH (Get) | A=00H | +| | | E=FEH (Get Err/Disp) | A=00H | +| | | E=01H (Set ZSDOS) | A=00H | +| | | E=00H (Set CP/M) | A=00H | +| 46 | Return Free Space | E=Disk Number | A=Error Code | +| | | | Space in DMA+0..DMA+3 | +| 47 | Get DMA address | None | HL=Current DMA Address | +| 48 | Get DOS & version | None | H=DOS type: "S"=ZSDOS, "D"=ZDDOS | +| | | | L=BCD Version Number | +| 49 | Return ENV Address | None | HL=Env. Descriptor Addr | +| 50-97 | Not Implemented | | | +| 98 | Get time | DE=Address to Put Time | A=Time/Date Code | +| 99 | Set time | DE=Address of Time | A=Time/Date Code | +| 100 | Get flags | None | HL=Flags | +| 101 | Set flags | DE=Flags | None | +| 102 | Get file stamp | DE=Addr of FCB | A=Time/Date Code, | +| | | | Stamp in DMA Buffer | +| 103 | Set file stamp | DE=FCB Address, | A=Time/Date Code | +| | | Stamp in DMA Buffer | | +| 104-151 | Not Implemented | | | +| 152 | Parse FileSpec | DE=FCB Address, | A=No. of "?"s in Fn.Ft | +| | | String in DMA Buffer | DE=Addr of delimit chr | +| | | | FCB+15=0 if Parse Ok, 0FFH if Error(s) | +| 153-255 | Not Implemented | | | + + +| BDOS Codes | | +| :--- | :--- | +| Directory Codes: | A=00H, 01H, 02H, 03H if No Error | +| | A=FFH if Error | +| Error Codes: | A=00H if No Error | +| | A=0FFH if error | +| Time/Date Codes: | A=01H if No error | +| | A=0FFH if error | +| Read/Write Codes: | A=00H if No error | +| | A=01H Read - End of File / Write - Directory Full | +| | A=02H Disk Full | +| | A=03H Close Error in Random Record Read/Write | +| | A=04H Read Empty Record during Random Record Read | +| | A=05H Directory Full during Random Record Write | +| | A=06H Record too big during Random Record Read/Write | +| Extended Error codes | A=0FFH Extended Error Flag | +| in Return Error Mode: | H=01H Disk I/O Error (Bad Sector) | +| | H=02H Read Only Disk | +| | H=03H Write Protected File | +| | H=04H Invalid Drive (Select) | + + +## 5.5 Datespec and File Stamp Formats + +The universal stamp and time formats used by ZSDOS are based on packed BCD digits. It was decided that these were the easiest format for Z80 applications programs to work with, and were compatible with most real time clocks. The format for the stamps and for the clock functions are identical to the Plu*Perfect DateStamper's formats for these functions. + +Some file stamping formats (for example CP/M Plus type) do not store all the information present in the universal format to disk. In the case of CP/M Plus type stamps, there is no provision for stamping the Last Access time. The ZSDOS interface routines fill unimplemented fields in the stamp with 0 when the Get Stamp function is used, and ignore the contents of the unused fields when the Put Stamp function is used. + +Depending on the stamping method selected, the format of the stamps on the disk may differ from the universal format. These differences are effectively hidden from users by ZSDOS and the Stamp routines so long as ZSDOS's functions are used to get or manipulate the stamps. + +Time format (6 bytes packed BCD): + +| Byte | Description | +| :---: | :--- | +| `TIME+0` | last 2 digits of year | +| | (prefix 19 assumed for 78 to 99, else 20 assumed) | +| `TIME+1` | month [1..12] | +| `TIME+2` | day [1..31] | +| `TIME+3` | hour [0..23] | +| `TIME+4` | minute [0..59] | +| `TIME+5` | second [0..59] | + +File Stamp format (15 bytes packed BCD): + +| Location | Description | +| :---: | :--- | +| `DMA+0 ` | Create field (first 5 bytes of time format) | +| `DMA+5 ` | Access field (first 5 bytes of time format) | +| `DMA+10` | Modify field (first 5 bytes of time format) | diff --git a/Doc/CPM/BPBIOS/BPBIOS_6_Utilities.md b/Doc/CPM/BPBIOS/BPBIOS_6_Utilities.md new file mode 100644 index 00000000..e5e56773 --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_6_Utilities.md @@ -0,0 +1,2579 @@ +# 6. B/P Bios Utilities + +We have developed and adapted many support routines to assist you in using and tailoring B/P Bios installations. Many of these follow generally established functions, and their use may be readily perceived. Others are adaptations of routines which we developed to support our earlier ZSDOS operating system, or are adapted from routines available in the Public Domain. The remainder were written specifically to support this product. + +Each support routine follows generally-acknowledged practices of Z-System Utilities, including built-in Help, and re-execution with the `GO` command. + +Help is accessed by typing the name of the desired routine followed by a double-slash (e.g. `LDSYS //`). Additional information is provided in the following sections of this manual. + +Some of the features of B/P Bios are supported with Version-dependent programs. These vary among specific systems and should not be intermingled if you support a number of different computer types. Contact us if you need to create such a specific tailored version of one of these programs. In the following descriptions, the routines which are restricted to a specific system or which require tailoring are so annotated. + + +## 6.1 BPBUILD - System Image Building Utility + +The purpose of BPBUILD is to create a loadable System Image. Input files needed by this utility include the output of assembling the `BPBIO-xx` file (in Microsoft relocatable format), a `.REL` or `.ZRL` image of an Operating System (ZSDOS for unbanked or ZSDOS2 [`ZS203.ZRL` or `ZS227G.ZRL`] for fully banked systems are recommended), and a `.REL` or `.ZRL` image of a Command Processor (`ZCPR33.REL` for unbanked, `Z41.ZRL` for fully banked systems are recommended). + +BPBUILD is capable of incorporating many types of operating system components into the executable image. Among systems tested are customized BIOSes, ZRDOS, CP/M 2.2, ZCPR2, ZCPR3x and others. One restriction in any segment occurs in the use of Named COMMONs for locating various portions of the system within the processor's memory map. Most assemblers and linkers are limited in the number of different named COMMON bases which can be supported. The linker incorporated in BPBUILD can handle only the following named COMMONs: `_ENV_`, `_MCL_`, `_MSG_`, `_FCB_`, `_SSTK_`, `_XSTK_`, `_BIOS_`, `BANK2`, `B2RAM`, and `RESVD`. + + +### 6.1.1 Using BPBUILD + +BPBUILD operates with layered Menus and may be invoked to build a replacement for an existing Image file, or with defaults to construct a totally new Image file. All files needed to construct the desired image; Bios, Dos, and CPR must reside in the current Drive and User Area, or be accessible via the PUBlic attribute if operating under ZSDOS. The syntax for BPBUILD is: + +| Command | Description | +| :--- | :--- | +| `BPBUILD` | Generate system w/ defaults | +| `BPBUILD fn[.ft]` | Make/Modify a specific system (Default type is `.IMG`) | +| `BPBUILD //` | Display this Message | + +It should be noted that if ZSDOS2 is the selected Dos, Bit Allocation buffers for Hard Drives are located in the System Bank. + + +### 6.1.2 Menu Screen Details + +Upon starting BPBUILD, you will be presented with the main menu screen. From this screen, you may select one of the three main categories to tailor the output image. At any point in the configuration, pressing Control-C or ESCape will exit the menu and return to the Command Processor prompt. + +```generic +/---------------------------------------------------------------------------\ +| Main | +| | +| | +| 1 File Names | +| | +| 2 BIOS Configuration | +| | +| 3 Environment | +| | +| Selection : | +\---------------------------------------------------------------------------/ +``` + + +#### 6.1.2.1 Screen 1 - File Names + +Selecting option One from the main menu will present a screen listing the current file names for the three input files needed to build an image, and the name to be applied to the output file. If BPBUILD was executed with the name of an existing Image file, the file names will be those of the files used to build the specified Image file, otherwise it will be default names furnished by BPBUILD. A sample screen for a non-banked YASBEC system might be: + +```generic +/---------------------------------------------------------------------------\ +| Files (1.1) | +| | +| | +| 1 Command Processor File : ZCPR33 .REL | +| | +| 2 Operating System File : ZSDOS .ZRL | +| | +| 3 B/P Bios Source File : B/P-YS .REL | +| | +| 4 B/P Executable Image : BPSYS .IMG | +| | +| Selection : | +\---------------------------------------------------------------------------/ +``` + +Selecting any one of the four options will allow you to change the name of the file to use for the desired segment. Default File types exist for each entry with both the Command Processor and Operating System files defaulting to `.ZRL` if no type is entered. The Bios file defaults to `.REL`, while the Image output file defaults to `.IMG`. + + +#### 6.1.2.2 Screen 2 - BIOS Configuration + +Selecting BIOS Configuration from the Main Menu (Selection 2) presents the basic screen from which the sizes and locations of either existing system segments (if building from an existing IMG file) or default values from within BPBUILD. A sample screen might appear as: + +```generic +/---------------------------------------------------------------------------\ +| Environment (2.1) | +| | +| COMMON (Bank 0) MEMORY BANK 2 MEMORY | +| ---------------------- ------------------------ | +| A Common BIOS - D400H E Banked BIOS - 0000H | +| Size - 83 Size - 0 | +| B Common BDOS - C600H F Banked BDOS - 0000H | +| Size - 28 Size - 0 | +| C Command Proc - BE00H G Command Proc - 0000H | +| Size - 16 Size - 0 | +| D User Space - E900H H User Space - 0000H | +| Size - 6 Size - 0 | +| | +| Selection : | +\---------------------------------------------------------------------------/ +``` + +While the ability to dictate locations and sizes for various system sizes is provided at this point, we urge you not to alter the values for Bank 2 Memory unless you are VERY familiar with the potential effects and willing to risk potentially disastrous consequences. The primary reason for including this screen was to allow setting Common Memory base locations and to dictate the size of the Resident User Space. Other than specifying the Common User Space size (the starting location defaults to the address in `Z3BASE.LIB`), the remaining values were included primarily for the few specialized users who require custom system locations. + + +#### 6.1.2.3 Screen 3 - Environment Configuration + +Since the Environment Descriptor is an integral part of the Operating System due to the specification of low-level parameters such as memory allocations, this screen is provided to configure the memory map in a suitable fashion for the system being built. For example, in a Fully Banked system with ZSDOS2, there is normally no need for a Resident Command Processor. Using this screen then, selection D may be used to indicate that no space is used for the RCP by setting its location and size to zero. With this space freed, the IO Package (Selection C) may be raised to F400H, keeping its size at 12 records. Since these are the two lowest segments in the memory map, BPBUILD will use this as the lowest value used in the Environment, and move the Operating System segments (including the Resident User Space) up in memory for an increase of 2k bytes in Transient Program Area. + +It is important to note that the Environment Descriptor defined in this screen is stored in a special area within the IMG file produced and placed in memory by LDSYS when activated. Any alteration after loading, for example loading another ENV file as part of the STARTUP script may cause the system to operate incorrectly. + +```generic +/---------------------------------------------------------------------------\ +| Environment (3.1) | +| | +| A - Environment - FE00H F - Named Dirs - FC00H | +| Size (# recs)- 2 # of Entries - 14 | +| B - Flow Ctrl Pkg - FA00H G - External Path - FDF4H | +| Size (# recs)- 4 # of Entries - 5 | +| C - I/O Package - EC00H H - Shell Stack - FD00H | +| Size (# recs)- 12 # of Entries - 4 | +| D - Res Cmd Proc - F200H Entry Size - 32 | +| Size (# recs)- 16 I - Msg Buffer - FD80H | +| E - Command Line - FF00H J - Ext. FCB - FDD0H | +| Size (bytes) - 208 K - Ext. Stack - FFD0H | +| | +| Selection : | +\---------------------------------------------------------------------------/ +``` + +When all configuration or inspection activity is complete at any menu, entering a return with no selection will return to the previous menu screen (Main menu from lower screens), and will start the build activity if a single return is entered from the main menu. All specified files are first read to determine their sizes, and internal memory address calculations are performed. You will be asked if you desire BPBUILD to use optimal addresses for the maximum amount of Transient Program Area (AutoSize), or use the values which were specified in menu 2.1. If you enter N at this point, the build will progress under the assumption that you want to use the values from Menu 2.1. A second prompt will ask you if you want to build a system of "standard" segment sizes. This refers to the CP/M 2.2 standard sizes of 16 records (2k) for the Command Processor and 28 records (3.5k) for the Basic Disk Operating System (BDOS). If you answer Yes, AND the segments are equal to or less than these sizes, the system will be built to reflect these system segment sizes. Since many ill-behaved, but very popular, programs assume the old CP/M segment sizes, this option should generally be used. If the autosize query is selected, BPBUILD automatically executes to completion and returns to the Command Processor prompt. + +To obtain the maximum Transient Program Area with "standard" segment sizes, the easiest method is to execute BPBUILD exiting with the Autosize query answered in the affirmative (Yes), then execute BPBUILD again on the produced image answering the first query with N for No Autosizing, and the second query with a Y to adjust the lower segment sizes for "standard" segment locations. While this is a somewhat cumbersome procedure, it results in a much smaller and faster running utility than otherwise possible, and was a design tradeoff in the development process. + + +## 6.2 BPCNFG - Configuration Utility + +The flexibility of the B/P Bios architecture permits customizing to your system and desired methods of operation. This utility consolidates some of the more common and important tailoring features in a single utility. BPCNFG, the B/P Bios Configuration Utility, provides an easy, menu-driven means of tailoring Hard and Floppy Drive Boot Sector images, Relocatable Image (`.IMG`) files, and certain elements in an executing system. Using BPCNFG reduces the need to assemble a new Bios image for simple changes, and increases the speed with which changes can be made. + + +### 6.2.1 Using BPCNFG + +BPCNFG syntax follows the standard conventions summarized in Section 1.2, and responds to the standard help option sequence of two slash characters. The syntax under which BPCNFG is invoked is dictated by the type of system you wish to configure. The BPCNFG Syntax is: + +| Command | Description | +| :--- | :--- | +| `BPCNFG //` | Print Built-in Help Summary | +| `BPCNFG` | Run interactive, screen mode | +| `BPCNFG *` | Configure Executing System | +| `BPCNFG d[:]` | Configure Drive "d" | +| `BPCNFG [du:]filename[.typ]` | Configure Image File | + +The first form of the syntax is self-explanatory and simply prints a short help file listing the purpose of the utility and the syntax of the program use. The Interactive mode of operation, execution of BPCNFG with no arguments, will first ask you whether you wish to configure a Memory, Disk or Image version of a B/P Bios system, and set internal parameters to that mode, as well as loading the requisite data if needed. If no file type is specified for an Image file, a type of `.IMG` is assumed. + +BPCNFG may configure options in the currently operating system with some limitations. The most significant limitation is that Hard Drive partitions may not be altered since space for the required bit buffers (ALV and CSV) is allocated at system load (boot) time and cannot be reset when a system is already installed. With this exception, all other parameters may be varied and will be in effect until another system is loaded by Cold Booting the computer, or loading an Image file with LDSYS. + +To abort the BPCNFG without changing current parameters, press either ESCape or Control-C from the main menu display. Option setting will occur if a Carriage Return only is entered from the Main Menu Screen. + + +### 6.2.2 Menu Screen Details + +BPCNFG is a Screen-oriented support routine using the terminal attributes defined in the currently installed Termcap. Five main screens are currently defined at the main menu, with several selections resulting in sub-menu screens. The first is the main menu from which the general category is selected for alteration. The top screen line reflects the level and mode as: + +```generic +/---------------------------------------------------------------------------\ +| Main Menu - Configuring Image File [A10:T1.IMG ] | +| Bios Version 2.0 | +| | +| 1 System Options | +| | +| 2 Character IO Options | +| | +| 3 Floppy Subsystem Options | +| | +| 4 Hard Disk Subsystem Options | +| | +| 5 Logical Drive Layouts | +| | +| | +| Enter Selection : | +\---------------------------------------------------------------------------/ +``` + +Each of the five selections results in a sub-menu screen which depicts the specific elements which may be changed and the current values/settings. Each of the selection screens is detailed below. + + +#### 6.2.2.1 Screen 1 - System Option Parameters + +The System Options may be set from Menu Screen 1 which may appear as: + +```generic +/---------------------------------------------------------------------------\ +| Menu 1 - System Options | +| | +| | +| 1 System Drive = A: | +| | +| 2 Startup Command = "START01 " | +| | +| 3 Reload Constant = 23040 (5A00H) | +| | +| 4 Processor Speed = 9 MHz | +| | +| 5 Memory Waits = 0, IO Waits = 0 | +| | +| | +| Enter Selection : | +\---------------------------------------------------------------------------/ +``` + +The Logical System drive selected by the first entry is used by the Bios Warm boot to load the operating system on a Cold boot, and on Error Exits. The Startup command is normally the name of a `.COM` file which performs additional system initialization when first started. Such a file is normally created by entering a sequence of instructions (file names and arguments) into a script using ALIAS, SALIAS, VALIAS or other similar ZCPR3 tool. + +The remainder of the entries concern the Physical hardware within the computer and generally do not need to be changed for other than initial installation. The Reload Constant at Selection 3 may be "fine tuned" by slightly varying the value. The normal effect of this is to adjust the speed of the Real Time clock within the computer to allow it to keep proper time. The Processor Speed (Selection 4) should be the CPU Clock speed rounded to the nearest MegaHertz. For example, the rate shown in the sample screen is, in fact, 9.216 MHz. When the Clock Speed is changed, an option is offered to automatically scale the Reload Constant (Selection 3) to scale it by a proper factor based on the amount that the Clock Frequency was changed. This is not always needed, but is generally desirable in HD64180/Z-180 systems using an interrupt clock timer. + +The number of Memory and IO Waits at Selection 5 are in addition to any Wait states inserted automatically in the hardware. For example, the Zilog Z180 inserts one wait state into all IO Port addresses. Since BPCNFG is a general purpose utility, it cannot know this. The number set with this selection is therefore in addition to any hardware injected wait states. + +A sixth menu also exists, but since inadvertent alteration of its values can result in bizarre and potentially destructive consequences, its existence is hidden and prompted if selected. The interaction to select option 6 is: + +```generic +Enter Selection : 6 +-- This is DANGEROUS...Proceed? (Y/[N]) : +``` + +If an explicit Y is entered, the hidden menu is displayed appearing as follows for a YASBEC with the MEM4 addressing PAL which allows the full 1 Megabyte range to be used: + +```generic +/---------------------------------------------------------------------------\ +| Menu 1.1 - System Bank Numbers | +| | +| | +| 1 TPA Bank # = 1 | +| | +| 2 System Bank # = 3 | +| | +| 3 User Bank # = 4 | +| | +| 4 RAM Drive Bank # = 5 | +| | +| 5 Maximum Bank # = 31 | +| | +| | +| Enter Selection : | +\---------------------------------------------------------------------------/ +``` + +The bank numbers should reflect the Physical 32k bank numbers in the system progressing from the lowest, or first available, to the highest. The Bank numbers are Zero-based, and may range from 0 to 255 (0FFH). The User Bank and RAM Drive Banks may be set to Zero if No Banked User area or RAM Drive respectively is desired. It should be noted that the actual control for these two features is in other screens, and setting the Bank Numbers to Zero while the options are active can have adverse consequences. + + +#### 6.2.2.2 Screen 2 - Character IO Parameters + +Screen Menu 2 allows configuration of the Character IO subsystem, to include assignment of logical devices to physical devices. A sample screen for the YASBEC might appear as: + +```generic +/---------------------------------------------------------------------------\ +| Menu 2 - Character IO Options | +| | +| | +| 1 IOBYTE Assignment: | +| Console = COM2 | +| Auxiliary = COM1 | +| Printer = PIO | +| | +| 2 COM1 - 9600 bps, 8 Data, 1 Stop, No Parity, [In(8)/Out(8)] | +| | +| 3 COM2 - 19.2 kbps, 8 Data, 1 Stop, No Parity, [In(7)/Out(8)] | +| | +| 4 PIO1 - [Out(7)] | +| | +| 5 NULL - [In(8)/Out(8)] | +| | +| 6 COM3 - 38.4 kbps, 8 Data, 1 Stop, No Parity, [In(8)/Out(8)] | +| | +| 7 Swap Devices | +| | +| Enter Selection : | +\---------------------------------------------------------------------------/ +``` + +Selection 1 determines which of the active devices is assigned to the addressable functions dictated by the IOBYTE. This location in memory is used by the operating system for Character IO normally consisting of the Console, Printer (List Device in CP/M terminology) and an Auxiliary IO (Reader and Punch in CP/M). The exact Devices assigned to these Logical functions depends on the bit-mapped characteristics of the IOBYTE, and positioning within the table portrayed in this Menu. + +Early versions of B/P Bios (Versions 1.0 and earlier) distributed as "Starter Systems" and test versions used a fixed number of devices and a different data structure for device access. B/P Bios Production systems with Version numbers of 1.1 through 1.9 will contain only four device drivers, but use the newer data structures. Beginning with Version 2.0, however, many Character Devices may be accommodated, with the first four being directly accessible by the IOBYTE, and the ability to exchange devices to place any four in the first positions for access by applications programs. The above screen depicts a typical display under a Version 2.0 Bios. Smaller systems such as placed on the Boot Tracks will use only four fixed devices with a typical Version Number of 1.1 and will not include selections 6 or 7. + +Selection 1 offers the opportunity to select which of the first four physical devices is assigned to the three logical IOBYTE defined functions. A secondary menu will prompt you for the exact functions and devices. An example of the interaction with selection 1 is: + +```generic +Set [C]onsole, [A]uxiliary, or [P]rinter : C + Set Com[1], Com[2], [P]io, or [N]ull ? +``` + +Selections 2, 3 and 6 in this sample screen allow configuration of the serial ports included in this B/P Bios. If you are making hardware changes in the Bios, please follow the specifications in the source code to insure that this utility will function as described. For most system installations covered to date, one or more of these options will have no effect, but the capability still exists to configure the option. This selection results in a series of options being presented for verification or alteration. Current settings are listed as default values which will remain selected if no entry is made before the ending Carriage Return (Enter key). A Sample interaction on a YASBEC is: + +```generic +Configuring COM1 [In(8)/Out(8)]: + Baud Rate (Max=38.4 kbps) = Selections are: + 1-134.5 bps 2-50 bps 3-75 bps 4-150 bps + 5-300 bps 6-600 bps 7-1200 bps 8-2400 bps + 9-4800 bps 10-9600 bps 11-19.2 kbps 12-38.4 kbps + Select [10] : + Data = 8-bits. Change? (Y/[N]) : + Stop Bits = 1-bits. Change? (Y/[N]) : + Parity = None Change? (Y/[N]) : + XON/XOFF Flow = No Change? (Y/[N]) : * Defaults selected + RTS/CTS Flow = No Change? (Y/[N]) : + Input is 8-bits. Change? (Y/[N]) : + Output is 8-bits. Change? (Y/[N]) : +``` + +Selection four tailors the default parallel port, normally a Centronics printer interface. As with previous selections, not all options may be active, but will appear in the configuration sequence to retain the generality of BPCNFG. Current settings (in braces) will be retained if a Carriage Return is entered. + +```generic +Configuring PIO1 [Out(7)]: + XON/XOFF Flow = No Change? (Y/[N]) : + RTS/CTS Flow = No Change? (Y/[N]) : + Output is 7-bits. Change? (Y/[N]) : +``` + +The final selection (only appearing in Bios Versions 2.0 and later) allows the exchange of devices. In the sample Menu 2, Selections 2-5 are active devices, with Selection 6 existing in the Bios, but not accessible. Using the last selection, COM3 could be exchanged with one of the first four making it an active device upon exiting BPCNFG which calls the Device Configuration function. The interaction may appear as: + +`Exchange Device : 3 With Device : 6` + +After this choice, active devices will be COM1, COM3, PIO1 and NULL. + + +#### 6.2.2.3 Screen 3 - Floppy Disk Parameters + +Extensive tailoring of the Floppy Disk subsystem is possible at this Screen. While many popular systems do not support all options (mainly due to the Controller logic), all options and respective settings will appear to be set at this point. Also, while such items as the Step rate will accept increments of a set size (1 mS for Step Rate), many systems have discrete increments that do not match allowable values. For example, the SMS 9266 used in MicroMint's SB-180 will only accept 2 mS increments with 5 1/4" Floppy Drives, the WD 1770 used in the Ampro Little Board only steps at 6, 12, 20 and 30 mS, while the 1772 used in the YASBEC permits 2, 3, 5, and 6 mS Steps. The rates set with BPCNFG are suitably rounded up to the most appropriate rate within the Bios code during drive selection to allow tailoring of drives in a generalized manner. Options tailorable for Floppy Disk drives as seen on a YASBEC are: + +```generic +/---------------------------------------------------------------------------\ +| Menu 3 - Floppy Disk Options | +| | +| | +| 1 Floppy Drive Characteristics: | +| Drv0 = 3.5" DS, 80 Trks/Side | +| Step Rate = 3 mS, Head Load = 4 mS, Unload = 240 mS | +| Drv1 = 5.25" DS, 40 Trks/Side | +| Step Rate = 4 mS, Head Load = 24 mS, Unload = 240 mS | +| Drv2 = 5.25" DS, 80 Trks/Side | +| Step Rate = 3 mS, Head Load = 24 mS, Unload = 240 mS | +| Drv3 = 5.25" DS, 80 Trks/Side | +| Step Rate = 6 mS, Head Load = 24 mS, Unload = 240 mS | +| | +| 2 Motor ON Time (Tenths-of-Seconds) : 100 | +| | +| 3 Motor Spinup (Tenths-of-Seconds) : 5 | +| | +| 4 Times to Try Disk Operations : 4 | +| | +| | +| Enter Selection : | +\---------------------------------------------------------------------------/ +``` + +Selecting one of the four items on this menu will prompt you for the information needed, allowing you to retain current settings as a default. An example of the additional prompts resulting from selection one on the above screen is: + +```generic +Configure which unit [0..3] : 2 + Size 8"(1), 5.25"(2), 3.5"(3)? [2] : + Single or Double-Sided Drive ? (S/[D]) : + Motor On/Off Control Needed ? ([Y]/N) : + Motor Speed Standard or Hi-Density ([S]/H) : + Tracks-per-Side (35,40,80) [80] : + Step Rate in Milli-Seconds [3] : + Head Load Time in Milli-Seconds [24] : + Head Unload Time in Milli-Seconds [240] : +``` + + +#### 6.2.2.4 Screen 4 - Hard Disk Parameters + +The B/P Bios Hard Disk Subsystem is centered around the Small Computer Systems Interface (SCSI) standard. Backward compatibility with the earlier Shugart Associates System Interface (SASI) is also provided to allow older controllers to be used. During the course of B/P Bios development, several controller types were incorporated, with unique features accommodated in a transparent way within the utilities. As a compromise between flexibility and program size, a limit of three physical hard drive units was placed on the system. This limit does not impact the 16 possible logical drives which the computer may handle. A sample Menu for a single Conner CP-3100 SCSI Drive of 100 Megabytes is: + +```generic +/---------------------------------------------------------------------------\ +| Menu 4 - Hard Disk Options | +| | +| 1 Hard Drive Controller = Conner SCSI | +| | +| 2 First Drive : Physical Unit 0, Logical Unit 0 | +| No. of Cylinders = 776, No. of Heads = 8 | +| | +| 3 Second Drive : - inactive - | +| | +| 4 Third Drive : - inactive - | +| | +| | +| Enter Selection : | +\---------------------------------------------------------------------------/ +``` + +The first available selection allows you to select the type of controller installed or used in the system. The controller definition applies across all three physical drives, so some care must be applied in mixing different controller types on the same system. For example, a Shugart 1610-3 controller is incompatible with a Seagate SCSI or SCSI-2 drive attached directly to the SASI bus since initialization information is required of drives on the 1610-3 which must not be sent to the SCSI due to the differing commands. The controller types defined in the initial release of B/P Bios appear in Selection 1 as: + +```generic + Select Controller Type as: + (0) Owl + (1) Adaptec ACB-4000a + (2) Xebec 1410a/Shugart 1610-3 + (3) Seagate SCSI + (4) Shugart 1610-4/Minimal SCSI + (5) Conner SCSI + (6) Quantum SCSI + +Enter Selection : +``` +(more added in later versions) + +Selections two, three and four from Menu 4 allow you to specify the physical parameters of one of the three possible drives. As with other options, some of the parameters do not apply, such as Reduced Write and Precompensation with SCSI drives, but appear here to allow a general configuration tool. Current settings appear in square braces and are selected if only a Carriage Return is entered. A sample entry configuring the Conner CP-3100 is: + +```generic +Activate Drive ([Y]/N) ? +Physical Unit (0..7) [0] : +Logical Unit Number (0..7) [0] : +Number of Physical Cylinders [776] : +Number of Heads [8] : +Reduced Write Starting Cylinder [0] : +Write Precomp. Start Cylinder [0] : +``` + + +#### 6.2.2.5 Screen 5 - Partition Parameters + +Menu 5 permits arranging the physical drive complement into Logical Drives, and dividing physical units into multiple logical Partitions. + +```generic +/---------------------------------------------------------------------------\ +| Menu 5 - Logical Drive Layout | +| | +| A: = Unit 0, 64 Sctrs/Trk, 4k/Blk, 7984k (998 Trks), 1024 Dirs | +| B: = Unit 0, 64 Sctrs/Trk, 4k/Blk, 20000k (2500 Trks), 1024 Dirs | +| C: = Unit 0, 64 Sctrs/Trk, 4k/Blk, 20000k (2500 Trks), 1024 Dirs | +| D: = Unit 0, 64 Sctrs/Trk, 4k/Blk, 54432k (6804 Trks), 2048 Dirs | +| E: = Floppy 0 | +| F: = Floppy 1 | +| G: = Floppy 2 | +| H: = -- No Drive -- | +| I: = -- No Drive -- | +| J: = -- No Drive -- | +| K: = -- No Drive -- | +| L: = -- No Drive -- | +| M: = RAM | +| N: = -- No Drive -- | +| O: = -- No Drive -- | +| P: = -- No Drive -- | +| | +| 1 Swap Drives, 2 Configure Partition 3 Show Drive Allocations | +| | +| | +| Enter Selection : | +\---------------------------------------------------------------------------/ +``` + +Selection 1 allows for swapping two specified logical drives. For example, the above screen shows a system which will boot from a hard drive. If the system were being configured for a Floppy-based system you might swap drive A with drive E with Selection 1 as: + +```generic + Enter Selection : 1 +Swap drive [A..P] : A with drive [A..P] : E +``` + +Selection 2 permits defining logical partitions on a Hard drive, and of the RAM drive, if active. It queries you for the needed information from which to set internal Bios values. If converting from an existing system, SHOWHD (See 6.19) will display the values to enter for a specified Partition. An example of the interaction is: + +```generic +Configure which Drive [A..P] : D +Allocation Size (1, 2, 4, 8, 16, 32k) [4] : + Number of Dir Entries [2048] : + Starting Track Number [6000] : + # Tracks in Partition [6804] : + Physical Unit Number [0] : +``` + +Selection 3 from Menu 5 may be used in conjunction with the allocation to view the existing allocations for a given Hard Drive Unit. Selecting 3 prompts you for the Desired Hard drive as: + +`Display Allocations for which Hard Drive [0..2] :` + +and will show the current Partitions and allocations. As an example, the four partitions on the Conner CP-3100 depicted in the Menu 5 screen are reported here on a separate screen as: + +```generic +/---------------------------------------------------------------------------\ +| Partition Data Hard Drive Unit : 0 | +| | +| Drv Start Trk End Trk | +| | +| A 2 999 | +| B 1000 3499 | +| C 3500 5999 | +| D 6000 12803 | +| [any key to continue] | +\---------------------------------------------------------------------------/ +``` + + +### 6.2.3 NOTES Spring 2001 + +A new menu item was added to the primary screen to allow configuration from a script configuration (`.CNF`) file. The format is explained in the built-in help. + + +## 6.3 BPDBUG - B/P Bios Debug Utility + +This utility provides a low-level tool patterned after Digital Research's DDT, but extended to provide a more useful user interface, the ability to handle Z80 and Z180 mnemonics in disassembly, and memory banking using B/P Bios interfaces. While the description is primarily oriented to screen output, the Operating system permits also sending output to the defined Printer by toggling Control-P which may be enabled and disabled within BPDBUG. + +### 6.3.1 Using BPDBUG + +The syntax for BPDBUG is simple with only three variants as: + +| Command | Description | +| :--- | :--- | +| `BPDBUG //` | Print a short help message | +| `BPDBUG` | Execute BPDBUG | +| `BPDBUG [fn[.ft]]` | Execute BPDBUG, Loading named file | + +When executed, BPDBUG relocates the majority of the code to high memory immediately below the BDOS, overwriting the Command Processor. If a file load is specified as in the third method of invocation shown above, and the file type is `.HEX`, then a file in Intel HEX format is assumed and it is converted to binary form at the specified address. + +In addition to the short help message available with the double-slash option, a built-in command summary is available at all times from the main BPDBUG prompt by entering a Question Mark. The summary appears as: + +```generic +/---------------------------------------------------------------------------\ +| B/P Bios DBug V 0.3 | +| -? | +| | +| Available commands: | +| B{ank} Bank# | +| D{ump} [From [To]] | +| E{nter} Addr | +| F{ill} Start End Byte | +| G{o} Addr | +| H{ex sum/diff} Word1 Word2 | +| I{nput} Port# | +| L{ist} [From [Thru]] | +| M{ove} Start End Dest | +| N{ame} FN[.FT] {for Read/Write} | +| O{utput} Port# Byte | +| R{ead file} [Offset] | +| T{race} {Trace mode On} | +| U{ntrace} {Trace mode Off} | +| W{rite file} Number_of_128-byte_blocks | +| X {set breakpoint} Addr | +| Z{ero breakpoints} | +| ? {Show this msg} | +\---------------------------------------------------------------------------/ +``` + +Square braces in the summary indicate optional parameters, while text strings and abbreviated names indicate parameters and types. + + +### 6.3.2 BPDBUG Commands + + +#### 6.3.2.1 Select Memory Bank _[ B ]_ + +To select a memory bank in the range of 0..255, simply enter the Command "B" followed by the bank number in Hexadecimal. Optional spaces may be placed between the command letter and the Bank number. The syntax for this command is: + +`B[ ]nn` + +The Bank number selected by this command will be made the current bank for Display (D), Enter (E) and List (L) commands. If the specified bank number exceeds the largest bank number physically existing in the system, the bank number will be set to the last bank defined in the B/P Bios Header. + + +#### 6.3.2.2 Dump (Display) Memory in Hex and Ascii _[ D ]_ + +This command displays memory contents in both hexadecimal and ascii form. Where the current byte in the display is a control character (less than 20H), a period character is printed in the ascii column. + +Defaults for this command are 100H and the TPA bank as the starting address, and 256 as the number of bytes to display if no End Address is specified. For subsequent uses of the Dump command, the Starting address will be one more than the ending address of the last Dump. The Bank Number will remain that last specified, or the TPA bank if never changed in a session. The syntax is: + +`D[ ][Start_Addr] [End_Addr]` + +A sample of the output appearing on the screen is: + +```generic +-d100 12f +01:0100 ED73 FE03 31FE 0321 5D00 7E23 FE2F 2006 .s..1..!].~#./ . +01:0110 BE11 AD01 2825 2A01 002E 5A7E FEC3 2018 ....(%*...Z~.. . +01:0120 CDAC 0121 FAFF 197E FE42 200C 237E FE2F ...!...~.B .#~./ +``` + + +#### 6.3.2.3 Enter Values in Memory _[ E ]_ + +This command permits entering values into memory. A period terminates entry. + +`E[ ][Start_Addr]` + +```generic +-e100 +:41 43 44 +:. +``` + + +#### 6.3.2.4 Fill Memory with Constant Value _[ F ]_ + +Entire memory areas may be set to a single constant value with this command. All three arguments (Start, End and Value) must be specified, and the command will not be executed if fewer arguments are given. The syntax is: + +`F[ ]Start End Value? + +As an example, the following command sets the sixteen bytes from 100H through 10FH in the currently selected bank to binary Zero; + +```generic +-f100 10f 0 +``` + + +#### 6.3.2.5 Go (Execute) Program in Memory _[ G ]_ + +Execution may be started at any arbitrary address with the "Go" command. If no target address is specified, 100H is assumed since it is the normal starting address of programs loaded into the Transient Program Area. The syntax of the command is: + +`G[ ][Address]` + + +#### 6.3.2.6 Hex Sum and Difference _[ H ]_ + +Simple Hexadecimal addition and subtraction is performed with the "Hex" command. When the command is executed with two addresses, both their sum (modulo 65536) and difference (also modulo 65536) are displayed in that order. The syntax of this command is: + +`H[ ]Value1 Value2` + +For example, if an offset of 45H from a base of 0ED3FH was desired, the resulting g positive and negative address could be determined as: + +`-hed3f 45` <-- Entered +`ED84 ECFA` <-- ..returned Sum and Difference + + +#### 6.3.2.7 Display Value from Input Port _[ I ]_ + +This command will read the desired Input Port in the range of 0 to 0FFFFH and display the resulting byte. Since 16-bit address calculations are used, this command will properly read the built-in ports of the HD64180 and Z180. The syntax of the Input command is: + +`I[ ]Port_num` + + +#### 6.3.2.8 List (Disassemble) Memory Contents _[ L ]_ + +Disassembly of executable instructions in memory is accomplished with this command. As with the "Dump" command, the starting address defaults to 100H when first loaded, and is assumed to be the instruction following the last one disassembled for subsequent uses of this command if no address is explicitly entered. If no Ending address is specified, 23-26 bytes will be contained in the listing depending on the length of the last instruction. The syntax is: + +`L[ ][Start] [End]` + +A sample of an entry and the resulting output with an arbitrary program is: + +`-l120 127` <-- Entered + +```generic +0120 CDAC01 CALL 01AC +0123 21FAFF LD HL,FFFA +0126 19 ADD HL,DE +0127 7E LD A,(HL) +``` +..displayed + +Note that the actual bytes included in the disassembled instructions are also listed in contrast to other similar programs to provide additional information for you. Additionally, an extra blank line is displayed after all unconditional jumps and returns to serve as a visual representation as an absolute change in control flow. The mnemonics are standard Zilog Z180 codes. + + +#### 6.3.2.9 Move Memory Contents _[ M ]_ + +This command permits blocks of data to be moved within memory. Memory address bounds checking is performed to insure that overlapping addresses are handled correctly so that minor shifts in blocks of data may be accomplished. The syntax for this command is: + +`M[ ]Start End Destination` + + +#### 6.3.2.10 Set File Name for Read/Write _[ N ]_ + +This command is used to set the file name and optional type prior to a read or write operation. The name remains active until changed or BPDBUG is exited. The syntax is: + +`N[ ]FileName[.FileTyp]` + + +#### 6.3.2.11 Send Value to Output Port _[ O ]_ + +This command forms the complement of the Input command covered above. It sends a specified byte to the addressed Output port. The syntax is: + +`O[ ]Port_num Value` + +As with all arguments, if more digits than the number needed are specified, only the last two (for a Byte) or four (for an address) are used in the expression. + + +#### 6.3.2.12 Read a File into Memory _[ R ]_ + +This command reads the file specified by the Name command into memory at the default address of 100H (if no offset is specified), or at a starting address of Offset+100H. The Offset value must be specified in Hexadecimal. The syntax of the Read Command is: + +`R[ ][Offset]` + +When the file is loaded, you will be informed of the current setting of the default address for the base of current memory (PC value) and the byte after the last one loaded by the Read Command (Next). The display might appear as: + +```generic +Next PC +0880 0100 +``` + +#### 6.3.2.13 Activate Trace Mode _[ T ]_ + +To assist in debugging programs, a Trace function is included which is activated with this command. Upon encountering a breakpoint (See X Command below) the program enters the Trace mode in which each instruction is trapped and the state of the processor displayed along with a Disassembled listing of the instruction. Entering a single letter "T" activates the Trace Mode. + +A fragment of a program run with Trace On is: + +```generic +S0Z0H0P0N1C0 A=00 BC=0000 DE=0000 HL=0000 SP=0100 + IX=A4AE IY=FFFE 0100 C30B01 JP 010B + +S0Z0H0P0N1C0 A=00 BC=0000 DE=0000 HL=0000 SP=0100 + IX=A4AE IY=FFFE 010B 2A0500 LD HL,(0005) +S0Z0H0P0N1C0 A=00 BC=0000 DE=0000 HL=52C3 SP=0100 + IX=A4AE IY=FFFE 010E CDBD07 CALL 07BD +S0Z0H0P0N1C0 A=00 BC=0000 DE=0000 HL=52C3 SP=00FE + IX=A4AE IY=FFFE 07BD 7C LD A,H +S0Z0H0P0N1C0 A=52 BC=0000 DE=0000 HL=52C3 SP=00FE + IX=A4AE IY=FFFE 07BE B5 OR L +S1Z0H0P0N0C0 A=D3 BC=0000 DE=0000 HL=52C3 SP=00FE + IX=A4AE IY=FFFE 07BF C8 RET Z +``` + + +#### 6.3.2.14 De-Activate Trace Mode _[ U ]_ + +This command turns the Trace Mode Off so that subsequent execution occurs at full speed with no trapping. Entering a single letter "U" deactivates the Trace Mode. + + +#### 6.3.2.15 Write File to Storage _[ W ]_ + +This command is the complement to the Read command covered above. It assumes that the data to be written starts at 100H and writes the specified number of 128-byte blocks to the file last specified with a "Name" command. The syntax of this command is: + +`W[ ]#Blocks` + + +#### 6.3.2.16 Set Breakpoint _[ X ]_ + +This command is used to tag locations within the program to be executed under BPDBUG which, when executed, will temporarily stop executing and either return to the BPDBUG prompt or print information for the Trace output. Up to two breakpoints may be active at any point in time. The syntax is: + +`X[ ]Address` + + +#### 6.3.2.17 Clear Breakpoints _[ Z ]_ + +This command clears all breakpoints set with the X command cited above. Entering the single letter "Z" clears all breakpoints. + + +#### 6.3.2.18 Display On-Line Help _[ ? ]_ + +Entering a single Question Mark ("?") as a command displays the Build-In help display containing a summary of the commands available from within BPDBUG. + + +## 6.4 BPFORMAT - Floppy Disk Format Utility + +BPFORMAT is the general-purpose format routine for Floppy Disk Drives in the B/P Bios system. It automatically adapts to the specific hardware used in your computer to present a single interface across a wide range of platforms, and incorporates the ability to format disks in formats not implemented in your computer. This capability allows you to format disks for exchange with other users in their native disk format using the same library of alien disk formats used by the EMULATE program (see 6.8). + +This program is B/P Bios-specific and will not function under other Bios systems. Its operation is the same under banked or unbanked systems, and with the many types of physical Disk Controller integrated circuits available. In the initial version, the following Controller types are supported: + +- 765 +- 1692 +- 1770 +- 1771 +- 1772 +- 1790 +- 1791 +- 1792 +- 1793 +- 1795 +- 2790 +- 8473 +- 9266 + +### 6.4.1 Using BPFORMAT + + +#### 6.4.1.1 Built-in Formats + +The simplest way of formatting diskettes is to use one of the formats included in the currently running B/P Bios. BPFORMAT may be invoked by simply entering the program name, or by following it with a drive letter and colon as: + +`BPFORMAT D:` + +Optionally, a Named directory may replace the drive letter and will format the drive associated with the named directory. For example, if a directory named WORK: is defined to be Drive C:, User 10, the command WORK: + +`BPFORMAT WORK:` + +would format Drive C:. When invoked in either of the above manners, BPFORMAT will list the built-in formats available for this drive from those included in the file `DPB.LIB` (and optionally `DPB2.LIB`, see sections 4.1 and 4.2). Only those formats which exactly match the drive characteristics will be presented, so only 80-track formats will be offered for an 80-track drive and so forth. For example, the offerings for a 40-track 5.25" disk drive may result in: + +```generic +Available formats are: + + A - Ampro DSDD B - Ampro SSDD + +Select format (^C to exit) : +``` + +As precautions against inadvertently formatting diskettes, confirmation prompts are included as the program progresses, and the opportunity exists to escape from the format program to Command processor. An example appears at this point where a Control-C aborts the format operation. + + +#### 6.4.1.2 Library Formats + +If formatting of a diskette is desired in a format not supported by the built-in selections featured in the executing Bios, the library of formats used by EMULATE (see 6.8) may be used. Reasons for using the library may range from the need to format in a mode used on another type of computer to a choice made internally unavailable by sizing constraints, as when tailoring a system for Boot Track installation. Whatever the reason, this flexibility is offered as an inherent feature of B/P Bios and is specified by specifying the L Option when invoking BPFORMAT. If specifying the desired drive on the command line as in either example above, simply add the option character at the end (with optional slash) as: + +`BPFORMAT D: L` + +If you wish to be prompted for the drive letter as part of the program flow, the slash becomes mandatory to inform BPFORMAT that you are specifying the Library option instead of Drive L:. The invocation thereby becomes: + +`BPFORMAT /L` + +When executed with the Library option, you will be presented with a menu of formats which may be used with the physical drive as defined in the Bios header. A sample display appears as: + +```generic +Available formats are: + + A - Actrx SSDD B - Ampro SSDD C - VT180 SSDD D - H-100/4 1D + E - H89/40 1S F - H89/40 1D G - H89/40 1X H - Kaypro 2 + I - Osborne 1S J - Osborne 1D K - Ampro DSDD L - H-100 DSDD + M - H89/40 2D N - H89/40 2X O - QC-10 DSDD P - Kaypro 4 + Q - MD-3 DSDD R - PMC-101 S - Sanyo 1000 T - TV 802/803 + U - XBIOS-3 2D V - XL-M180 T2 + +Select format (^C to exit) : +``` + +Entering one of the letters corresponding to a format will set all parameters and proceed with the format operation. Entering a Control-C at this point will return you to the Command Processor at this point avoiding any inadvertent disk formatting. + +The Assembly source to the Format library is provided in the B/P Bios package as an aid in accepting formats not included in the default distribution package, or to experiment with new formats. + + +### 6.4.2 Configuration + +Two options exist for custom tailoring BPFORMAT to operate in a method you find most comfortable. The first is a Quiet option which will minimize extraneous output to the Console. It is set by a Boolean flag consisting of a Byte at an offset of 22 (16H) bytes from the beginning of the program. A Zero byte in this location signifies Verbose operation where all defined prompts and status information is displayed. A Non-Zero value (normally 0FFH) indicates that Console output should be minimized with only essential output displayed. + +The second option is for selection of the File Name and Type to be used for the Library of formats used with the L option. The default value of this entry is `ALIEN.DAT` (in formatted FCB form) which is also used with the EMULATE program. This field begins at an offset of 23 (17H) bytes from the beginning of the program. + + +### 6.4.3 BPFORMAT Error Messages + +`Must be wheel to FORMAT!!!` + +As a safety feature, only users with Wheel privileges may format diskettes. This error message identifies an attempt without the proper authorization. + +`*** ERROR ! Not B/P Bios, or Old Version !` + +In most cases, this error will be seen if an attempt is made to format a disk under a Bios other than B/P Bios. If some of the mandatory data structures have been altered, or if an attempt is made to run the release version of B/P Bios under one of the early test versions of B/P Bios, this message will also be displayed. + +`*** ERROR ! The selected format is not supported by FORMAT!` + +This error will be displayed if a format from a library of formats is incompatible with the specified drive, such as if a 5.25" format is selected for an 8" drive. + +`*** ERROR ! The detected FDC is not supported by FORMAT!` + +The Bios reported a Floppy Disk Controller (FDC) that is not in the list of Controllers supported by BPFORMAT. To view the list of controllers supported, view the internal Help by using the double-slash option. + +`*** ERROR ! Disk is Write Protected!` + +An attempt was made with the Write Protect Tab ON (for 5.25"), OFF (for 8") or in the Protect position (3.5") for the specified disk. Set the disk to Read/Write by altering the physical setting and try to format the disk again. + +`*** ERROR ! Disk won't recalibrate` + +The drive heads could not be restored to Track 0 position. Thiserror is often due to a failure in the drive mechanism, but can also be caused by deformed diskettes or loose drive cable. + +`Format Error : xx` + +An error was detected during the format process. The "xx" will be the Hexadecimal byte returned by the Bios portion of the format routine, and bits set to a "1" value should represent an error code decipherable from the FDC Data or programming sheet. + +`+++ Can't Open : fn.ft` + +BPFORMAT could not open the format library file. To access a format library, it must either be in the default library, or accessible from it either via the PUBlic bit or along the ZSDOS path. + +`No formats available for this drive!` + +This error will be reported if no formats (internal or from a format library, depending on how it was invoked) are supported on the specified drive. For example, if all internal formats are for 5.25/3.5" drives and the target drive is specified as an 8" drive, then no formats will be available if BPFORMAT is invoked using the internal format method of operation. + + +## 6.5 BPSWAP - Logical Disk Swap Utility + +This utility allows you to exchange the drive letters defining two logical drives or partitions within the system. It performs any operations necessary to properly adjust the Operating System to account for drive redefinition, and relogs both drives using Dos Function 37 to force rebuilding of the Allocation Bit Map. + +BPSWAP is a B/P Bios utility and will not execute under any other system. It may be operated in an interactive mode, fully "expert" mode with arguments passed on the command line, or a combination where the first drive letter is passed on the command line and the second entered in response to a query. If running in the interactive mode, entering a Control-C instead of a drive letter will interrupt the program and return to the Command Processor. BPSWAP is re-executable under ZCPR with the `GO` command. + + +### 6.5.1 Using BPSWAP + + +#### 6.5.1.1 Interactive Operation + +To execute BPSWAP in the interactive query/response mode, simply invoke the program by entering its name as: + +`BPSWAP` + +The program will insure that the system is running a B/P Bios, gather internal data from the operating environment, and display the prompt: + +`First Drive to Swap [A..P] :` + +At this point, a drive letter (upper or lowercase) should be entered within the specified range of "A" through "P". All invalid characters, except for Control-C which aborts the program, will result in repeated prompts for the first drive letter. When a valid drive letter is detected, the second is likewise requested with the prompt: + +`Second Drive to Swap [A..P] :` + +BPSWAP responds to entries at this point in an identical manner to the first, repeatedly prompting for a valid letter, or the abort character. When a valid letter is received, each logical drive is reassigned to the physical definitions of the other. + + +#### 6.5.1.2 Command Line Operation + +BPSWAP can accept and parse drive letters passed to it on the Command Line in order to include drive exchanges in Startup scripts or other alias commands. To invoke the program in this manner, enter the program name with two drive letters in the range of "A" through "P" with a delimiter between each field. Each of the drive letters may be followed by an optional colon. Delimiting characters are Tab, Space, and Comma. A summary of the complete syntax is: + +`BPSWAP d1[:] | | d2[:]` + +To illustrate, the following are valid commands executing BPSWAP: + +| Command | Description | +| :--- | :--- | +| `BPSWAP A: E:` | Exchange E drive with A | +| `BPSWAP D,H` | Exchange D drive with H | + +If an invalid character is detected for either or both of the drive letters when called in the Command Line mode, operation automatically reverts to the Interactive mode and the respective prompt(s) will be given for valid drive letter(s). This feature permits a hybrid mode of operation to be specified wherein the first drive letter is passed on the Command Line, and the second entered in response to the second drive prompt. + + +### 6.5.2 BPSWAP Error Messages. + +The only error message which may be printed by BPSWAP is in response to internal routines which validate the presence of a B/P Bios. Any attempt to run this utility on other Bioses results in the error: + +`+++ Not B/P Bios ... aborting +++` + +after which point the program aborts and control returns to the Command Processor. No effect on drive allocations will occur if this error is displayed. + + +## 6.6 BPSYSGEN - System Generation Utility + +BPSYSGEN is our generic version of the classic SYSGEN program used to place an executable system image onto the boot sectors of a Floppy or Hard Disk. It uses information provided by the Bios in the form of DPB/XDPB data (see 5.2.3) which defines the physical and logical drive characteristics to write system information from the system tracks of one drive to another, or from an image produced by MOVxSYS (see 6.16) to the boot tracks of a drive. + + +### 6.6.1 Using BPSYSGEN + + +#### 6.6.1.1 Interactive Operation + +The basic Interactive mode is initiated by simply entering the program name at the Command Line prompt as: + +`BPSYSGEN` + +You will first be prompted for the source drive from where to obtain a bootable system image, then for a destination drive to save the image. To provide a visual clue that the program is executing, a series of periods is printed on the screen with each period representing a physical sector of data. At the conclusion of the operation, the program exits to the Command Processor prompt. + +A binary file produced by MOVxSYS (see 6.16) may be placed on the system tracks of a hard or floppy disk by specifying the file name as a command line argument as: + +`BPSYSGEN B:ZSDOS64.BIN` + +When activated in this manner, you will be prompted for the destination drive letter after BPSYSGEN loads the image file and validates it as a valid system image. Alternatively, you may replace the file name with a drive letter followed by a colon to automatically load the image from a specific drive, and be prompted for the destination drive. + + +#### 6.6.1.2 Command Line Operation + +A single operation may be completely specified from the command line arguments thereby avoiding drive prompts. When invoked in this manner, the first argument specifies the source for the system (drive designator or file) with the second argument being the drive specification on which to place the bootable system image. The syntax for the Command Line method of operation is: + +`BPSYSGEN {d: | fn[.ft]} d:` + + +### 6.6.2 BPSYSGEN Error Messages + +`*** Read Error` + +An unrecoverable error was encountered reading either the boot tracks of a drive, or a specified bootable file. + +`*** Bad Source!` + +The source drive does not exist or could not be selected. + +`*** Write Error` + +An unrecoverable error was encountered writing the boot tracks of the specified destination drive. + +`*** Bad Destination!` + +The destination drives does not exist or could not be selected. + +`*** No System!` + +There are no valid System Tracks on the Source or Destination Drive, or an anomalous condition (more than 3 reserved tracks) was detected. + +`*** Can't Open Source File!` + +The specified boot image file could not be located, or an error occurred during the attempted File Open. + + +## 6.7 COPY - Generic File Copy Utility + +`COPY.COM` is a file copy program derived from the ZCPR3 MCOPY tool written by Richard Conn. It blends the many modifications by Bruce Morgen, Howard Goldstein and others in MCOPY48 with further enhancements in the spirit of the ZSDOS environment. File date stamping is supported for the full range of stamping capabilities provided by ZSDOS. A user-definable "Exclusion list" is now supported to prevent copying of specific files or file groups, and two options to ease file backups with the Archive bit have been added. COPY is also more user-friendly than MCOPY, and provides increased error checking and user feedback. + +COPY only operates in the Command Line Driven or Expert mode. As with the other utilities provided with ZSDOS, COPY displays a short Help message when invoked with a double-slash argument as explained in Section 1.2. The Help message also includes a list of available options along with the effect of each when included as command line arguments. + +While COPY is ready to run without special installation procedures, you may wish to change the default parameters to customize it to your operating style. In this manner, you can minimize the number of keystrokes required to perform routine operations by avoiding passing many options on the command line. To set default conditions, insure that `COPY.COM`, `COPY.CFG` and `ZCNFG.COM` are available to the system, and execute ZCNFG as described in Section 4.8 of the ZSDOS 1.0 Manual. + + +### 6.7.1 Using COPY + +The basic syntax for COPY follows the original CP/M format by listing the destination drive/user, an equal sign, then the source drive/user and file name. An alternate syntax added by Bruce Morgen in MCOPY48 permits specifying transfers in the "Source-Destination" form popularized in MS-DOS. In this alternate form, you first enter the source drive/user and filename, a space, and then the destination drive/user and optional filename. Using the normal symbology, the syntax is summarized as: + +`COPY dir:[fn.ft]=[dir:]fn.ft,... [/]options` + +or + +`COPY [dir:]fn.ft dir:,... [/]options` + +If no destination filename is specified, a number of unique files may be copied to a specified directory by catenating source files separated with commas. Where a destination file name is specified, both source and destination file names and types must be free of wildcard characters. This popular "Rename" feature in a copy was a much requested addition to the ZSDOS copy utility. Options to tailor the actions of COPY may be appended after the source file list. + +Yet another method of transferring files was retained from the original MCOPY roots. If no destination drive/user is recognized in the command line arguments, all referenced files will be copied to a default drive/user location which is contained in the header portion of COPY. The default location is Drive B, User 0 in the distribution program, but may be changed as described below. If options are desired with this syntax, the slash option delimiter is mandatory. The syntax for this method is summarized as: + +`COPY [dir:]fn.ft,... /options` + +Various configuration options detailed later allow you to customize COPY to suit your operating style. For example, status displays of each operation may be suppressed for a "Quiet" mode, verification that copied files match the original (or at least produce the same error check code) may be enabled or disabled, etc. If a method of Date and Time Stamping is active under ZSDOS, the original Stamp information will be transferred to the destination file. The following examples in the "Verbose" method of operation will serve to illustrate by copying a file from the current Drive and User area to the same drive, User 10. + +```generic + COPY ZXD.COM 10: + +COPY Version 1.71 (for ZSDOS) +Copying C2:ZXD .COM to C10: + -> ZXD .COM..Ok (Dated) Verify..Ok + 0 Errors +``` + +In this case, No file of the same name existed in the destination area, but some form of File Stamping was active, so the source Stamp information was successfully transferred to the destination. Performing the same activity with the other syntax now produces: + +```generic + COPY 10:=ZXD.COM + +COPY Version 1.71 (for ZSDOS) +Copying C2:ZXD .COM to C10: + -> ZXD .COM Replace Same (Y/N)? Y..Ok (Dated) Verify..Ok + 0 Errors +``` + +Since COPY now detected a destination file of the same name, and File Stamping as well as duplicate checking (another option flag) were in effect, COPY compared the Last Modified dates for both source and destination files. Finding a match, the prompt "Replace Same" was issued, and received a (Y)es response to copy the file anyway. Other responses, depending on the results of the date comparison are "Replace Older", which means that an older file exists on the destination, and "Replace Newer" which means that you are trying to replace a newer file on the destination with an older version. + +A similar error check is made if a duplicate file is found to determine if the file was found with the PUBlic Attribute bit. If a Public file is detected on the destination drive, a warning to the effect is printed. Answering Yes to replacement at this point will result in a Read-Only error unless ZSDOS has been set to permit writes to Public Files (see 2.8.3 of the ZSDOS 1.0 Manual). + +As stated earlier, COPY has no Interactive mode of operation per se, but the Inspect option provides a means to select files for transfer in a somewhat interactive manner. In this mode, all files selected by the file specification in the command line are displayed, one at a time, and you may enter "Y" to copy the file, "N" to Not copy the file, or "S" to forget the rest of the selected files. An example copying all files from the current Drive and User to User 10 is: + +```generic + COPY *.* 10: /I + +COPY Version 1.71 (for ZSDOS) +Copying C2:????????.??? to C10: + Inspect -- Yes, No (def), Skip Rest +BU16 .COM - (Y/N/S)? Y +BU16 .MZC - (Y/N/S)? N +COPY .COM - (Y/N/S)? Y +COPY .Z80 - (Y/N/S)? S +``` + +If operating in the Verbose mode, status on each file will be printed as the copies progress. + + +### 6.7.2 COPY Options + +Several option characters are available to customize COPY operations. Most of these options may be set as default conditions using Al Hawley's ZCNFG Configuration Utility. Alternatively, you may enter any of them on the command line to alter the functions of a single operation. The command line option characters are as follows: + +| Option | Description | +| :---: | :--- | +| `A` | Archive | +| `E` | Test for File Existence | +| `I` | Inspect Files | +| `M` | Multiple Copy | +| `N` | No replacement if File exists | +| `O` | Test Existence of R/O Files on Destination | +| `Q` | Quiet | +| `S` | exclude System Files | +| `V` | Verify | +| `X` | Archive Only if File exists | + +From the brief syntax summaries listed above, you will note that the standard option delimiter, a slash, is optional if both source and destination specifications are listed on the command line. If only one specification is listed, is when copying to the default drive, the delimiter is Mandatory. Each option is described in the following paragraphs. + + +#### 6.7.2.1 Archive Option + +When this option is active either by specifying in the command line or as a default, only files which do Not have their Archive Attribute set will be selected. After the selected files are copied, the Archive Attribute on the Source file will be Set to indicate that the file has been "Archived". When used in conjunction with the default drive and user settings, the A option provides a simple method of archiving files in a single user area. The default for this option is Off, for No control of selection by the Archive Attribute. Adding the A option to the command line reverses the configured setting. + +It should be noted that this option is incompatible with the "M" (Multiple Copy) option. The first copy operation will set the Archive bits on selected files, and they will not appear in subsequent copies. + + +#### 6.7.2.2 File Existence Option + +This option controls the test for an already-existing file on the destination drive by the same name. Adding the E option to the command line argument reverses the configured setting. The default in the ZSDOS distribution version is On, or Check for Existing files. This option does not affect the check for PUBlic files on the destination drive, which is always active. + + +#### 6.7.2.3 Inspect Files Option + +As illustrated previously, the I option provides a means of selectively copying files, without entering the name of each file. The distribution default for this option is Off, or do Not inspect the selected file list. Specifying this option on the command line argument list reverses the configured setting. + + +#### 6.7.2.4 Multiple Copy Option + +This option may be used to copy a file, or group of files to the same drive several times, as when making several copies of the same file group on different disks. A prompt is given before each copy operation begins, and you may abort at the prompt, or change disks before beginning the copy. The distribution default for this option is Off, for No Multiple copying. Adding the M option to the command line argument list reverses the configured setting for this option. + + +#### 6.7.2.5 No Replacement Option + +When added as a command line argument, the N option will not allow replacement of a file which already exists on the destination Drive/User. This option cannot be configured, and always assumes the same initial state when COPY is called. The default initial state for this option is Off to permit replacement of existing files. + + +#### 6.7.2.6 Read-Only File Test + +This option, when added as an argument, reverses the configured setting of a flag which checks for the existence of file(s) satisfying the specified name and type with the Read-Only attribute set. If this flag is active and a Read-Only file is located satisfying the criteria, the file will not be automatically overwritten. The E (File Existence) flag will still dictate how other files are handled. + + +#### 6.7.2.7 Quiet Option + +When used on a system with ZCPR3, this option causes a reversal in operation of the ZCPR3 Quiet flag. If the ZCPR3 Quiet flag is active, COPY with the Q option operates in a Verbose mode. If you do not use ZCPR3, or the ZCPR3 Environment defines the Quiet flag as inactive, this option will disable unnecessary console messages for a Quiet mode of operation. There is no default condition for this option, and it is only effective for a single call of COPY. + + +#### 6.7.2.8 System Files Option + +This option controls whether or not files with the SYStem Attribute set will be located by COPY. The distribution default is Off to include SYStem files in COPY file lists and permit copying of such files. The default may be configured as described below, and the default may be reversed by adding an S in the command line option list. + + +#### 6.7.2.9 Verify Option + +To add a measure of confidence that no errors occurred in a COPY operation, the Verify option may be activated. When active, the destination file is read in order to compute a Cyclic Redundancy Check (CRC) word. This word is then compared to a value calculated when reading the source file. If the two values match, you can be reasonably sure that the destination file is a true copy of the source file. The distribution default for this option is True to verify each file copied. This option may be changed by configuration, or reversed by adding a V to the command line option list. + + +#### 6.7.2.10 Archive if Only if File Exists Option + +Occasionally, you may wish to update frequently archived files to the same destinations in a simpler manner than naming each file, or by using the Inspect option. The X option was created for just this purpose. When this option is added, COPY first searches the source directory for files which have not been archived, then checks the destination directory for each file. If a match is found, the file is copied, and the source file deleted, unless it is marked as Read-Only. There is No configurable setting for this option which is always assumed to be OFF when beginning COPY. + + +## 6.8 EMULATE - Alien Disk Emulation Utility + +EMULATE locks any or all Floppy Disk Drive(s) to specified formats, native or alien, from a Database of formats. It may also be used to display current settings and restore drives to auto-selection if the Bios was assembled with the AutoSelect option (see 4.2). The Floppy Disk format information is contained in a file named ALIEN.DAT whose use is shared with BPFORMAT (see 6.4). This sharing of a common database of formats allows formatting, as well as reading and writing of a large number of the hundreds of formats used by CP/M vendors over the years. + + +### 6.8.1 Using EMULATE + +This utility is only usable with B/P Bioses which have been assembled with the Auto-Select option (`AUTOSEL`) active. This is the normal mode for release versions of B/P Bios, although some versions placed on the boot tracks of floppy disks may have a scaled-down complement of built-in formats to reduce the system image size (see 4.3). EMULATE can be executed either in an interactive query/response mode or in a command line "expert" mode with arguments passed on the command line. The EMULATE syntax is: + +| Command | Description | +| :--- | :--- | +| `EMULATE //` | Print Built-in Help Summary | +| `EMULATE [/]X` | List Current Floppy Format Settings | +| `EMULATE [/]U` | Return All Floppies to Autoselect | +| `EMULATE` | Execute in interactive Query/Response mode | +| `EMULATE d[:]` | Select format of Drive d: interactively | +| `EMULATE d[:] [nn]` | Set Drive d: format to entry nn (expert) | + +To keep the numbering of formats in the Database file constant, thereby allowing the expert mode of configuration, all formats in the `ALIEN.DAT` file are loaded without validation against the actual drive parameters. Once a format is selected, the required drive characteristics (disk size, number of sides, speed and number of tracks) are compared to the physical drive parameters contained in the B/P Bios header structure (see 5.2.1, `CONFIG+35`). If the selected format can be accommodated by the physical drive, then the format information is loaded into the Extended DPH/DPB fields for the specified drive and the format locked to prevent re-assignment on warm boots. + +The following formats are currently included in the ALIEN.DAT file, the source code for which is included in the distribution version of B/P Bios as ALIEN.LIB: + +```generic + 1 Actrx SSDD 2 Ampro SSDD 3 VT180 SSDD 4 H-100/4 1D + 5 H89/40 1S 6 H89/40 1D 7 H89/40 1X 8 Kaypro 2 + 9 Osborne 1S 10 Osborne 1D 11 Ampro DSDD 12 H-100 DSDD +13 H89/40 2D 14 H89/40 2X 15 QC-10 DSDD 16 Kaypro 4 +17 MD-3 DSDD 18 PMC-101 19 Sanyo 1000 20 TV 802/803 +21 XBIOS-3 2D 22 XL-M180 T2 23 Ampro SSQD 24 DEC Rainbo +25 Eagle-IIE 26 H89/80 1D 27 H89/80 1X 28 Ampro DSQD +29 Amstrad WP 30 H89/80 2D 31 H89/80 2X 32 XBIOS-4 2Q +33 CCS SSDD 34 IBM 3740 35 Bower 8"1D 36 TTek SSDD +37 Bower 8"2D 38 CCS DSDD 39 TTek DSDD2 40 TTek DSDD1' +``` + +Current drive format allocations may be examined at any time with the X option which will list the 10-character name the format assigned to each floppy drive in the system, or state that it is Autoselecting. The U option removes all fixed formats, returning them to Autoselecting. + + +### 6.8.2 EMULATE Error Messages + +`+++ Can't Open Database File +++` + +EMULATE could not locate the `ALIEN.DAT` file in the currently logged directory. Solutions include setting the PUBlic attribute of `ALIEN.DAT` and insuring that the Dos Path includes the drive containing the file. + +`+++ Format Not Supported on this drive!` + +Self-explanatory. Common causes of this error are selecting an 80-track format on a 40-track drive, or an 8" format on a 5.25" drive. Check the `ALIEN.DAT` source code to determine any needed data on the exact drive requirements for each format. + + +## 6.9 HDBOOT - Hard Drive Boot Utility (tailored) + +HDBOOT is a specialized routine which is only available for those computers which feature the ability to boot from Hard Drives from a cold start such as the YASBEC and Ampro Little Board computers in the initial version. HDBOOT is a customized utility which is tailored for specific versions and will not execute on B/P Versions which it does not recognize. It modifies the boot record of a Floppy Disk System image placed on a drive by BPSYSGEN (see 6.6) to allow the system to be started from the Hard Drive at power-on or from a system Reset. + + +### 6.9.1 Using HDBOOT + +HDBOOT is extremely simple to use, and accesses the B/P Bios Data structures of the target system for any system-specific data required, such as initialization parameters for the Shugart/Xebec controller types. When invoked, the existing system is checked to insure that it is a valid B/P Bios version. If valid, you will be asked to specify which of the three possible physical SCSI units to access, and from there on the operation is automatic. A sample screen for a successful execution of this utility is: + +```generic +/---------------------------------------------------------------------------\ +| B/P HDBOOT Utility V1.0 31 Aug 92 | +| Copyright 1992 by H.F.Bower/C.W.Cotrill | +| | +| Configure which unit for Booting [0..2] : 0 | +| | +| Target Controller is : Seagate SCSI | +| ...Reading Boot Record... | +| ...Writing Boot Record... Ok.. | +| | +| A0:BASE>_ | +\---------------------------------------------------------------------------/ +``` + +It should be noted that a system must have been placed on the target unit with BPSYSGEN (see 6.6) before executing this utility, or an error message will be issued and the operation aborted. + + +### 6.9.2 HDBOOT Error Messages + +`*** No System!` + +The specified target Unit does not contain a valid Boot System. Place a valid Boot Track system on the unit with BPSYSGEN and execute HDBOOT again. + +`*** Invalid Unit Number ***` + +The Unit number specified on the command line is invalid. Either it is not "0", "1" or "2", or the unit is not active. + +`*** Invalid Boot Record ***` + +The Boot Record existing on the specified Unit is not valid for this type of Computer. Normal causes are no system currently exists on the specified unit or the system in place is not a valid one for this system. Both of these may be corrected by placing a system on the first physical partition of the unit with BPSYSGEN (see 6.6) + +`+++ Image is Not B/P Bios, or Wrong Version +++` + +The image read from the Boot Tracks of the specified system was not a valid version of B/P Bios. The two most common causes of this are; not placing a Boot System on the System Tracks with BPSYSGEN, or altering the fixed data structures of the Bios source code in a way which violates the standard layout resulting in a system which cannot be recognized. + +`+++ Unit Not Active! Run BPCNFG to Set Drives.` + +The specified Hard Drive Unit (0, 1 or 2) was not tagged as an active unit. This can be changed by first executing BPCNFG (see 6.2) on the executing memory system, then re-invoking HDBOOT. + + +`+++ Not B/P Bios ... aborting +++` + +An attempt was made to execute this utility on a system which was not running under B/P Bios. Boot the system with a B/P Bios-equipped system and try again. + + +`*** Read Error` + +An unrecoverable error occurred while trying to read the target system's Boot Record. This is most often due to media errors on the first cylinder of the target unit and cannot be rectified. Another cause may be an incorrect definition of the physical characteristics of the controller and/or drive. + + +`*** Write Error` + +An unrecoverable error occurred while trying to write the modified Boot Record to the Hard Drive unit. If a second attempt at execution is unsuccessful, it probably indicates either an incorrect physical definition of the Hard Drive unit, or unrecoverable media errors on the first cylinder of the drive. + + +## 6.10 HDIAG - Hard Disk Format/Diagnostic Utility + +HDIAG is a generic B/P Utility program to Run Diagnostics, Format, Verify and examine Hard Drive parameters using any of the defined controller types in a B/P Bios system where such capabilities are defined. The ability to select the controller type in the beginning of the program is allowed to enable you to check and initialize drives using controller types other than that defined in the executing Bios for added flexibility. The following controller types are handled in the initial B/P Bios release: + +- Adaptec ACB-4000A +- Shugart 1610-3 / Xebec 1410A +- Seagate SCSI +- Shugart 1610-4 (Minimal SCSI) +- Conner SCSI +- Quantum SCSI +- Maxtor SCSI (others added in later releases) + + +### 6.10.1 Using HDIAG + +This utility tool only operates in an interactive mode, so it is simply invoked with its name and no arguments (other than the standard double-slash Help request). When activated, it reads the controller type from the B/P Bios header structure and asks you if this is the controller type you wish to use. If you wish to use a different controller type, such as diagnosing a Seagate SCSI drive from a system which has an Adaptec controller for normal use, you may alter the controller definition for the remainder of the HDIAG session. The interaction through to the main loop prompt may appear as: + +```generic +/---------------------------------------------------------------------------\ +| B/P Bios Hard Disk Utility V1.3a, 14 Jun 97 | +| | +| Controller = Adaptec Ok ([Y]/N) ? : Y | +| | +| Functions: F - Format | +| V - Verify | +| D - Run Diagnostics | +| P - Show Disk Parameters | +| | +| Select (^C or ESC to Quit) : | +| | +\---------------------------------------------------------------------------/ +``` + + +#### 6.10.1.1 Show Disk Parameters _[ P ]_ + +If you are running HDIAG on a Hard Drive Unit which is already defined in the Bios and was previously formatted, or one of the self-identifying SCSI drives, then you may view the current drive parameters with the P command. The display varies with the controller type and the amount and type of information that is available. Some of the data may be from Bios definitions, and other data from either the controller (e.g. Adaptec) or the drive electronics (SCSI or SCSI-2). Samples of the forms of information are: + +SCSI1 setting +```generic +Unit : 0 CONNER CP3100-100mb-3.5 + + Total Blocks = 204864 (12804 Eq. Tracks) + Sctrs/Track = 33 + Sector Size = 512 + Interleave = 1 + # Cylinders = 776 + Num of Heads = 8 +``` + +Adaptec ACB-4000, Syquest SQ-312 10 MB +```generic +Unit : 0 + + Total Blocks = 22140 (1383 Eq. Tracks) + Sctrs/Track = 18 + Sector Size = 512 + # Cylinders = 615 + Num of Heads = 2 + Reduced Wrt. = 615 + Precomp. Cyl = 615 + Step Rate = 12 uS Buffered + Media type = Removable + Landing Zone = 615 +``` + +#### 6.10.1.2 Hard Disk Diagnostics _[ D ]_ + +Some drives feature built-in diagnostics routines which test the unit's electronics and media. Other systems simply execute the power-up sequence which generally includes a sequence of self-tests. Normally, only the re-initialize function can be relied on, and is included in the standard suite of HDIAG functions with this command. Sample output resulting from this function is: + +```generic + Select (^C or ESC to Quit) : D + Unit Number [0..2] (^C or ESC to Abort) : 0 +Re-Initializing Unit : 0 ..Ok + ..Waiting for Ready.. +``` + +Pauses may occur in the execution of the sequence, most noticeably after the status prompt stating "Re-Initializing Unit" before the "..Ok" appears. Depending on the exact system, this time is often when the actual controller electronics are being checked, and may involve moving the drive head which can be a time consuming task. There is also a pause very often after the prompt "..Waiting for Ready..", particularly if the heads were moved and must be repositioned over the outer cylinder of the drive. When the drive returns a ready status, then the main selection menu is again displayed and HDIAG is ready for another command. + + +#### 6.10.1.3 Verify Drive Media _[ V ]_ + +This function permits evaluating the condition of a formatted drive to identify defects to a varying extent. By using a mix of defeating the Error Correcting code where possible, and enabling or disabling the Individual Sector checks, a relatively extensive, albeit often time consuming, non-destructive status of the drive unit may be obtained. + +```generic + Select (^C or ESC to Quit) : V + Unit Number [0..2] (^C or ESC to Abort) : 0 + Verify Individual Sectors (Y/[N]) : N +Verifying Unit : 0 CONNER CP3100-100mb-3.5 + +Block 891 + ...aborted... +``` + + +#### 6.10.1.4 Format Drive _[ F ]_ + +Setting all of the data storage areas on the disk to a constant value, and renewing the control information on the drive is the purpose of this function. It is destructive, and any data on the drive will be lost. For this reason, several checks are included in the program to insure that you do not inadvertently activate this command. + +While most of the information needed to format a drive is available from either the built-in data which can be read from the drive or controller, or from the Bios data areas, some items are still required from the user. You will therefore be asked to provide any data necessary to format the drive. In the older SASI systems (1610-3, Xebec, etc) this can amount to a considerable number of entries. Fortunately, formatting of drives is not often required, and the method of formatting used in HDIAG is flexible enough to allow a wide range of devices to be connected. + + +### 6.10.2 HDIAG Error Messages + +Several error messages will be presented for specific problems encountered in the operation of HDIAG. Many of the messages will be specific to certain operations, and others will change the specific information depending on the capabilities of the controller type selected. The most general of these concerns the SCSI/SASI Sense command. The Newer SCSI systems use "Extended Sense" which can return more information than the basic Sense values. When Extended Sense is detected, the "Key" value is displayed in many error messages rather than the basic "Sense" byte. Consult the programming manual for the specific controller or drive for the specific meanings of these bytes. Such a message will usually be displayed as: + +`Error! (Comnd = xx) Sense: xx` + +or + +`Error! (Comnd = xx) Key = xx` + +Also, to provide additional information during operation of many of the functions, the raw status byte read from the controller when an error occurs is also displayed as part of an error message as: + +`(status = xxH)` + +The interpretation of the hexadecimal byte presented may be gathered from the programming manual for your specific drive or controller type. + +`+++ Not B/P Bios ... aborting +++` + +An attempt was made to execute HDIAG under a Bios other than B/P, or modifications made to the Bios altered the locations or values needed to correctly identify the system. + +`**** SCSI Block Length Error !` + +This fatal error message will be displayed if the Command Descriptor Block returned from the Bios is too small to allow the extended commands needed for the requested operation. It usually results from alterations to the Hard Driver module which change necessary values. + +`**** Controller Not Readable !` + +HDIAG could not read parameters from the drive or controller. This will only appear in the R (Read Drive Parameters) function, when the controller type is "Owl". + +`**** No Diagnostics for : ` + +The Controller selected cannot perform Diagnostics in a way that HDIAG can access or perform the needed functions. This will only appear in the D (Perform Diagnostics) function. + +`**** Verify Not Available !` + +The specific drive/controller selected has not been defined adequately to allow verification of the drive. This will only appear in the V (Verify) function when the controller type is "Owl". + +`+++ 1610-3 Initialization Error...Sense = xxH` + +An error was detected sending the initialization string to a Shugart 1610-3 or Xebec 1410A controller. Insure that this is the correct type of controller setting for your hardware configuration. It will only appear in the V (Verify) function. + + +## 6.11 INIRAMD - RAM Disk Initialization Utility + +INIRAMD is a B/P Bios utility that initializes the Directory of a RAM Drive and optionally initializes it for DateStamper (tm), P2DOS, or both types of file stamps. It contains protective features to preclude inadvertent initialization of an already formatted RAM Disk, and may be command line driven for execution from within STARTUP scripts. + + +### 6.11.1 Using INIRAMD + +This utility is designed to be operated with Command Line arguments, but features built-in defaults which can be configured by either overlaying bytes in the beginning of the program with new default settings, or by configuring with Al Hawley's ZCNFG tool. To execute with the default settings, simply enter: + +`INIRAMD` + +The complete syntax for INIRAMD is: + +`INIRAMD [d:][/][Q][D][P]` + + +### 6.11.2 Command Line Mode + +By entering arguments on the Command Line when INIRAMD is invoked, several internal default values can be set to the specific settings desired at the time. The first argument expected when parsing the Command Line tail is a Drive Letter. This is optional and will override the default drive M: built into the program. To specify a drive other then the default, enter: + +`INIRAMD d:` + +Extraneous prompt and status messages can be withheld during execution of INIRAMD by either setting the default "Quiet" flag embedded in the program, setting the "Quiet" flag in the Environment, or passing a Q as an argument when invoking the program. Initializing the RAM Drive in Quiet mode using the default drive is then accomplished by entering: + +`INIRAMD Q` + +You may also specify which types of Date/Time Stamps to add to the RAM drive during preparation with the P (for P2DOS Stamps) and/or D arguments. If not operating in the Quiet mode, INIRAMD notifies you which type(s) of Stamping methods have been added to the RAM Drive after the directory area is initialized to a blank value. Initializing drive M: for both types of Stamps then is initiated by entering: + +`INIRAMD M: PD` + + +### 6.11.3 INIRAMD Error Messages + +`+++ Not B/P Bios ... aborting +++` + +An attempt was made to execute INIRAMD under a Bios other than B/P, or modifications made to the Bios altered the locations or values needed to correctly identify the system. + +`+++ Already Formatted...Proceed anyway (Y/[N]):` + +This warning and prompt will be issued if INIRAMD detected the dummy file name used as a tag that the RAM Drive is already formatted. This is most often seen in systems that contain battery backed-up RAM and INIRAMD is invoked either directly or in a Startup alias script. To minimize the appearance of this message if you desire to have the RAM Disk initialized in the Startup script, include the following: + +| Command | | +| :--- | :--- | +| `IF ~EX M:-RAM.000` | Assume RAM Disk is M: | +| `INIRAMD M:` | Assume RAM Disk is M: | +| `FI` | | + +`+++ Drive d: does NOT Exist` + +Either the default or explicit drive specified in activating INIRAMD was has not been defined to the system. One possibility is that the RAM Drive was swapped for an undefined drive letter. Check the drive assignments with BPCNFG, Option 5 if you wish to check the Drive assignments. + +`+++ Drive d: is Not a RAM Drive!` + +Either the default or explicit drive specified in activating INIRAMD was a valid drive, but was not a RAM Drive. As with the previous error, one possibility is that the RAM Drive was swapped for another drive which was of another type. Use BPCNFG, Option 5 to check the Drive assignments. + + +## 6.12 INITDIR - P2Dos Stamp Initialization Utility + +INITDIR prepares disks for P2DOS-type file stamping. It does this by replacing every fourth entry in the disk's directory tracks with a time and date entry which is prefixed with a special character (hexadecimal 21). Existing directory entries in the fourth position are then shifted to the first entry in the next logical sector and the initialized directory sectors are written back to the disk. + +| **W A R N I N G** | +| --- | +| INITDIR should not be run on disks containing valid DateStamper file stamps since it rearranges directory data. To install both DateStamper and P2DOS stamping on one disk, start with a blank disk, or one with no datestamps of either type and run both PUTDS and INITDIR on the disk before using it. Doing otherwise will invalidate any existing stamp data. | + + +### 6.12.1 INITDIR Interactive Mode. + +INITDIR can be run in either an interactive mode by simply entering its name at the Command Prompt, or in "Expert Mode" by specifying a drive letter as an argument on the command line. In the interactive mode, you will be asked for a drive letter which will specify the drive to initialize with P2DOS stamps. + +If the DateStamper `!!!TIME&.DAT` file is detected on the disk, INITDIR issues a warning and asks if you want to proceed or not (see 6.12.2 below). To avoid the possibility of loss of Time and Date Stamp information from DateStamper, this routine should only be run on freshly-formatted or blank drives. The syntax of INITDIR is summarizes as: + +| Command | Description | +| :--- | :--- | +| `INITDIR //` | Print summary help message | +| `INITDIR` | Execute in Interactive Mode | +| `INITDIR d[:]` | Initialize Drive D: | + + +### 6.12.2 INITDIR Error Messages + +`Directory already initialized` + +The selected disk is already prepared for P2DOS stamps. + +`Illegal drive name` + +The character entered was not in the range of "A" thru "P". + +`Not enough directory space on disk` + +The directory on the selected disk is more than three-fourths full. Not enough space is available to support P2DOS file stamps. + +`Directory read error` + +An error was encountered in reading the disk directory. + +`Directory write error` + +An error occurred while writing the initialized directory. It will probably result in loss of file data. + +```generic +--> DateStamper !!!TIME&.DAT File Found <-- + Proceed anyway (Y/[N]) : +``` + +The special DateStamper `!!!TIME&.DAT` file exists on the disk. If other files are also on the disk, most of the DateStamper time and date information will be lost. On freshly-formatted or empty disks, no DateStamper file stamp data exists, so it is safe to answer with a Y and initialize the disk. + + +## 6.13 INSTAL12 - Boot Track Support Utility + + +Install CPR, ZSDOS, B/P Bios in a MOVxSYS "type" image from standard size (2k CCP, 3.5k DOS, ~4.375k Bios) files + +INSTAL12 is the latest modification to the ZSDOS INSTALOS utility distributed with ZSDOS 1.0 which automatically overlays your computer's System Image file, such as `MOVCPM.COM` (CP/M) or `MOVZSYS.COM` (ZRDOS) program, or Absolute System Model file (e.g., `CPM64.COM`) with ZSDOS or ZDDOS to produce a new file containing ZSDOS/ZDDOS instead of your original Basic Disk Operating System. INSTAL12 also allows you to set the defaults of various ZSDOS parameters during the installation process (these parameters may also be changed later with the ZSCONFIG program). + +INSTAL12 is designed to make the installation process as easy as possible. With INSTAL12 you may load files from all drives and user areas from A0: to P31:. Error detection is extensive, and Section 6.13.3 of this manual fully explains all INSTAL12 error messages. Finally, you may safely abort INSTAL12 at nearly all points by pressing Control-C. + +Before using INSTAL12, ensure that any necessary files from your B/P Bios and/or ZSDOS Distribution Disk are present: + +* Microsoft .REL formatted assembly of B/P Bios (MOVCPM = YES) +* ZSDOS.ZRL (if replacing Operating System) +* ZCPR33.REL, ZCPR34.ZRL or other Comnd Proc (if replacing CPR) +* INSTAL12.COM + +The following file from your B/P Bios Distribution Disk, CP/M or ZRDOS System Disk must also be accessible: + +* MOVxSYS.COM (B/P Bios), MOVCPM.COM (CP/M), MOVZSYS.COM (ZRDOS), or System Image file for systems such as the Oneac ON! + + +### 6.13.1 Using INSTAL12 + +To run INSTAL12, most users should simply enter + +`INSTAL12` + +at the Command Prompt. This tells INSTAL12 that you are installing a system segment over a System Image relocation file, such as `MOVxSYS.COM`, `MOVCPM.COM` or `MOVZSYS.COM`. If you need to install a segment over an Absolute System Model file such as a `CPM59.COM`, `ZSYSTEM.MDL`, or Oneac ON! file, you should enter + +`INSTAL12 /A` + +to run INSTAL12 in Absolute mode. INSTAL12 now displays its opening banner and requests the name of a file as: + +`System Image file to patch (Default=MOVCPM.COM) :` + +in Relocatable mode, or + +`Absolute System Model (Default=SYSTEM.MDL) :` + +in Absolute mode. + +You need not enter all of the information; INSTAL12 will fill in any missing items with the default disk, user, or filename. If you simply hit RETURN, INSTAL12 searches the current directory for the default System Image or Absolute System Model file (`MOVxSYS.COM`, `MOVCPM.COM` or `SYSTEM.MDL`). Here are some sample responses: + +```generic +System Image file to patch (Default=MOVCPM.COM) : B3: + (Selects MOVCPM.COM on drive "B" in user area 3) + +System Image file to patch (Default=MOVCPM.COM) : 10:MOVYSYS + (Selects MOVYSYS.COM on the current drive, user 10) + +System Image file to patch (Default=MOVCPM.COM) : C:MOV18SYS.OLD + (Selects MOV18SYS.OLD on drive "C", current user area)` +``` + +Once INSTAL12 finds the requested file, it validates your operating system image. If the CCP, BDOS or BIOS portions of the System Image or Absolute System Model file are invalid, INSTAL12 prints an error message and quits at this point. This may occur if an Absolute System Image was loaded but INSTALOS was invoked without the /A suffix. If both methods of calling INSTAL12 fail, first ensure that your system image or generation program is operating properly. If you are sure that you have a working MOVxSYS, MOVCPM, MOVZSYS, or Absolute Model file that INSTAL12 cannot validate, you will need to contact your distributor who will initiate actions to correct your problem. + +If all values in your operating system file match expected parameters, a summary of those values is displayed. If you specified a System Image file (e.g., `MOVxSYS.COM`), the display should be similar to: + +```generic +Addresses in system image (as seen under DDT) : + CCP : 0980H Map @ 3610H + BDOS: 1180H Map @ 3710H + BIOS: 1F80H Map @ 38D0H +``` + +The addresses shown will probably differ from these, but if both columns display values other than 0000H, INSTAL12 will correctly overlay the three system segment portions of the image with specified files. + +If you specified an Absolute System Model, the display will be similar to: + +```generic +Addresses in system image (as seen under DDT) : + CCP : BC00H + BDOS: C400H + BIOS: D200H +``` + +As above, the addresses will probably differ from those in the example, which are for a 54K system. + +If no error message appears, INSTAL12 has properly validated your file. Next, a menu of choices appears: + +```generic + 1 - Replace CCP + 2 - Replace DOS + 3 - Replace BIOS + 4 - Save and Exit +Enter Selection (^C Quits) : _ +``` + +To install a new B/P Bios image from your assembly, select option 3. You will be asked to enter the name of the file as: + +`Name of BIOS file (Default=CBIOS.REL) : _` + +The default file type is `.REL` and the file **MUST** be in Microsoft relocatable format. When a terminating Carriage Return is entered, either the name you entered or the default will be located. If found, the size will be evaluated against the available space in the image file. Often when adding a B/P Bios to an older system generation program, the bit map portion of the program will be relocated. You will be notified with a message signifying the distance in bytes that the map was relocated. This is simply a diagnostic tool, and you should not be alarmed at the message. Following the message "...overlaying BIOS...", INSTAL12 will return to the main menu for the next command. + +Replacement of the Command Processor with `ZCPR33.REL` or `ZCPR34.ZRL` is identical to Bios replacement, except that no relocation of the bit map is possible. The specified file will either fit and overlay the original, or it will be too large and the program will exit with an error message to that effect. + +For ZSDOS installation, enter a 2. You will be asked for the name of a Disk Operating System file as: + +`Name of DOS file (Default=ZSDOS.ZRL) : _` + +The default file type at this point is `.ZRL`, but operating systems in Microsoft `.REL` format such as distribution versions of ZRDOS are also accepted. As above, you may respond with a full or partial file specification and INSTAL12 will fill in any missing items with the default disk, user, or filename. + +Once the Disk Operating System file is found the following prompt appears: + +```generic +ZSDOS.ZRL Size OK...overlaying BDOS.. +Examine/Change ZSDOS parameters ([Y]/N)? : _ +``` + +At this point, INSTAL12 allows you to change the startup settings of all ZSDOS options. If this is your initial installation of ZSDOS, we recommend that you press N for "No" to bypass this step, and skip the following paragraph. + +If you enter any character other than N or n, the default option in brackets ([Y] for "Yes") is assumed, and INSTAL12 displays the current ZSDOS defaults as: + +```generic + 1 - PUBlic Files : YES + 2 - Pub/Path Write Enable : NO + 3 - Read-Only Vector : YES + 4 - Fast Fixed Disk Log : YES + 5 - Disk Change Warning : NO + 6 - Path w/o System Attr : YES + 7 - DOS Search Path : Disabled + 8 - Wheel Byte Protect : Disabled..Assumed ON + T - Time Routine (Clock) : Disabled + A - Stamp Last Access Time : Disabled + C - Stamp Create Time : Disabled + M - Stamp Modify Time : Disabled + G - Get Date/Time Stamp : Disabled + S - Set Date/Time Stamp : Disabled +Entry to Change ("X" if Finished) : _ +``` + +These options are presented in the same manner by ZSCONFIG, and are fully described in Section 4.10 of the ZSDOS 1.0 manual. + +Once you bypass the configuration step or exit by pressing X, one of the following prompts appears depending on whether you are installing an Image or Absolute Model file: + +`Name to save new system (Default=MOVZSDOS.COM) : _` + +or + +`Name to save new system (Default=ZSSYS.MDL) : _` + +Again, you may respond with a full or partial file specification and INSTAL12 will fill in any missing items with the default disk, user, or filename. If a file with the same name exists, INSTAL12 prompts you for a new name. When INSTALOS has a valid name, it creates your new system file and exits, displaying one of the following messages: + +`..Saving MOVZSDOS.COM` (relocatable) + +or + +`..Saving ZSSYS.MDL` (absolute) + + +### 6.13.2 INSTAL12 Error Messages + +Occasionally INSTAL12 may issue error messages. Most errors result when the files you specified do not conform to INSTAL12' expectations. Often the solution is to run INSTAL12 again, specifying relocatable mode instead of absolute mode or vice-versa. Many INSTAL12 errors will also result from damaged files. If INSTAL12 gives errors in both absolute and relocatable modes, try recopying the source file from masters, or re-assemble the source program and execute INSTAL12 again. + +If all of the above fail, your system files may contain information which INSTAL12 cannot recognize. You may be able to attempt an alternate installation with NZCOM or JetLDR for CPR and DOS segments, but you may need to contact the experts on Ladera Z-Node for assistance with Bios-related problems. + +The following is a summary of all INSTAL12 error messages, their meanings, and some possible remedies. + +`*** SORRY! ZSDOS will only run on Z80 type computers!` + +ZSDOS and its utilities will only operate on processors which execute the Z80 instruction set such as the Z80, NSC-800, Z180 or HD64180. There is no fix for this condition other than to run it on another system. + +`*** Unable to open [filename.typ]` + +INSTAL12 cannot locate or open the system file you specified. First, ensure that the file is at the default or specified drive/user location. If you have specified the file correctly but this error persists, obtain a fresh copy of your system file and try again. + +`*** Can't find CCP/BDOS/BIOS at standard locations !!!` + +The operating system contained in your system file is not a standard CP/M system. It contains a CCP which is not exactly 2 kilobytes long, a BDOS which is not exactly 3.5 kilobytes long, or both. If this message appears, first ensure that your system file has not been damaged. If you still receive this message, contact the authors on Ladera Z-Node or your distributor. + +`++ Image Vector does not match Calculations ++` + +INSTAL12 found an internal error in the image file while installing a MOVCPM-type file. If you did not use the /A option when running INSTAL12, you may be trying to perform a relative installation on an absolute file. Try running INSTAL12 again with the command `INSTAL12 /A`. + +`*** Cannot find legal Relocation Bit Map` + +INSTAL12 was unable to locate a valid relocation bit map pattern in the MOVCPM-type file when installing in Relocatable mode. Non-standard relocatable image files are the general cause for this error. A workaround is to generate an Absolute Model with MOVCPM first, then use INSTAL12 in Absolute (/A) mode on the Absolute Model file. + +`---Can't find [filename.typ].. reenter (Y/[N]) :` + +The replacement file (CCP, BDOS or BIOS) specified cannot be located. Ensure that the drive, user and file name are correct. + +`*** Error in .REL sizing [filename.typ] + Err Code : nn` + +An error occurred during the sizing operation of INSTAL12 on the `.REL` or `.ZRL` file. The `.REL` or `.ZRL` must be in Microsoft relocatable format. Named Common segments other than `_CCP_`, `_BDOS_`, and `_BIOS_` are not allowed, and code and data segments (if any) must not overlap. + +`*** file too large to fit...` + +The size of the relocatable CCP or BDOS is greater than the available space in the image file (2048 bytes for the CCP, 3584 bytes for the BDOS). This error may result if the relocatable file is not in proper Microsoft relocatable format, or if a customized file is used. This error should never occur with the distribution `ZSDOS.ZRL` file, which is exactly 3584 bytes (3.5k) long. + +`*** Error opening : [filename.typ]` + +INSTAL12 could not open the specified relocatable file. Ensure that you selected a valid `.REL` file. + +`*** Error reading : [filename.typ]` + +INSTAL12 detected an error when reading the specified relocatable file. Try recopying the file. + +`*** Error in .REL file : nn` + +An error was found in a relocatable input file while attempting to replace the CCP, BDOS or BIOS portions of your operating system. "nn" is a hexadecimal code which may assist in locating the cause of the error. Contact your distributor if you need help in resolving an error of this nature with the code in the error message. + +`--- That file already exists. Overwrite it (Y/[N])?` + +The file you told INSTAL12 to write to already exists. If you enter "Y" here, INSTAL12 will erase the previous copy and create a fresh file with this name. Enter N to select a new name. + +`*** No Directory Space for [filename.typ]` + +There was not enough directory space for the output file on the selected disk. Send the output file to a different drive by preceding the filename with a drive specifier, or change the disk in the output drive. + +`*** Error writing file. Try again with another disk (Y/[N])? :` + +This message usually results from a lack of disk space on the drive you specified for output. Change disks and enter Y to try again. + + +## 6.14 IOPINIT - IO Package Initialization Utility + +IOPINIT initializes an IOP Buffer defined in the Environment Descriptor to the standard Dummy IOP format and patches it into the Bios Jump Table. It serves the same basic function as the older ZCPR3 method of loading a SYS.IOP file, but was added as a stand-alone routine to do essentially the entire installation of the package. In so doing, additional space was freed in the B/P Bios core code allowing other routines to be added which cannot be removed to external programs. + + +### 6.14.1 Using IOPINIT + +This program should be included near the beginning of the initial STARTUP script for any system in which an IOP is defined. **NOTE:** This routine MUST be run before any programs which change the Warm Boot Jump at location 0! + +No arguments are expected when calling IOPINIT with all values determined from the executing system Environment. The routine responds to the normal double-slash help request as with all support routines. + + +### 6.14.2 IOPINIT Error Messages + +`--- No IOP Buffer defined in Environment ---` + +Self-Explanatory. If the IOP Buffer has been deliberately removed during configuration or assembly, no harm will be caused by executing IOPINIT. + +`--- No Z-System Environment Defined ---` + +This message should NEVER appear since a valid Environment Descriptor is REQUIRED in B/P Bios equipped systems. If it does, one possible cause is incorrect value(s) at critical points within the Descriptor that are used to validate the Environment. + +`*** IOP Already Installed! ***` + +Self-Explanatory. No harm is done to the system, this message is simply for information. + + +## 6.15 LDSYS - System Image File Loader + +LDSYS is the primary utility to activate a System Image file prepared by BPBUILD (see 6.1). It first validates the currently-running system, then loads the image file, places the component parts where they belong in the computer's memory, and executes the Bios Cold Boot routine of the newly-loaded system. Image files may be either banked or unbanked and need not be placed in the currently-logged directory, since LDSYS can access files along the system path, or from Z3-style Path specifications. + + +### 6.15.1 Using LDSYS + +This utility provides the only way to install a banked system in a B/P System, and a simple way to test non-banked systems before final conversion to bootable systems to be loaded onto system tracks using INSTAL12, MOVxSYS and BPSYSGEN. LDSYS expects only a single parameter to be passed on the Command Line, that being the name of an Image file to load. If no File Type is explicitly entered, a type of `.IMG` is assumed. The location of the desired file may be explicitly stated in normal ZCPR3 fashion with either DU: or DIR: prefixes. The overall syntax of LDSYS is therefore: + +`LDSYS [du|dir:]name[.typ]` + +When loading, two summary screens are displayed, the first from LDSYS itself, and the second from the Cold Boot routine in the loaded system after control is transferred from LDSYS to the newly-loaded system. A sample display from a banked system during development when installed on a MicroMint SB-180 is: + +```generic +/---------------------------------------------------------------------------\ +| B/P Bios System Loader Vers 1.0 31 Aug 92 | +| Copyright (C) 1991 by H.F.Bower & C.W>Cotrill | +| | +| CCP starts at : CC80 (0F80H Bytes) | +| DOS starts at : DC00 (0F00H Bytes) | +| Banked Dos at : 1080 (0500H Bytes) | +| BIOS starts at : EB00 (0880H Bytes) | +| Banked Bios at : 1580 (1269H Bytes) | +| | +| ...installing Banked System | +| | +| SB180 B/P 60.25k Bios Ver 0.6 26 Jan 92 (Banked) with: | +| | +| ZCPR3+ Env | +| ZSDOS Clock | +| Hard Disk Support | +| Warm Boot from RAM | +| RAM Disk (M:) | +| Full Error Messages | +| _ | +\---------------------------------------------------------------------------/ +``` + +All messages in the above sample screen through the line "...installing Banked System" are printed by LDSYS. All subsequent lines in the above screen are displayed from the newly-loaded Bios. During alteration, or modification of a new system, this subdivision in the display areas may be a clue to any difficulties encountered. The position of the cursor at the bottom of the sample screen is the point at which the new Bios, now in control, attempts to load the Startup file defined in the B/P Header. If none is found, additional initialization will not be performed, and you will see only the prompt for Drive A, User 0. + + +### 6.15.2 LDSYS Error Messages + +`*** No file specified ! ***` + +LDSYS was called without a specifying file to load. You may reinvoke it directly with the ZCPR "GO" command as: `GO filename` or call it in the normal fashion specifying an image file to load. + +`--- Ambiguous File: fn[.ft]` + +At least one question mark (or expanded asterisk) was detected in the specified file to load. Re-execute with an unambiguous file name. + +`--- Error Opening: fn[.ft]` + +The specified image file could not be located. Common causes for this are a mismatch in the file name, no file with the default type of `.IMG` or an inability to find the file along the Dos Path or in a PUBlic directory. + + +## 6.16 MOVxSYS - Boot Track System Utility + +This routine is a program to generate a bootable system image for the boot tracks of a Floppy or Hard Disk. It is customized for each type of hardware system using the B/P Bios. The generic name MOVxSYS translates to a specific name reflecting the standard name ID, examples of which are: + +| Utility | Description | +| :--- | :--- | +| `MOVYSYS` | YASBEC | +| `MOVAMSYS` | Ampro Little Board | +| `MOV18SYS` | MicroMint SB-180 | + + +### 6.16.1 Using MOVxSYS + +This program is patterned after the original `MOVSYS.COM` distributed with most Digital Research CP/M 2.2 systems, but extensively updated to reflect the Z-System standard Help, entry of a base address or system size in kilobytes, and additional checks needed to insure B/P standards. + +Two basic parameters may be passed to this program as arguments on the command line. The first specifies the system size in either the equivalent number of kilobytes in an equivalent CP/M 2.2 system, or as the base address of the Command Processor. MOVxSYS parses the first element to determine if the value is a Hexadecimal number ending in the letter "H", and assumes that the value specifies a starting address if so. Valid addresses must be greater than 8000H to insure that the resident portion of the operating system in the Common Memory area. If the argument is not a Hexadecimal address, it is assumed to be a number of kilobytes in the range of 39 to 63. These sizes are based on the "standard" CP/M component elements of 2k bytes for the Command Processor, 3.5k bytes for the Basic Disk Operating System, and at least 1.5kbytes for the resident Bios portion. Several checks are performed within MOVxSYS and the initial executing portion of the Bios (Cold Boot) to detect invalid locations and incorrectly sized data areas. + +The second parameter which may be specified on the command line is an optional asterisk ("*") or File Name and Type after the size specification. If an argument is present, one of two actions will be taken. The Asterisk instructs the program to relocate the system image to the specified size, and simply retain it in memory upon exitting without saving the image to disk. Any other characters will specify the name of a file under which name the image should be written to disk. If no second argument is given, the image will be written under a file name of SYSnnK.BIN where "nn" will be the number of kilobytes in the system size described above rounded down to the nearest even number. + +Placing a system image on the Boot Tracks of a disk is done by BPSYSGEN (see 6.6) which may be done by immediately following MOVxSYS (invoked with the asterisk argument) by BPSYSGEN using the "Image in Memory" selection, or by specifying a file output from MOVxSYS, and invoking BPSYSGEN with the name of the resultant file. + +If you reconfigure the Bios for your system with the goal of modifying the Boot System, you must assemble B/P Bios in the Non-Banked Mode by setting the `BANKED` equate to NO, and setting the `MOVCPM` equate to YES in the `DEF-xx.LIB` file (see 4.2). The revised Bios may then be added to `MOVxSYS.COM` with INSTAL12 (see 6.13) to produce a customized Boot System reflecting your tailored needs. Refer to Chapter 3 for a more complete description of the installation process. + + +### 6.16.2 MOVxSYS Error Messages + +`**** Start < 8000H !!!` + +A size value or CPR Starting address was specified which results in a base address less than 8000H. Since the lower 32k of memory (0..7FFFH) may be banked, the CPR MUST be in the upper half of memory. Execute the program again with an adjusted size specification. + +`**** Create Error !` + +The program could not create the specified Binary output file. Possible causes are a full directory, Write Protected diskette, or bad media or drive. + +`**** Write Error...Exiting` + +An error occurred while writing the specified Binary output file. Possible causes are a media or drive error, or a disk with inadequate storage space for the file. + +`**** Close Error !` + +An error occurred while attempting to close the specified Binary output file. This is usually due to a media or drive error. + +`**** Size must be in 39..63 !!` + +MOVxSYS was invoked with an invalid size (number of K) specification. Execute the program again with an adjusted size specification. + +`**** Bad Syntax !!` + +The program became confused and could not properly decide what you wanted it to do. Review the built-in help by entering: `MOVxSYS //` and follow the syntax listed. + + +## 6.17 PARK - Hard Drive Head Park Utility + +PARK is a simple B/P Utility routine that moves the Hard Drive heads on all drives to the designated landing zone (also called shipping or park zone) if defined for the type of Controller/Drive in your system. When all drives are parked, the utility executes a HALT instruction which requires a hardware reset or power-off/power-on sequence to overcome. To avoid the possibility of Hard Drive damage by removing power from drives while the heads are positioned over data storage portions of hard drives, PARK should always be executed prior to turning your computer off. This recommendation is particularly important for drives which do not feature automatic hard parking, or where such hardware features have failed. + + +### 6.17.1 Using PARK + +This utility is simply called with no arguments, and sequentially scans all three possible Hard Drive units, executing the SCSI "Stop Unit" command on each. When all three units have been processed, the processor disables interrupts and executes a HALT instruction to prevent the units from becoming reactivated by subsequent instructions. Normally, only cycling the power or pressing the Reset button on the computer will allow processing to resume. Developing the habit of executing HALT before turning your computer off may result in increased life from your hard drives, and should become routine. + +This utility is a specialized version of SPINUP (see 6.20) which permits individual units to be turned off and on during normal operation. + + +### 6.17.2 PARK Error Messages + +`+++ Not B/P Bios ... aborting +++` + +An attempt was made to execute PARK under a Bios other than B/P, or modifications made to the Bios altered the locations or values needed to correctly identify the system. + +`+++ Can't Park this type of Controller! +++` + +PARK was executed with a type of Controller or drive in the Bios that does not implement the "Stop Unit" SCSI function. + +`**** SCSI Block Length Error !` + +The Bios does not support the Extended Commands necessary to park the heads using the "Stop Unit" SCSI Function. This is most probably due to changes during an edit/assembly of the Bios which altered either the Command Descriptor Block size, or the Hard Drive function which returns the values. + + +## 6.18 SETCLOK - Real-Time Clock Set Utility + +This utility provides a means of setting a B/P Bios clock from a physical clock contained in the ZSDOS CLOCKS.DAT library. It presents a similar interface to the ZSDOS 1 utility TESTCLOK from which it was derived. + + +### 6.18.1 Using SETCLOK + +SETCLOK is invoked by entering its name with an optional Clock Driver Number. For initial testing, or trying different clocks (always a dangerous procedure), simply enter the utility name as: + +`SETCLOK` + +You will be asked whether to extract clocks from a library. If you are using a custom clock, answer No. If you wish to use a clock from the prepared ZSDOS library, enter Yes which is the default setting if a Carriage Return is entered. You will also be asked for the location (Drive/User) of the clock file or library. This prompt sequence may appear as: + +```generic +Extract Clock from Library ([Y]/N) : _ +Location of CLOCKS.DAT [B0:] : _ +``` + +Drive B, User 0 illustrated in the above sample prompt will probably differ in your system with the current drive and user always shown as the default location. If the file is on the currently-logged drive and PUBlic, it will also be found without specifying a unique User area. If the default reflects the location of the `CLOCKS.DAT` file, or a location accessible via the PUBlic feature, simply enter a carriage return, otherwise enter the location of `CLOCKS.DAT`, followed by a colon and a carriage return. A list of over 40 available clocks will appear. To select one of these clock drivers, enter the number corresponding to the clock, and the program will do the rest. Various messages will be displayed as the clock driver is loaded, linked and executed. If all goes well, the final message will be the Date and Time read from the clock followed by message that the B/P Bios Clock was Set Ok. + +Alternatively, a clock driver may be selected for automatic execution according to a specification on the command line. To use this mode, the `CLOCKS.DAT` file must either be in the currently-logged Drive and User, or on the current drive with the PUBlic Attribute bit set. the syntax for this method of setting the B/P Bios clock is: + +`SETCLOK nn` + +where "nn" is a number corresponding to one of the clocks in the `CLOCKS.DAT` file. This method of operation may be used to set the Bios clock within an alias script such as `STARTUP.COM` commonly used when the computer is first booted. + + +### 6.18.2 SETCLOK Error Messages + +Some of the errors in the SETCLOK utility are generated by the top-level program. These errors consist of: + +`+++ This is only for Z80 type computers!!!` + +This routine will only operate with Z80 or compatible processors since it is a B/P Bios utility which is also restricted to these types. + +`-- Error in locating Clock file` + +This routine could not find the `CLOCKS.DAT` Library. Insure that the library either exists in the currently-logged directory, can be found via the PUBlic feature, or is available along the DOS Path. + +Other errors are generated in the process of extracting and validating the driver selected from the `CLOCKS.DAT` library. Such errors consist of: + +`-- Error Opening : clockname` + +The Selected Clock driver in the Library could not be opened. This is most often due to corruption of the `CLOCKS.DAT` file. Restore it from your ZSDOS backup disks and try again. + +`-- Error Reading : fn.ft` + +An error occurred while reading the Clock code from the library. This also is most often due to corruption of the `CLOCKS.DAT` file. + +`-- Error in : clockname` + +An error occurred in the logical relocatable structure of the selected clock driver. + +`-- Error initializing DAT file` + +An error was encountered in initializing the `CLOCKS.DAT` Library. + +`-- Memory overflow in DAT file` + +A memory allocation error occurred in the Clock routine which caused the allocated memory to be exceeded. This should not occur in any of the library clock drivers, but may be experienced if the guidelines are not followed when developing a custom clock. + +Still other errors relate to the reading and linking of the selected clock routine whether it is from the Clock Library, or loaded as a Standalone driv- er. These errors include: + +`+++ Can't find : CLOCKS.DAT` + +SETCLOK could not find the referenced Clock file. This error will be seen if an attempt is made to use a standalone clock driver which could not be found in the current Drive/User, via the PUBlic attribute, or along the Dos path. + +`+++ Error on file open` + +An error occurred while trying to open a standalone clock file. Insure that the file was correctly assembled and try again. + +`+++ Error sizing : fn.ft` + +The selected clock file contained erroneous or invalid sizing information. If this is reported from the `CLOCKS.DAT` file, reload the file from your ZSDOS backup disk and try again. If it is reported while loading a standalone clock, it is most often due to incorrect specifications of the CSEG/DSEG/Named Common areas within the Clock template. Insure that the clock specifications were followed, reassemble the driver and try again. + +`+++ Link Error : nn in file : fn.ft` + +An error occurred while linking the relocatable code from a clock driver. The "nn" reported is an indicator to the exact nature of the error. Consult the authors if you cannot resolve the error. + +The final two errors are indicators that errors occurred after the clock driver has been loaded, linked, and validated. If either of these occurs, it is most often due to selection of an incorrect clock driver, problems with the hardware controlling the selected clock, or alterations to the B/P Bios code which altered the specified interface. + +`-- Clock Not Ticking --` + +The selected clock driver could not detect an active clock. This is most often the result of selecting the incorrect driver, or setting incorrect values when asked for specific addresses or values when activated. + +`-- Error Setting B/P Bios Clock !!` + +The Bios reported an error while attempting to set the B/P Bios clock. This is most often caused by errors when modifying the module `CLK.Z80`. + + +## 6.19 SHOWHD - Partition Display Utility + +SHOWHD is a utility which is furnished with the B/P Bios package as an aid in converting existing systems to B/P Bios without losing data, particularly on Hard Drives. It is not specific to B/P Bios and should properly execute on any CP/M 2.2-compatible system. Its purpose is to display the current Hard Drive Partition settings so that you may configure a B/P Bios in either source code, or image form (with BPCNFG) to reflect the same partitioning data. + + +### 6.19.1 Using SHOWHD + +This routine is a basic utility which is normally infrequently, so frills were not added. It expects no arguments and only operates in an interactive mode. To execute it, simply enter: + +`SHOWHD` + +You will be prompted to enter a drive letter. When entered, you will be presented with a display listing the logical parameters for the drive. A sample of execution is: + +```generic +/---------------------------------------------------------------------------\ +| Show Hard Drive Partition Data - 2 Nov 91 | +| | +| Enter Drive Letter [A..P] : C | +| | +| Drive: C | +| DPH Info BPCNFG Info | +| | +| | +| Sectors/Track = 64 (same) | +| Blk Shift Fctr = 5 4k/Block | +| Block Mask = 31 | +| Extent Mask = 1 | +| Disk Blocks-1 = 4999 20000k Total (2500 Tracks) | +| Max Dirs - 1 = 1023 1024 Dir Entries | +| Alloc bytes = FFH, 00H | +| Check Size = 0 | +| Track Offset = 3500 (same) | +| _ | +\---------------------------------------------------------------------------/ +``` + +### 6.19.2 SHOWHD Error Message + +Only one message may be displayed from the utility. It is: + +`+++ Invalid Drive : d` + +The Drive Letter selected was not a valid drive within the Bios. + + +## 6.20 SPINUP - Hard Disk Motor Control Utility + +SPINUP is a generic B/P utility to directly control the heads and motors of newer SCSI drives. It moves the heads on the specified hard drive unit to the designated shipping or park zone and may turn the drive motor off if called to Stop the unit and that feature exists in the drive. If called to Start the unit, the drive motor is turned on (if applicable) for the specified drive unit and the heads are positioned to Cylinder 0. This routine may be used as a power conservation feature where operation can be continued for periods of time from RAM or Floppy drives without need to access the hard drive unit. Attempts to access a unit which has been "spun down" with SPINUP will result in an error. This routine is essentially a generic version of PARK (see 6.17) and is furnished in source code form to demonstrate methods of interfacing to Hard Drives from Application Programs. + + +### 6.20.1 Using SPINUP + +This utility was written for use primarily in battery-operated systems where power conservation is desired. Generally, only the newer SCSI drives respond to the Stop/Start Unit commands by controlling the drive motors and positioning the heads over the designated "Landing Zone". SPINUP is Command-Line driven and expects an argument consisting of a valid Unit Number for the physical Hard Drive unit (see 5.2.1, `CONFIG+61`). Valid Unit Numbers are "0", "1" and "2". + +Stopping the unit is indicated by preceding the Unit Number with a minus sign as: + +`SPINUP -0` + +which will cause Unit 0 to park the heads and remove power from the drive motor if possible. Starting the unit is indicated by simply passing the Unit Number as an argument as: + +`SPINUP 0` + +Whether starting or stopping a Hard Drive Unit, SPINUP monitors the unit status after issuing the command and reports the status of the drive when results of the operation are received. Results are returned as; the unit is Stopped, Started, or an error has occurred (see 6.20.2 below). + +Prior to using SPINUP to stop a hard drive, you must insure that accesses to any logical drive on that unit will not occur while the unit is stopped by either exchanging logical drives with BPSWAP (see 6.5) or altering the Command Processor and Dos Search Paths with the ZSDOS Utility ZPATH. For example, if your system includes a partition on the subject Hard Drive as Drive A:, you have logged onto a RAM Drive as M: and the unit is stopped, ZCPR3 and ZSDOS may attempt to find a file on drive A: which will result in a Read Error. In this example, you may either swap drive A: with M:, insuring that M: is not in either Path, or set both paths to exclude drive A: + + +### 6.20.2 SPINUP Error Messages + +`+++ Not B/P Bios ... aborting +++` + +An attempt was made to execute SPINUP under a Bios other than B/P, or modifications made to the Bios altered the locations or values needed to correctly identify the system. + +`+++ Can't handle this Controller Type! +++` + +The Controller Type within the Bios cannot handle the "Stop/Start Unit" SCSI Commands. + +`**** SCSI Block Length Error !` + +The Bios does not support the Extended Commands necessary to turn the drive on and off using the "Stop Unit" and "Start Unit" SCSI Functions. This is most probably due to changes during an edit/assembly of the Bios which altered either the Command Descriptor Block size, or the Hard Drive function which returns the values. + +`**** Invalid Unit # !` + +The specified unit number was not "0", "1" or "2". Only three physical Hard Drive units are recognized in B/P Bios. + + +## 6.21 TDD - SmartWatch Support Utility + +TDD is a customized version of the ZSDOS utility TD. With ZSDOS2 systems, it used to display, set or update the B/P Bios clock. This latter capability only exists with the Dallas SmartWatch (DS-1216E) or JDR No-Slot-Clock in the Ampro Little Board, SB180 or YASBEC. + + +### 6.21.1 Using TDD + +TDD obtains the system Time and Date with a DOS Function 98 and displays the information on your console. Your system Must have an installed clock driver to use this utility. If the clock driver supports a set function, TDD can set the Date and Time using DOS Function 99. When setting the clock, TDD will allow you to operate in either an Interactive or Command Line driven mode. + +TDD responds to the standard Help request described in Section 1.7. You may obtain a brief usage description by entering: + +`TDD //` + +You may obtain the current Date and Time from the system clock by simply entering the program name as: + +`TDD` + +If you are using a Dallas 1216E-based clock, you can set the B/P Bios clock directly by entering: + +`TDD U` + +A continuous display may be obtained which will update every second until any key is depressed by entering: + +`TDD C` + +The system clock may be set in the Interactive mode by entering the program name followed by the "S" parameter as: + +`TDD S` + +You will then be asked to enter the date. The prompt will display the format in which the date will be accepted (US or European) as either: + +`Enter today's date (MM/DD/YY):` (US) + +or + +`Enter today's date (DD.MM.YY):` (European) + +Date fields (month, day, and year) may be either one or two digits in each position. Invalid entries such as an invalid day for the entered month will cause the prompt to be re-displayed for a new entry. + +When a valid date has been entered, you will be prompted for the current time. + +The prompt will vary depending on whether you are using a Real Time Clock, or the Relative counter substitute for a clock. The two prompts are: + +`Enter the time (HH:MM:SS):` (Real Time Clock) +`Enter the relative time (+XXXX):` (Relative Counter) + +Time is assumed to be in 24 hour format when a Real Time Clock is being used. Seconds may be omitted when setting the clock. When the relative clock is used, a '+' must prefix the count to which you wish to set the Relative Counter. Counts from +0 to +9999 are permitted. + +When the time entry is ended with a carriage return, the date and time will not be automatically set. A message will prompt you to press any key. At this point, the next key depression (other than shift and control) will set the clock. This procedure allows you to accurately synchronize the time with one of the many accurate time sources. + +Command Line setting of the clock is initiated by entering the program name followed by the date and optional time. The date must be in the correct form (US or European) for the configured TDD. If an error is detected in a Command Line clock set, TDD switches to the interactive mode and prompts for date and time as described above. + + +### 6.21.2 Configuring TDD + +TDD can be configured to present the time in either the US format of month, day, year as: Sep 18, 1988, or the European and military style as: 18 Sep 1988. Likewise, the set function accepts a US format of MM/DD/YY or the European DD.MM.YY. The default may be set with Al Hawley's ZCNFG utility using data contained in the TDD.CFG file on the distribution disk. + + +### 6.21.3 TDD Error Messages + +Error messages for TDD are simple and are mostly self-explanatory. For clarity, however, they are covered here. + +`SORRY! ZSDOS or ZDDOS is required to run this program!` + +You tried to run this with someone else's DOS. Use ZSDOS or ZDDOS. This error aborts to the Command Processor. + +`*** NO Clock Driver installed!!!` + +You tried to read a clock which does not exist. Install a clock with SETUPZST and try again. This error aborts to the Command Processor. + +`*** Clock does NOT Support SET!!!` + +The clock driver on your computer will not permit you to set the time with TDD. This error aborts to the Command Processor. + +`*** Must have B/P Bios to use!!!` + +This utility only functions under B/P Bios. If you are using B/P Bios and this message appears, it is most probably due to edit/reassembly of the Bios source which altered critical values in the data structures. + +`*** Hardware Type Not Supported ! ***` + +Since TDD is integrally tied to specified hardware platforms, it will only function if the running computer is one of the types for which the correct code has been implemented. This error should not appear unless the "U" or "S" command is issued. + +`++ Insufficient Memory! ++` + +The base of available memory has been reduced below that needed for the portion of TDD which is relocated to high memory. The most common cause of this is the addition of Resident System Extensions (RSXs) which cause the top of the TPA to be reported as below 8100H. + +`*** Error in Data Input` + +An invalid character or number was entered when trying to set the date and time. This error will cause the Interactive mode to be entered and issue a prompt to re-enter correct date/time. + +`*** Must be wheel to set clock!` + +An attempt was made to set the clock without Wheel access. Use ZSCONFIG (ZSDOS 1) or ZSCFG2 (ZSDOS2) to set a valid Wheel byte, or disable it (see 6.22 for ZSCFG2 or the ZSDOS 1 manual for ZSCONFIG). This error aborts to the Command Processor. + +`*** Must have Z180 Processor!!!` + +This error may be received if the ID tag identifies the Bios for a computer with a Z180/HD64180, but the check for this CPU failed. It is probably due to incorrect porting of the Bios or manipulation of the header structure. + +`*** Must have Z180 to Set No-Slot-Clock!!!` + +Similar to the error above, but will appear when trying to set the clock under al altered system. + +`**** Can't find No-Slot-Clock!` + +The JDR No-Slot-Clock/Dallas DS-1216E SmartWatch could not be validated in the system. This message will be seen if TDD is executed without the clock installed, or the clock has failed for some reason. + + +### 6.21.4 NOTES Spring 2001 + +TDD has been extended to more clocks than the DS-1216E cited in this manual. It handles the clocks in all supported B/P BIOS versions. + + +## 6.22 ZSCFG2 - ZSDOS2 Configuration Utility + +ZSCFG2 is a program to configure various parameters of a ZSDOS2 Operating System. It is included in this manual due to the close interaction of all parts of an operating system, particularly the Banked and Portable BIOS. ZSCFG2 operates in either an interactive (novice) or command line driven (expert) mode for maximum flexibility and ease of use. If your computer is running ZCPR3, the Z3 Environment is automatically detected and ZSCFG2 will use video attributes such as reverse video and cursor addressing to enhance the display. + +As in all of our support routines, a brief on-line help message is available by entering the name followed by two slashes as: + +`ZSCFG2 //` + +This configuration tool automatically tailors itself to the ZSDOS2 system, and all messages, from Help to Interactive prompts will accurately reflect the options and status for the running configuration of ZSDOS2. + + +### 6.22.1 ZSCFG2 Interactive Use + +To start ZSCFG2 in the interactive mode, simply enter the program name as: + +`ZSCFG2` + +If a valid ZCPR3 environment is located, the screen is cleared, and you will see a screen containing needed addresses from the environment, and a tabular display of the current settings within the operating ZSDOS2 system. Reverse video is used to enhance the display if available. If you are using a computer which is not equipped with ZCPR3, or cannot support direct cursor addressing, the information (less ZCPR3 addresses) is simply scrolled up the screen, one line at a time. The only content differences between the two displays is that no data on the ZCPR3 environment will be displayed. An example of a ZSDOS2 display is: + +```generic +/---------------------------------------------------------------------------\ +| ...Configuring ZSDOS Ver 2.0 Z3 Environment at : FE00H | +| ZCPR Path Address : FDF4H | +| Wheel Byte at : FDFFH | +| | +| 1 - Public Files : YES | +| 2 - Pub/Path Write Enable : NO | +| 3 - Read-Only Vector : YES | +| 4 - Fast Fixed Disk Log : YES | +| 5 - Disk Change Warning : NO | +| 6 - Path w/o System Attr : YES | +| 7 - DOS Search Path : Enabled - Internal | +| 8 - Wheel Byte Protect : Enabled Addr = FDFFH | +| T - Time Routine (Clock) : F168H | +| A - Stamp Last Access Time : Disabled | +| C - Stamp Create Time : EEB2H | +| M - Stamp Modify Time : EEBCH | +| | +| Entry to Change ("X" to EXIT) : _ | +\---------------------------------------------------------------------------/ +``` + +The type of Operating system and version number are first displayed, followed by any ZCPR3 Environment information needed. If no environment is located, you will see a message to that effect. In such a case, certain options will be restricted as covered later in detailed descriptions. + +Interactive operation consists simply of entering the number or letter in the left of each line to select a function. If you select numbers between one and six, the option is changed from OFF to ON or vice versa, and the menu and status are again displayed. If you select any of the other items, you will be asked for more detailed information. Section 6.22.2 below contains a detailed description of all options. + + +### 6.22.2 ZSCFG2 Command Line (Expert Mode) Use + +Command line entry (or Expert Mode) provides the ability to dynamically set ZSDOS options within STARTUP scripts, ZCPR Alias files, Submit files, or directly from the your console. This permits the operating system parameters to be tailored to specific applications, and restored upon completion. For example, a submit or alias command might feature the following sequence: + +```generic +Disable/Enable ZSDOS features and set addresses +...Process application programs +Restore ZSDOS features and addresses and return +``` + +Tailoring of ZSDOS in this sequence would be via a call to ZSCFG with arguments passed on the command line within the script. In this fashion, you do not have to constantly attend the computer to change DOS parameters. + +Settings are passed to ZSCFG as groups of characters separated by one or more tabs, spaces or commas. Each group of characters begins with a Command character which identifies the setting to be changed. In the case of the items related to time and date, a two-character sequence is used. A "+" sign identifies the Command as a Clock, or Time Stamp-related function, and the following Command character tells which parameter of the six is to be changed. Command Identifiers for ZSDOS are: + +| Option | Description | +| :---: | :--- | +| `P` | Public File Support | +| `W` | Public/Path Write Enable | +| `R` | Read-Only Drive Sustain | +| `F` | Fast Hard Disk Relog | +| `!` | Disk Change Warning | +| `S` | Path without SYStem Attribute | +| `>` | ZSDOS Search Path | +| `*` | Wheel Byte Write Protect | +| `C` | Clock Routine Address | +| `+A` | Stamp Access Time | +| `+C` | Stamp Create Time | +| `+M` | Stamp Modify Time | + +Options which are simply On/Off toggles require no arguments. You enable them merely by entering the Command Identifier(s). To disable such options, you simply append a minus sign ("-") to the end of the Identifier. For example, a command line entry to activate the Fast Relog capability for hard disks, turn PUBlic bit capability on, and disable the Disk Change warning would be: + +`ZSCFG2 F,!-` + +Certain options require additional parameters which are handled by a secondary prompt in the interactive mode. Since no prompt can be issued in the Command Line entry mode, the added parameters are passed by appending them to the Command Identifier. An example to set the Wheel Byte Write Protect to be the same as the ZCPR3 Wheel Byte, Activate the Internal path and set the Clock address to the standard B/P Bios Clock Vector is: + +`ZSCFG2 *Z,>I,CB` + +You must remember that NO spaced or other delimiters (spaces, tabs and commas) are permitted between the Command Identifier and added arguments. An "Invalid" error will generally be the result if you forget. When entering ad- dresses or numbers as arguments, they are always in Hexadecimal (base 16) with optional leading zeros. The algorithm used to interpret the number entered only retains up to four digits. Therefore, if you enter the sequence "0036C921045", it would be interpreted as 1045H. + +The following section describes each option and what alternatives are available to optimize it for your system. + + +### 6.22.3 ZSCFG2 Option Descriptions + +The two tools which permit tailoring of a ZSDOS2 system to your specific needs, INSTAL12 and ZSCFG, both present the same interactive display. This section, therefore, is applicable to installation as well as "on the fly" customization with ZSCFG2. Each option will also include specific arguments for Command Line entry of the option. Options will be covered in their order of appearance in the INSTAL12 and ZSCFG2 interactive menus. + + +#### 6.22.3.1 Public Files + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 1 - Public Files | +| | (toggle) | +| Command Line Character: | P | +| Enable | P | +| Disable | P- | + +This flag controls recognition of the Plu*Perfect PUBlic attribute bit (Bit 7 of the second letter in the file name). When set to YES or activated, any file having this bit set will be accessible from any user area on the disk. This means that a search for the file will locate it on the first try, regardless of which User Area is currently selected (see 2.9.4, Public Access). If set to NO, the file will be private and can only be found if the user area matches that of the file. The default setting for this option is YES, to recognize PUBlic files. + + +#### 6.22.3.2 Public/Path Write Enable + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 2 - Pub/Path Write Enable | +| | (toggle) | +| Command Line Character: | W | +| Enable | W | +| Disable | W- | + +When set to YES or activated in Command Line mode, ZSDOS2 will permit write operations to Public files, and in the case of ZSDOS2, files located along the Path. When set to NO or disabled, attempts to write to the file will result in a "Read-Only" error. The default setting for this option is NO. + + +#### 6.22.3.3 Read-Only Vector Sustain + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 3 - Read-Only Vector | +| | (toggle) | +| Command Line Character: | R | +| Enable | R | +| Disable | R- | + +When set to YES or activated, the normal Write Protect vector set by ZSDOS2 function call 28 will not be cleared on a warm boot as with CP/M and ZRDOS. If set to NO or disabled, the Write Protect vector will function as in CP/M and ZRDOS. The default setting for this option is YES. + + +#### 6.22.3.4 Fast Fixed Disk Relog + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 4 - Fast Fixed Disk Log | +| | (toggle) | +| Command Line Character: | F | +| Enable | F | +| Disable | F- | + +When set to YES or enabled, the allocation bit map for a fixed drive (one in which the WACD buffer is zero) will not be rebuilt after the initial drive logon. This results in much faster operation for systems with Hard Disks and RAM disks. If set to NO or disabled, the allocation map will be rebuilt each time fixed disk drives are initially selected after a warm boot. The default setting for this option is YES. + + +#### 6.22.3.5 Disk Change Warning + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 5 - Disk Change Warning | +| | (toggle) | +| Command Line Character: | ! | +| Enable | ! | +| Disable | !- | + +When set to YES or enabled, a warning will be printed whenever ZSDOS2 detects that a disk in a removable-media drive (normally floppy disk drives) has been changed. If you press any key other than Control-C, ZSDOS2 will automatically log in the new disk and continue. If set to NO or disabled, no warning will be given, and the disk will be automatically logged, and the operation in progress will continue. The default setting for this option is NO, for no displayed message. + + +#### 6.22.3.6 Path Without System Attribute + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 6 - Path w/o System Attr | +| | (toggle) | +| Command Line Character: | S | +| Enable | S | +| Disable | S- | + +When set to YES or enabled, Public files on drives along the Path will be found without the System Attribute being set (see 2.9.2, Path Directory Access mode). If this option is set to NO or disabled, Public files on drives addressed along the Path will not be found unless the System Attribute Bit (bit 7 of the second character in the filetype) is set (see 2.9.3, Path File Access mode). The default setting for this option is NO or Disabled, requiring the Public bit Set on accessible files. + + +#### 6.22.3.7 DOS Search Path + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 7 - DOS Search Path | +| Options | (D)isable | +| | (S)et addr | +| | (I)nternal | +| | (Z)CPR3 (only if running ZCPR3) | +| Command Line Character: | > | +| Enable | >addr | +| | >I | +| | >Z (only if running ZCPR3) | +| Disable | >- | + +When this option is selected from the Interactive mode, you will be prompted for one of the three options. Contrary to the earlier ZSDOS1 configuration, a ZCPR3 style Environment Descriptor is required, so the following prompt will always be displayed: + +`DOS Path [(D)isable, (S)et, (I)nternal, (Z)CPR3] :` + +Operating ZSCFG2 in the Command Line mode permits you to select the same options directory from the command line as summarized above. No additional characters are required for Disable, Internal or ZCPR3 path selection. If you choose the (S)et option, you will be prompted for a Hexadecimal address with: + +`Enter PATH Address :` + +If you Disable the DOS Path option, ZSDOS2 functions just as CP/M 2.2 and ZRDOS for file searches. Requests for files will access only the currently logged disk and user, modified only by the Public capability, if active. This results in the familiar requirement to install utilities such as compilers, word processors and data base management systems to tell them where to go to find their overlays. + +Proper use of the DOS Path overcomes the limitation in finding program overlays and other files by simply setting the DOS Path to the drive and user area where the relevant overlays and other files are stored. The Path may be set in three ways. + +The first way is to assign a fixed address using the (S)et option from the Interactive Mode, or by appending the address to the Command Character in the Command Line mode. You will be responsible for insuring that any path at that address conforms to proper ZCPR3 path definitions. + +The second way to set a DOS Path is to use the three element Internal path by selecting the (I)nternal option from the Interactive Mode, or adding an "I" after the Command Character in the Command Line mode. As distributed, ZSDOS contains a single path entry of "A0:" to direct path searches to User Area 0 on Drive A. An alternative way to activate the Internal Path is with the `ZPATH.COM` utility made available with ZSDOS1. ZPATH will enable you to change the default path, and define up to three drive/user search elements. + +The final method of setting a DOS Path is only available if you are operating a ZCPR3 system. It is chosen by selecting the (Z)CPR3 option from the Interactive Mode, or following the Command Character with a "Z" in the Command Line mode. This Path mode will probably see little use, but is made available for systems which need more than three elements in a path. + +The principal disadvantage of using the ZCPR3 path is that requests from the command prompt (e.g. `A0>`) may result in n-squared searches where n is the number of elements in the path. The reason is that ZCPR3 will select the first path element, and ZSDOS will sequentially search along the entire path if the file is not found, returning to ZCPR3 with a "file not found" error. ZCPR3 will then select the second element with ZSDOS again searching along the entire file. This situation does not occur once an application program is started, since the ZCPR3 Command Processor is no longer active. + +The default setting for the DOS Path is "Internal". + + +#### 6.22.3.8 Wheel Byte Write Protect + +| | Description | +| ---: | :---: | +| Interactive Prompt: | 8 - Wheel Byte Protect | +| Options | (D)isable | +| | (S)et addr | +| | (Z)CPR3 | +| Command Line Character: | * | +| Enable | *addr | +| | *Z | +| Disable | *- | + +When you select this option from the Interactive mode of ZSCFG, you will presented with an additional lines containing available choices as: + +`Wheel [(D)isable, (S)et, (Z)CPR3] :` + +Selecting the (D)isable option by entering a "D" or disabling the Wheel Byte with the "*-" parameter string in the Command Line mode will cause ZSDOS2 to assume that the Wheel byte is always ON giving the user full privileges in file control (Writes, Renames and Erasures). Entering an "S" for (S)et from the Interactive mode will allow you to enter a Hexadecimal address for a Wheel Byte. It is your responsibility to insure that the byte is protected as necessary from unintentional alteration. Setting a Wheel Byte address from the Command line simply requires appending a Hexadecimal address after the Wheel Command Character. Entering a "Z" from the Interactive mode, or a "*Z" parameter string in the Command Line mode will set the address to the address defined for the Wheel byte in the ZCPR3-compatible B/P environment. The default for this option is OFF or Disabled to assume that the user has full privileges. + + +#### 6.22.3.9 Time Routine (Clock Driver) + +| | Description | +| ---: | :---: | +| Interactive Prompt: | T - Time Routine (Clock) | +| Options | (D)isable | +| | (S)et addr | +| Command Line Character: | C | +| Enable | C addr | +| Disable | C- | + +This option allows the user to enter the address of a clock driver routine conforming to ZSDOS standards, or disable an existing clock routine. When you enter a "T" at the prompt in the Interactive mode, the following appears: + +`Time (Clock) Routine [(D)isable, (S)et, (B)ios+4EH] :` + +Entering a "D" in the Interactive mode or the Command Line sequence "C-" will disable any existing clock. The primary effect of this is to cause an error return to DOS function calls 104 and 105 as well as disabling Date/Time Stamping functions. If you enter an "S" at this point in the Interactive mode, you will be further prompted for a Hexadecimal address of a clock driver. The same effect of setting a Clock Driver address is achieved in the Command Line mode by entering the "C" Command character followed by a valid Hexadecimal address beginning with a Number. Selecting "B", or entering "CB" as a command line argument, will Set the Dos Clock Driver address to the base of B/P Bios offset by 4EH which corresponds to the Jump Table entry for the B/P ZSDOS-compatible Clock driver. Do NOT enter unknown values since unpredictable results can occur! + + +#### 6.22.3.10 Stamp Last Accessed Time + +| | Description | +| ---: | :---: | +| Interactive Prompt: | A - Stamp Last Access Time | +| Options | (D)isable | +| | (E)nable | +| Command Line Character: | +A | +| Enable | +A | +| Disable | +A- | + +This option is only available with DateStamper type of Date/ Time Stamps. For P2DOS, the function is not defined and is ignored within ZSDOS2. As stated in Section 3.4.4.2, Unless you have a definite need to retain a record of the last time files are accessed, we recommend that you disable this option to reduce unnecessary overhead. To Select the Last Access Time option, enter an "A" at the Interactive main prompt. This will display the following prompt: + +`Stamp Last Access Time Routine [(D)isable, (E)nable] :` + +If you enter a "D" at this point in the Interactive mode or disable the function with the sequence "+A-" in the Command Line mode, no times will be entered in the "Last Accessed" field in the DateStamper file. This option may be re-enabled by selecting the "E" option in the Interactive mode from this secondary prompt, or the sequence "+A" from the Command Line mode. + + +#### 6.22.3.11 Stamp Create Time + +| | Description | +| ---: | :---: | +| Interactive Prompt: | C - Stamp Create Time | +| Options | (D)isable | +| | (E)nable | +| Command Line Character: | +C | +| Enable | +C addr | +| Disable | +C- | + +Entry of a "C" from the main menu in the Interactive mode will allow you to enable or disable the Create Time stamping feature. A secondary prompt will be displayed as: + +`Stamp Create Time Routine [(D)isable, (E)nable] :` + +To disable the Create time, enter a "D" from the secondary prompt, or the sequence "+C-" in the Command Line mode. To enable stamping of Create Times, enter an "E" from the secondary prompt from the Interactive mode, or by entering the Argument Sequence "+C" from the Command Line mode. + + +#### 6.22.3.12 Stamp Modify Time + +| | Description | +| ---: | :---: | +| Interactive Prompt: | M - Stamp Modify Time | +| Options | (D)isable | +| | (E)nable | +| Command Line Character: | +M | +| Enable | +M | +| Disable | +M- | + +The time of last Modification of a file is probably the most valuable of the times offered in a ZSDOS system. As such, you will probably never have a need to disable this feature. Should the need arise, however, enter an "M" at the Interactive main prompt. You will then be presented with: + +`Stamp Modify Time Routine [(D)isable, (E)nable] :` + +If you enter a "D" at this point in the Interactive mode or disable the function with the sequence "+M-" in the Command Line mode, no times will be stored in the "Modify" field of any active Time Stamp activity. + +This option may be re-enabled by selecting the "E" option in the Interactive mode from this secondary prompt, or the sequence "+M" from the Command Line mode. + + +### 6.22.4 ZSCFG2 Error Messages + +Only two error messages exist in ZSCFG2. For the most part, any error you see will deal with invalid parameters or entry mistakes. The two error messages are: + +`-- Invalid --` + +An invalid address or character was entered in a parameter. + +`*** ERROR: DOS is not ZSDOS2!` + +An attempt was made to run ZSCFG2 on an Operating system which was not ZSDOS2. This program cannot function under any other operating system. + + +## 6.23 ZXD - File Lister Utility for ZSDOS2 + +ZXD Version 1.66 is a modification of an earlier version released with our ZSDOS 1 package. It is the ZSDOS Extended Directory listing program derived from the ZCPR3 tool XD III written by Richard Conn and now modified to properly return disk sizing information from a banked ZSDOS 2 Operating System. Many additional capabilities were added over the original XD III, not the least of which is the ability to display time stamps for each file in a variety of formats. ZXD can display file Dates and times from DateStamper, P2DOS, and Plu*Perfect Systems' DosDisk stamp methods. In ZCPR3 systems, the Wheel byte is used to disable some functions as a security precaution in remote access systems. + + +### 6.23.1 Using ZXD + +ZXD is activated by entering its name at the command prompt, and may be followed by optional drive and user specifications to obtain the directory of another drive or user area. It may also be followed by various parameters which alter the format and/or content of the display. If options are listed without being preceded with a File Specification (drive, user, file name), then they must be preceded by the standard option character, a slash. A help message may be obtained in the standard manner by entering: + +`ZXD //` + +ZXD accepts directions in a natural form popularized with the ZCPR series of Command Processor replacements. Using the conventions described in Section 1.2, the syntax is summarized by: + +`ZXD [dir:][afn] [/][options]` + +If ZXD is called with no arguments, a display of only those files satisfying built-in default conditions will be displayed. Normally these defaults select only non-system files in the current drive and user. The default selections may be modified by option parameters detailed below. If option parameters are desired without drive, user or file specifications, then the options must be prefixed with a slash. The slash is optional if any redirection or file specifications are entered. + + +### 6.23.2 ZXD Options + +Option parameters, consisting of one or two characters, allow you to obtain selected information from files on a disk, or to tailor the display to your particular needs. Each of these options is also reflected as a permanent default. After deciding which parameters you use most by using the command line options, we recommend configuring ZXD to reflect those parameters as defaults. The results will be the requirement to enter fewer keystrokes, and consequently faster operation when a directory scan is required. + +The option characters are described in alphabetical order in the following sections. + + +#### 6.23.2.1 Select Files by Attribute + +In order to avoid cluttering a directory display with unwanted file names, ZXD features a flag which controls addition of those files marked with the SYStem Attribute Bit. The A Option controls this feature. It requires a second character of S, N, or A. Control offered by these characters is: + +| Option | Description | +| :---: | :--- | +| `S` | Include Only Files marked with the SYStem Attribute | +| `N` | Include Only Files Not marked with the SYStem Attribute (this is the defalt condition) | +| `A` | Include All Files | + +Since listing of all Non-SYStem files is the default condition, you will probably not use the N option very often. The A option, on the other hand, offers a simple way of viewing All files within the current directory, including SYStem files which are normally invisible due to the Attribute bit. + +In a ZCPR3 system where Wheel access has not been granted (Wheel byte is Off), this option is forced to Non-SYStem files only and the A option character is not permitted. + + +#### 6.23.2.2 Date Display Format + +The Dates for a ZXD display may be displayed in either US form of MM/DD/YY or European form of DD.MM.YY. You may override the default form with the D option. Here is an example of the two types of date displays: + +US Form: + +```generic +ZXD Ver 1.66 3 Apr 1993 15:43:17 +Filename.Typ Size Modified Filename.Typ Size Modified +-------- --- ---- -------- -------- --- ---- -------- +INITDIR .COM 4k 07:01-09/17/88 ZPATH .COM 4k 07:50-09/17/88 +ZXD .COM 8k 08:01-09/17/88 + C2: -- 3 Files Using 16K (324K Free) +``` + +European Form: + +```generic +ZXD Ver 1.66 3 Apr 1993 15:43:11 +Filename.Typ Size Modified Filename.Typ Size Modified +-------- --- ---- -------- -------- --- ---- -------- +INITDIR .COM 4k 07:01-17.09.88 ZPATH .COM 4k 07:50-17.09.88 +ZXD .COM 8k 08:01-17.09.88 + C2: -- 3 Files Using 16K (324K Free) +``` + + +#### 6.23.2.3 Disable Date (NoDate) Display + +While the display of date and time information is the default mode of ZXD, this may be disabled with the N option to display more file names on a screen. + + +#### 6.23.2.4 Output Control Option + +The O option controls ZXD's printer or screen output, and requires a second character which adds additional control to output formats. The second characters recognized are: + +| Option | Description | +| :---: | :--- | +| `F` | Send a Form Feed character at the end of the list | +| `H` | Toggle Horizontal/Vertical display of sorted listing | + + +#### 6.23.2.5 Output to Printer + +Option P controls output to the printer. When this option is given, the sorted directory listing is sent to both the console screen and the printer. This option is disabled and not available in a ZCPR3 system where Wheel access has not been granted (Wheel byte is Off). + + +#### 6.23.2.6 Sort by Name or Type + +The default sort condition for ZXD is to first sort by File Name, then by File Type within matching Names. Option S reverses the sequence. + + +#### 6.23.2.7 Primary DateStamp + +ZXD features an algorithm which will attempt to find one of several types of Date/Time Stamps for each file. The default conditions tell ZXD to first attempt to locate DateStamper type of Stamps. If that fails, a search is made for DosDisk stamps from MS/PC-DOS disks, and finally to check for P2DOS type stamps. The T option causes the DateStamper checks to be bypassed, thereby speeding response if DateStamper type stamping is never used. + + +#### 6.23.2.8 All User Areas + +The distribution version of ZXD will only search a single User area, either the currently logged or the explicitly stated area, for files. The U option will locate files in all user areas on the disk. Combining the U with the AA options will list all files in all user areas, both system and non-system, on a disk. This option is disabled and not available in a ZCPR3 system where Wheel access has not been granted (Wheel byte is Off). + + +#### 6.23.2.9 Wide Display + +ZXD only displays the "Last Modified" Date/Time Stamp. This may be reversed by appending the W option to the Command Line, which generates a Wide of all available Stamps. Only DateStamper has provisions for all three stamp categories; P2DOS contains only Created and Modified stamps, while the single MS/PC-DOS stamp accessed through DosDisk best corresponds to "Modified". A display created with this option is: + +```generic +Filename.Typ Size Created Last Access Modified +-------- --- ---- ------- ---- ------ -------- +BU16 .COm 8k 17:26-06/12/88 08:42-08/21/88 17:26-06/12/88 +COPY .COM 8k 15:06-09/17/88 15:06-09/17/88 +ZPATH .COM 4k 07:50-09/17/88 15:02-09/17/88 07:50-09/17/88 +ZXD .COM 8k 08:00-09/17/88 08:01-09/17/88 +``` + + +### 6.23.3 Customizing ZXD + +The configuration utility ZCNFG.COM is used to alter the default settings in ZXD. Settings and text prompts for ZXD are contained in the file ZXD.CFG which must be accessible to ZCNFG for any configuration change. All options are simple ON/OFF, or reversible settings and correspond to the options discussed in Section 6.23.2 above. See Section 4.8 of the ZSDOS 1.0 User Manual or ZCNFG documentation on the Ladera Z-Node for details on using ZCNFG. + + +## 6.24 Additional Utilities (NOTES Spring 2001) + +Several of the utilities documented in this manual have also matured over the years, and some new ones added. Some of the more significant are: + +**HASHINI.COM** - This utility prepares a fresh directory for file accesses via the ZSDOS2 hash algorithm implemented in ZS203.ZRL. See the built-in help for more details on use. + +**SIZERAM.COM** - Examine and report memory statistics in a Banked system. This utility uses the inter-bank data movement features of a Banked BPBIOS system and will not execute in a non-banked system. + +**TURBO.COM** - When using the Z8S180 CPU, this utility allows you to switch the internal divide-by-two circuit in and out of operation resulting in a doubling or halving of the processor speed. + diff --git a/Doc/CPM/BPBIOS/BPBIOS_7_ZSDOS2.md b/Doc/CPM/BPBIOS/BPBIOS_7_ZSDOS2.md new file mode 100644 index 00000000..efc80a13 --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_7_ZSDOS2.md @@ -0,0 +1,37 @@ +# 7 ZSDOS Version 2 + +Version 2 of ZSDOS is currently in a developmental phase. The version provided with this package is preliminary and should not be considered a final work. Be sure you back up any files which you don't mind sacrificing, and please let us know in as much detail as possible any problems you experience. + +In addition to the ZSDOS Version call (Function 48) returning 20H signifying ZSDOS2, three new Operating System functions have been added. They are: + +| Function 46 | Return Disk Free Space | +| ---: | :--- | +| Enter: | C = 46 (function #) | +| | E = Drive # (A=0..P=15) | +| Exit: | A = 0 if Ok, <>0 if Error | +| | Disk Free Space in kilobytes is placed in DMA+0 (LSB) thru DMA+3 (MSB) | + +This function returns Disk Free Space from fully-banked systems where the ALV buffers are not directly accessible by applications programs. It **MUST** be used to reliably determine free space since there is no way for programs to ascertain which System Bank (if more than one) contains the Allocation Bit Map. For most reasonably-sized systems, only the lower two or three bytes will be used, but four bytes are allocated to accommodate a maximally-sized system. + +| Function | Return Environment Descriptor Address | +| ---: | :--- | +| Enter: | C = 49 (function #) | +| Exit: | HL = Address of Env Desc. | + +This function returns the address of a ZCPR 3.4 "type" Environment Descriptor needed in B/P Bios systems. Rather than rely on the Command Processor inserting the ENV address into application programs upon execution, this function may be used to reliably acquire the ENV address at any time. + +| Function 152 | Parse File Name | +| ---: | :--- | +| Enter: | C = 152 (function #) | +| | DE = Pointer to dest FCB | +| | DMA --> start of parse string | +| Exit: | A = Number of "?" in fn.ft | +| | DE = points to delimiter | +| | FCB+15 will be 0 if parse Ok, 0FFH if errors occurred | + +This function may be used to replace Z3LIB library routines in a more robust manner and produce consequently smaller applications programs. It is fully compliant with ZCPR 3.4 parse specifications. + + +## 7.1 NOTES Spring 2001 + +The versions of ZSDOS2 (the Banked Z-System DOS) and Z4x Banked Command Processor Replacement have been modified over the years. The manual may refer to specific versions, or by generic names. As of the Spring 2001 release under the GNU General Public License, Two versions of ZSDOS2 are provided; `ZS203.ZRL` which contains code for hashed directories, and `ZS227G,ZRL` which does not. diff --git a/Doc/CPM/BPBIOS/BPBIOS_8_ZCPR4.md b/Doc/CPM/BPBIOS/BPBIOS_8_ZCPR4.md new file mode 100644 index 00000000..f3162af2 --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_8_ZCPR4.md @@ -0,0 +1,10 @@ +# 8 ZCPR Version 4 + +`Z40.ZRL` is a consolidation of ZCPR34 and many of the RCP features commonly in use, modified by the need to bank as much of the Command Processor as possible. When Z40 is used in a Fully-Banked system, you may not need much of, or any Resident Command Processor with your system. Z40 relys on ZSDOS2 and will **NOT** work without it since the Command Line Parser and disk free space calculations have been removed in favor of ZSDOS2 services. Additionally, the prompt line displays the time and will only function correctly if he ZSDOS2 clock is enabled. Comments on how these new System components work would be appreciated. + +More complete documentation is provided in the `Z40.HLP` files included with the distribution diskettes, and a list of active functions is available with the H command at the prompt. To read the On-line help files, use `HELP.COM` available for downloading from any Z-Node. + + +## 8.1 NOTES Spring 2001 + +The versions of ZSDOS2 (the Banked Z-System DOS) and Z4x Banked Command Processor Replacement have been modified over the years. The manual may refer to specific versions, or by generic names. As of the Spring 2001 release under the GNU General Public License, the latest version of the Z4x Processor Replacement is `Z41.ZRL` which features a small amount of tailoring. A new utility; **`CONFZ4.COM`** is available for this purpose. diff --git a/Doc/CPM/BPBIOS/BPBIOS_9_Glossary.md b/Doc/CPM/BPBIOS/BPBIOS_9_Glossary.md new file mode 100644 index 00000000..326043fd --- /dev/null +++ b/Doc/CPM/BPBIOS/BPBIOS_9_Glossary.md @@ -0,0 +1,100 @@ +# GLOSSARY + +**Application Programs** +In contrast to utility programs (see), application programs or applications are larger programs such as word processors which function interactively with the user. + +**BDOS** +Basic Disk Operating System. The machine-independent, but usually processor-dependent, program which controls the interface between application programs and the machine-dependent hardware devices such as printers, disk drives, clocks, etc. It also establishes the concept of files on media and controls the opening, reading, writing, and closing of such constructs. + +**BGii** +BackGrounder ii from Plu*Perfect Systems, a windowing task-switching system for CP/M users with hard or RAM disks. + +**BIOS** +Basic Input/Output System. Machine-dependent routines which perform actual peripheral device control such as sending and receiving characters to the console, reading and writing to disk drives, etc. + +**Bit** +BInary digiT. An element which can have only a single on or off state. + +**Bit Map** +An array of bits used to represent or map large arrays of binary information in a compact form. + +**Boot** +The term used for the starting sequence of a computer. Generally applies to starting from a "Cold," or power-off state, and includes the loading of Operating System, and configuration steps. + +**Byte** +A grouping of eight bits. + +**CPR** +Command Processor Replacement. Replaces CCP (see below). Example: ZCPR + +**CCP** +Console Command Processor. The portion of the operating system that interprets user's commands and either executes them directly or loads application programs from disk for execution. The CCP may be overwritten by applications, and is reloaded by the "Warm Boot" function of the BIOS. + +**Checksum** +An value which arithmetically summarizes the contents of a series of memory locations, and used to check the current contents for errors. + +**Clock Driver** +A software link between a Non-banked ZSDOS and the clock on your system. The clock driver allows ZSDOS and its utilities to read the clock which is normally inherent in the B/P Bios. + +**Command Script** +Sometimes called simply scripts, command scripts allow you to create a single command which issues other commands to perform a unique set of actions. CP/M submit files are one kind of command script familiar to all CP/M users. ZCPR also offers more sophisticated types of scripts such as aliases and command files (e.g., ALIAS.CMD). + +**DateStamper** +A software package developed by Plu*Perfect Systems to allow time and date stamping of files. The Boot System uses an external module in the file LDDS.COM to implement DateStamper, while ZSDOS2 automatically supports this stamping method. DateStamper is unique among file stampers for microcomputers for two reasons: first, it maintains all file stamps within a file; second, it maintains stamps for create, access, and modify time/date for each file. + +**DDT** +Dynamic Debugging Tool. A utility distributed with CP/M 2.2 which can display, disassemble, or alter disk files or areas of memory using opcodes or hexadecimal values. + +**DOS** +Disk Operating System. Often used term for the BDOS, but generally refers to the aggregate of CCP, BDOS and BIOS. + +**DosDisk** +A software package from Plu*Perfect Systems which allows users of CP/M and compatible computers to write and read files directly to and from standard 5-1/4" 40-track Double-Sided, Double-Density MS-DOS format diskettes. This is the standard "360k" disk format used in IBM-PC compatible computers. + +**FCB** +File Control Block. A standard memory structure used by CP/M and compatible operating systems to regulate disk file operations. + +**File Attributes** +Also known as file attributes, reserved bits stored along with file names in disk directories which control how the files are accessed. + +**Hexadecimal** +A base-16 numbering system consisting of the numbers 0-9 and letters A-F. Often used to represent bytes as two digits (00 to FF). Use of Hexadecimal numbers is usually represented by suffixing the number with an "H" as in "01H". + +**IOBYTE** +Input/Output Byte. A reserved byte at location 3 which is used by some CP/M BIOS's to redirect input and output between devices such as terminals and printers. + +**K** +Usually refers to Kilobyte or 1024 (2^10th power) bytes. + +**P2D** +P2Dos Datestamps. An alternative form of file stamping used in HAJ Ten Brugge's P2DOS. P2D stamps are compatible with CP/M Plus time and date stamps. This format is supported in a B/P Boot system with the LDP2D.COM Stamp module, and automatically in ZSDOS2. + +**RAM** +Random Access Memory. As opposed to Read Only Memory (ROM) the area of a computer's memory which may be both read from and written to. + +**RSX** +Resident System Extension. A program module complying with a standard developed by Plu*Perfect Systems for extending the functionality of a CP/M 2.2 compatible Operating System. The module must be loaded at the top of the Transient Program Area, and below the Console Command Processor. + +**System Prompt** +The familiar A> prompt which appears soon after CP/M computersare started up. + +**TPA** +Transient Program Area. That addressable memory space from the lowest available address to the highest available address. Usually this extends from 100H to the base of the BDOS (assuming that the Command Processor is overwritten), or the base of the lowest RSX. + +**Utility Programs** +In contrast to application programs (see), utility programs or utilities are shorter programs, such as directory programs, which accept a single command from the user. + +**Wheel Byte** +Taking its name from the colloquial "Big Wheel," the Wheel byte controls security under ZCPR and ZSDOS. When the byte is set to a non-zero value, the user has "Wheel status" and may execute commands unavailable to other users. + +**Word** +In the computer context, a fixed number of bytes. For 8- bit microcomputers, a word is usually two bytes, or 16 bits. + +**Z-System** +An operating system which completely replaces CP/M by substituting ZCPR for Digital Research's command processor and ZSDOS for Digital Research's disk operating system. ZCPR and ZSDOS complement one another in several ways to enhance performance. + +**ZCPR** +Z80 Command Processor Replacement. Originally developed as a group effort of the Special Interest Group for Microcomputers (SIG/M), but refined by Richard Conn to ZCPR version 3.0 and Jay Sage to versions 3.3 and 3.4. + +**ZRL** +A form of Relocatable file image using specified "Named Common" bases. For ZSDOS, files of this type are MicroSoft-compatible REL files using only the Common Relative segment "_BIOS_". diff --git a/Doc/CPM/ReadMe.txt b/Doc/CPM/ReadMe.txt index 92d2189d..0aecd7e4 100644 --- a/Doc/CPM/ReadMe.txt +++ b/Doc/CPM/ReadMe.txt @@ -68,3 +68,11 @@ ZSDOS is the DOS portion of Z-System. This is the manual for ZSDOS 1.x as included in RomWBW. The installation instructions can be ignored since that work has already been completed as part of the RomWBW distribution. + +ZPM3 ("ZPM3.txt") +----------------- + +A Z80 coded CP/M 3.0 compatible BDOS replacement with ZCPR support. +This minimal documentation is all that is provided with ZPM3. + +-- WBW 8:38 AM 6/6/2025 diff --git a/Doc/CPM/ZPM3.txt b/Doc/CPM/ZPM3.txt new file mode 100644 index 00000000..7df5cb8f --- /dev/null +++ b/Doc/CPM/ZPM3.txt @@ -0,0 +1,483 @@ + + Z P M 3 by Simeon Cran + ======================== + + A Z80 coded CP/M 3.0 compatible BDOS replacement. + + The first public release: 27/3/92 + This document dated: 16/6/92 + + Distributed at: Z-Node 62 (Perth, Western Australia) + V21,V22,V22bis 09 450 0200 + + +WELCOME TO ZPM3 +~~~~~~~~~~~~~~~ +Welcome to the best CP/M compatible operating system for Z80 +based computers with banked memory. The best? Yes, we believe so. +CP/M 3.0 has had bad press, but the fact is that it is faster +than CP/M 2.2 ever was, and it offered more integrated +facilities. Perhaps it was all the Z80 replacement BDOSes for +CP/M 2.2 which stole the limelight from CP/M 3.0, or was it just +that few computers had the required banked memory? + +Whatever the reason for CP/M 3.0's lack of success in the +marketplace, there are still plenty of users who will stand by +its wonderful facilities and speed. For those users ZPM3 provides +the long awaited Z80 coded update. + +ZPM3 offers all the good things that CP/M 3.0 does, and then it +offers more. Because ZPM3 is written in Z80 code rather than the +8080 code of CP/M 3.0, it can do everything that CP/M 3.0 does, +but in much less space. With the extra space recovered, ZPM3 +packs in a number of new facilities. Yet the whole package fits +in exactly the same space as CP/M 3.0 so you can directly replace +your old CP/M 3.0 BDOS with ZPM3 without a worry. + +ZPM3 is also fast. Faster, in fact, than CP/M 3.0. This is +possible because the rich Z80 instruction set allows many +algorithms to be implemented more efficiently. In addition, the +extra space available in ZPM3 has been put to use to further +optimise the code. Lots of small optimisations smooth the +execution flow, so ZPM3 becomes the fastest operating system on +most banked CP/M computers. + + +THE FEATURES +~~~~~~~~~~~~ +ZPM3, in addition to complete CP/M 3.0 compatibility, offers the +following features: + + +Random Read Bug fixed. +++++++++++++++++++++++ +Maybe you didn't know, but CP/M 3.0 has a bug. It affects random +reads under very specific circumstances, and can result in a +program thinking that you don't have some pieces of data in a +file when in fact you do. The bug would occur very, very rarely, +but it is real. ZPM3 finally squashes it. + + +Protected SCB User code ++++++++++++++++++++++++ +The System Control Block of CP/M 3.0 was a revolution at the +time. ZCPR has a system environment and most other operating +systems have other similar structures, but the SCB of CP/M 3.0 +was one of the very first. + +Unfortunately, Digital Research never properly documented it, and +some programmers found things out about it that weren't quite +true and started programming accordingly. As well, because it is +available in the TPA bank, runaway programs can overwrite it +causing problems. + +Mostly though, the SCB will survive, or at least any problems +will be so obvious that the user will realise that a crash has +occurred and will reboot. A real problem exists with the CP/M 3.0 +code however when the user value is written over with a value +above 15. Many programs now directly write to this byte, and if +they put a value in that is above 15, all sorts of havoc can +happen with the disk system. Actually, CP/M 3.0 will handle user +areas above 15 with this method, and all seems ok until the +operating system mistakes one of these directory entries as an +XFCB. Simply put, user areas above 15 must not be used with CP/M +3.0. + +ZPM3 has code which prevents these problems, making the system +even more stable. + + +Obsoleted Trap system. +++++++++++++++++++++++ +One of the problems of the banked operating system was that it +was possible to redirect the BIOS to code below common memory, in +which case the banked BDOS could not access it. One solution is +to call all BIOS code from common memory, but this involves a +bank switch for every BIOS call, and this slows things down +considerably. + +CP/M 3.0 got around the problem by providing special code just +below the SCB. If you redirected the BIOS, you also had to change +this code which caused a bank switch when your new BIOS routine +was called. When you removed the redirection, you also had to +restore the special code. + +This system has major drawbacks. For a start, if you redirect the +BIOS, then another program redirects your redirection, then you +remove your first redirection (along with the special code), the +bank switch won't happen for the second redirection and the +system will crash. + +If a CP/M 2.2 program tried to do the redirection, it would know +nothing about CP/M 3.0 and would not adjust the special code, so +a crash would result in that case too. + +The special code was called the "Trap System" as it was meant to +trap redirection (as long as you set the trap). ZPM3 has +eliminated the need for the traps. They are still there, and +programs can still fiddle with them, but it doesn't matter how +they are set, they are ignored. There is simply no need for them +anymore. And this has been achieved without a performance +penalty. In fact, in the case of a program which sets the traps +but forgets to restore them, performance is now much better. + + +Semi-Permanent Read Only status for drives. ++++++++++++++++++++++++++++++++++++++++++++ +In recent years, a trend in CP/M 2.2 is to make drives which have +been set read only to remain that way until explicitly changed by +function 37. ZPM3 now adopts this logic. Previously a control-C +would return a read only drive to read write. The advantage is +that a program can now make a drive read only for a session and +know that it will stay that way. + + +ZCPR compatible function 152 +++++++++++++++++++++++++++++ +Function 152 is the CP/M 3.0 parser. It was a great innovation at +the time as parsing is one of the more tedious aspects of +programming for CP/M. Unfortunately, almost as soon as it +appeared, it was made obsolete by the fact that it didn't handle +references to user number (DU references). A line such as +A:FILE.TYP would be correctly parsed, but A3:FILE.TYP would not. +CP/M 3.0 programs would often parse the drive and user +separately, then give function 152 the line without the DU: +reference. All this extra work should not have been necessary if +CP/M 3.0 had included user number parsing. + +ZPM3 parses the user number, and goes even further by handling +named directories for ZCPR. This is possible as long as you set a +special word in the SCB which tells ZPM3 where to find the ZCPR +system environment descriptor. ZCCP, a companion CCP for ZPM3, +handles this automatically, but for Z3PLUS users, a special +utility is available which automatically sets this word. + +The result is that CP/M 3.0 programs will not balk at DU: +references and ZPM3 aware programs can use the full DU: and DIR: +facilities of function 152. It has also made the brilliant ZCCP +code possible. + + +New Functions 54 and 55 ++++++++++++++++++++++++ +Datestamps in CP/M 3.0 are wonderful, but difficult to +manipulate. Two new functions make them easier to handle and at +the same time give compatibility to Z80DOS aware programs. + +Function 54 (Get Stamp) returns a Z80DOS compatible datestamp. +Any program (such as many directory programs) which recognise the +Z80DOS standard can make use of function 54. There is only one +slight difference between Z80DOS datestamps and ZPM3's which you +should be aware of. Z80DOS will return a correct datestamp after +any successful open or search of any extent. ZPM3 can only return +a correct datestamp after a successful open or search of the +first extent of the file. This is because CP/M 3.0 datestamps are +only saved for the first extents of each file, in order to +provide the highest performance. + +Even more interesting is Function 55 (Use Stamp) which provides a +mechanism for changing datestamps on files. Trying to do this +with CP/M 3.0 was virtually impossible because it involved direct +sector writes. With Function 55 you can simply set the stamp and +then write. + + +Wheel protected files ++++++++++++++++++++++ +If you are using a ZCPR system (ZCCP or Z3PLUS), ZPM3 has access +to the wheel byte and supports wheel protected files. Such files +act normally if the wheel is set (signifying a priveleged user), +but if the wheel is not set, the files can not be changed. This +is of most benefit to BBS systems. The implementation is +virtually the same as most current Z80 CP/M 2.2 compatible +BDOSes. + + +Better error messages ++++++++++++++++++++++ +CP/M 3.0 introduced the best error messages that CP/M had ever +had. ZPM3 goes further. The main difference you will notice is +that the user number as well as the drive is shown in the error +message. This is invaluable in helping you identify which file +might have caused a problem. + + +Function 10 history buffer and improved editing. +++++++++++++++++++++++++++++++++++++++++++++++++ +Function 10 is used by the CCP to input command lines. Many other +programs use function 10 for input. + +CP/M 3.0 introduced a history buffer for function 10. You press +control-W and you were returned the last command. It is a great +facility, but because it only remembers one command it is rather +limited. There have been RSXes written which give a much larger +history buffer, but RSXes take up extra program memory so are +undesirable. + +ZPM3 gives a large (approximately 250 bytes) history buffer which +can store multiple commands. It also makes very intelligent use +of the buffer so that identical commands are not stored twice, +and commands of less than three characters are not stored. The +history buffer takes up no additional memory, and is always +available. + +For security, it is possible to clear the history buffer so that +other users can not see what commands you have used. + +The ZPM3 history buffer feature is so good, that for many users, +the ZPM3 upgrade is completely justified by it. + +As part of the history buffer system, ZPM3 also offers a facility +called Automatic Command Prompting. This can be disabled, or can +be made switchable from the keyboard. When it is on, ZPM3 tries +to fill in the rest of your command based on what commands you +used most recently. It is like magic, and can save you typing out +complicated commands many times. In effect, it looks through the +history buffer for you and finds the command it thinks you want. +As you keep typing, if it turns out that the command doesn't +match anymore, it will try to match another command, and if it +can't, it lets you make the command by yourself. This facility is +quite amazing to watch. + +And to integrate the history buffer and the automatic command +prompting, function 10 has the best command line editing you'll +find anywhere. Most of the control keys do something when you are +editing a function 10 line, and for the most part they mimic the +standard WordStar/NewWord/ZDE functions. You can jump to +different words in the command, delete individual words, delete +individual letters, insert letters, and a whole lot more. + + +Here is a list of what the various control keys do for function +10: + +A Move left one word +B Go to the beginning or end of the line +C Warm boot if at start of line, otherwise nothing +D Go right one character +E Go backwards one command in the history buffer +F Go right one word +G Delete current character +H Destructive backspace +I +J Enter line +K Delete all to the right +L +M Enter line +N +O +P Toggle printing +Q Toggle automatic command prompting (if enabled) +R +S Go left one character +T Delete current word +U Add current line to history buffer +V Clear line and delete from history buffer +W Go forwards one command in the history buffer +X Delete all to the left +Y Clear the whole line +Z + + +CPMLDR.REL bug fixed. ++++++++++++++++++++++ +If you have ever tried to use the CPMLDR.REL code supplied with +CP/M 3.0 to load a CPM3.SYS file larger than 16k, you have +probably come across the CPMLDR.REL bug. The computer probably +crashed, and you were left wondering what you did wrong in your +bios. + +Well CPMLDR.REL has a bug. To solve this for you ZPM3 comes with +ZPM3LDR.REL which directly replaces CPMLDR.REL. It is also +somewhat better in that all the messages, and the fcb for loading +CPM3.SYS, are at the start of the file along with plenty of spare +room. As a result you can easily patch the signon and error +messages to say whatever you like and even change the FCB to load +a file called something other than CPM3.SYS. + + + + +All About the Random Read Bug. +============================== +Never heard of it? Well it's there in CP/M 3.0. I spent a lot of +time trying to work out what it was and just why it was +happening, and if you are interested, here are the details. + +CP/M 3.0 uses the Record Count byte of an active FCB a little +differently from the way CP/M 2.2 does. It is mentioned in the +CP/M 3.0 manuals that the record count may contain numbers +greater than 128, but in such a case it implies that the record +count is really 128. CP/M 2.2 would not return record counts +greater than 128. + +The reason for the use of the record count in this way is to help +speed up some of the logic used to find records in a file. It +works very well for sequential access. When it comes to random +access, the system has some failings. + +The idea behind CP/M 3.0's unusual use of the record count is to +keep the record count of the last logical extent of the current +physical extent always in the Record Count byte. When accessing +extents before the last one, bit 7 of the byte is set. That way +it will always be at least 128 for logical extents before the +last (which CP/M 3.0 translates to mean equal to 128), and the +lower 7 bits are used as convenient storage for the record count +of the last logical extent. This is particularly convenient +because it means there is no need to go and read the directory +entry again when it comes time to read the last logical extent. + +I hope you have followed that! In sequential access, this scheme +is great. The problem occurs with random access. In this case it +is possible to access a logical extent which has no records in +it. This could be any logical extent past the last one. In such a +case the record count must be returned as 0 (which is correct). +If we then go back to a previous logical extent in the same +physical extent, CP/M 3.0 gets confused and assumes that there +must be 128 records in that extent because the one we just came +from had no records and we are now accessing an earlier extent. +You're probably well and truly lost by now! + +Anyhow, the assumption that CP/M 3.0 makes is quite wrong. The +record count ends up being set to 128, a read is allowed to go +ahead as if nothing was wrong, no error is returned, and the +record count remains incorrectly set until a different physical +extent is opened. The result could be chaos, but mostly it just +means that a program returns the wrong information. + +Remember, a logical extent is always 16k. A physical extent can +be a multiple of 16k and is all the data described by one +directory entry. If your system has physical extents which are +16k, you would never have the problem because a new physical +extent would be properly opened for every new logical extent that +was accessed. + +Typically though, a physical extent is 32k, so it holds 2 logical +extents. The problem won't arise until the file grows past the +32k mark in such a case. And when the file gets over 48k the +problem can't occur again until it gets over 64k... and so on. +Even then, it can only happen if reads are attempted to +particular extents in a particular order. So you shouldn't be too +surprised if the bug hasn't been too noticeable to you. + +ZPM3 squashes the bug once and for all by using the correct +logic. In the situation where the bug would normally occur, ZPM3 +makes sure it gets the correct record count information, and the +reads return the correct record count every time. + +If you are interested in seeing a demonstration of the bug in +action (on CP/M 3.0) and comparing it with ZPM3, there is a file +floating around various bulletin boards which contains +demonstrations for the bug and an RSX to fix it. The RSX is a +less than perfect way of overcoming the bug, although it seems to +work. However, now that you have ZPM3, you don't need to worry. + + + + +Other things you should know about ZPM3 +======================================= +ZPM3 has worked on EVERY CP/M 3.0 system tried so far except one. +This is a Bondwell computer, and as yet it isn't clear why it +won't work. I will study the source code of its BIOS and come up +with a fix shortly. + +The MAKEDOS.COM utility is not perfect (as mentioned previously) +and it seems that nobody has managed to get it to work with the +Commodore C128 system. You must use the conventional method for +installing ZPM3 on such systems. + +If you have a computer that ZPM3 will not install on with MAKEDOS +and you do not have access to the files required to do a +conventional install, please contact me. I am interested in +making ZPM3 as universal as possible and will help you to install +it on your system. + +The ESCAPE key is ignored by function 10. There has been some +lively discussion about this but the decision is final: it stays +ignored. Remember what function 10 is for and you will understand +why I made it ignore the ESCAPE key. The argument against this +has been from people who control their terminals from the command +line. Apparently some people type in an escape sequence at the +command line (which CP/M 3.0 will not output correctly anyhow +(converting the escape character to ^[)) then press return to +have the CCP echo back the line including the escape character. + +Sorry folks, that is a KLUDGE in my books! Anybody using Z-System +would of course use an ALIAS and ECHO to do this properly, but +for those who will continue to complain that I have sacrificed +CP/M 3.0 compatibility I am now including ECHOTERM.COM to solve +your problems. Run it and whatever you type will be sent to the +terminal correctly after you press RETURN. Press RETURN twice to +exit the program. + +And a reminder that the ability to put control characters into +function 10 lines was always limited by the fact that some +control keys were used to edit the command line. CP/M 3.0 added +even more, and ZPM3 uses virtually all the control keys. The few +that aren't used are ignored, and this is in fact a FEATURE which +guarantees that unusable characters can't get into function 10 +lines by accident. + + + + +LEGALS and SUCH +=============== +The ZPM3 package is supplied free of charge, on the condition +that you don't use it to make money. If you want to use it +commercially you must contact me to get the OK (and negotiate our +fee). + +If you find anyone (except myself) charging money for ZPM3, +please inform me! + +Nobody is making any guarantees about this software. None at all. +If it causes your house to burn down, or a divorce, or just a bad +day, this is unfortunate, regrettable, but there is nothing that +I can or will do about it. You have been warned. + +The ZPM3 package must only be distributed in the form that you +found it. Do not change or add anything. Don't even change it +into a different type of archive. Just leave it alone. However +you are free to distribute it to as many places and people that +you can. Just don't charge for it. + + + +If in using ZPM3 you find that it doesn't act as described, +please forward the details to me so that either the ZPM3 code or +the documentation can be changed. If you would like further +details, please forward your specific questions to me. SJC. + + + + +As a service to all our ZPM3 fans, the latest version of the ZPM3 +package can now be ordered. At this stage we can only supply IBM +formatted 3.5 inch 720k disks, however if you are keen enough +that shouldn't matter. ZPM3 remains free, however this service +will cost you $15 Australian (for the disk, copying, postage and +packing) to most places in the Western World (others by +arrangement). + +This is a good way to guarantee you have the latest version, and +to guarantee that your package has not been corrupted by some +unscrupulous person. + +When we fill your order, we will make sure to include the latest +demonstration copy of MYZ80 - the fastest and best Z80 emulator +for IBM AT (and better) compatibles. MYZ80 can run ZPM3 with +ease. It also handles ZCPR and CP/M 2.2. And yes, we do mean +FASTEST. + +Send your international money order to: + + Software by Simeon + ZPM3 Package + 2 Maytone Ave + Killara NSW + Australia 2071 + +Your order will be promptly filled. + \ No newline at end of file diff --git a/Doc/ChangeLog.txt b/Doc/ChangeLog.txt index cf1bdd7b..fcea7f27 100644 --- a/Doc/ChangeLog.txt +++ b/Doc/ChangeLog.txt @@ -1,7 +1,25 @@ Version 3.6 ----------- +- RDG: Added VDA driver for Xosera FPGA-based VDC - MGG: Added COBOL language disk image - WDC: Added config options to PCF driver +- WBW: Enabled dynamic CPU speed update on LCD screen +- WBW: Improve LPT driver boot messaging when not detected (per Robb Bates) +- WBW: Correct DS1307 boot date/time display (per Tadeusz Pycio) +- WBW: Add -DELAY option to TUNE app (per Robb Bates) +- RDG: Add online documentation site +- WBW: Added enhanced Hi-Tech C Compiler files from Ladislau Szilagyi +- WBW: Added boundary check to ram/rom disk driver +- WBW: Per Peter Onion, switch KERMIT default file xfer mode to binary +- J?L: Source for ZSDOS2 and BPBIOS Utilities (from disassembly) +- WBW: Support ROM-based font storage +- MAP: New Slice Inventory Rom App "S" display bootable slices, during boot +- MAP: Device Inventory moved from HBIOS to Rom App, saving >1k space in HBIOS +- MAP: Added disk image for all Infocom text adventure Games +- M?R: Fixed formatting issue with SLABEL where Slice # < 10 +- WBW: Improved image creation process to allow user defined aggregates +- WBW: Implemented config driven slice name and system image specification +- D?N: Added native USB driver support (keyboard, floppy, mass storage) Version 3.5.1 ------------- diff --git a/Doc/Language/Cowgol Compiler Manual.pdf b/Doc/Language/Cowgol Compiler Manual.pdf new file mode 100644 index 00000000..4b36f201 Binary files /dev/null and b/Doc/Language/Cowgol Compiler Manual.pdf differ diff --git a/Doc/Language/HI-TECH Z80 C Compiler Messages.txt b/Doc/Language/HI-TECH Z80 C Compiler Messages.txt new file mode 100644 index 00000000..cd0af096 --- /dev/null +++ b/Doc/Language/HI-TECH Z80 C Compiler Messages.txt @@ -0,0 +1,99 @@ +1 "dimension required" +2 "functions can't return arrays" +3 "functions can't return functions" +4 "can't have array of functions" +5 "argument redeclared: %s" +6 "not an argument: %s" +7 "undefined struct/union: %s" +8 "can't have array of functions" +9 "only functions may be void" +10 "functions can't return arrays" +11 "declarator too complex" +12 "no identifier in declaration" +13 "can't initialize arg" +14 "argument redeclared: %s" +15 "bad storage class" +16 "can't mix proto and non-proto args" +17 "type specifier reqd. for proto arg" +18 "can't initialise auto aggregates" +19 "integer expression required" +20 "undefined enum tag: %s" +21 "integer constant expected" +22 "bad bitfield type" +23 "members cannot be functions" +24 "struct/union redefined: %s" +25 "can't be unsigned" +26 "can't be short" +27 "can't be long" +28 "can't be register" +29 "inconsistent type" +30 "bad storage class" +31 "storage class illegal" +32 "inconsistent storage class" +33 "illegal initialisation" +34 "only register storage class allowed" +35 "too much indirection" +36 "argument list conflicts with prototype" +37 "identifier redefined: %s" +38 "not a label identifier: %s" +39 "'case' not in switch" +40 "'default' not in switch" +41 "default case redefined" +42 "inappropriate break/continue" +43 "illegal type for switch expression" +44 "inappropriate 'else'" +45 "illegal initialisation" +46 "initialisation syntax" +47 "illegal initialisation" +48 "%s expected" +49 "close error (disk space?)" +50 "digit out of range" +51 "hex digit expected" +52 "exponent expected" +53 "'.' expected after '..'" +54 "char const too long" +55 "illegal character (0%o)" +56 "illegal conversion" +57 "logical type required" +58 "type conflict" +59 "simple type required for %.3s" +60 "integral type required" +61 "illegal use of void expression" +62 "void function cannot return value" +63 "pointer required" +64 "only lvalues may be assigned to or modified" +65 "can't take this address" +66 "can't take address of register variable" +67 "undefined struct/union: %s" +68 "struct/union member expected" +69 "struct/union required" +70 "illegal type for index expression" +71 "not a variable identifier: %s" +72 "undefined identifier: %s" +73 "expression syntax" +74 "illegal type for array dimension" +75 "constant expression required" +76 "too few arguments" +77 "too many arguments" +78 "function does not take arguments" +79 "float param coerced to double" +80 "non-void function returns no value" +81 "Unreachable code" +82 "implicit return at end of non-void function" +83 "Can't create xref file %s" +84 "implicit conversion of float to integer" +85 "illegal conversion between pointer types" +86 "illegal conversion of pointer to integer" +87 "illegal conversion of integer to pointer" +88 "%s() declared implicit int" +89 "operands of %.3s not same type" +90 "operands of %.3s not same pointer type" +91 "function or function pointer required" +92 "Can't create xref file %s" +93 "close error (disk space?)" +94 "Can't reopen %s" +95 "can't open %s" +96 "illegal '#' directive" +97 "EOF in #asm" +98 "Too many cases in switch" +99 "unexpected EOF" diff --git a/Doc/Language/ReadMe.txt b/Doc/Language/ReadMe.txt index 3fb9b397..bd6ad74c 100644 --- a/Doc/Language/ReadMe.txt +++ b/Doc/Language/ReadMe.txt @@ -11,45 +11,53 @@ distribution archive. It contains documentation for Programming Languages provided with the system. -Aztec C Compiler User Manual (Aztec_C_1.06_User_Manual_Mar84.pdf) +Aztec C Compiler User Manual ("Aztec_C_1.06_User_Manual_Mar84.pdf") ----------------------------------------------------------------- Official user manual for the Aztec C Compiler included in the aztecc disk image. -Borland TurboPascal User Manual (Turbo_Pascal_Version_3.0_Reference_Manual_1986.pdf) +Borland TurboPascal User Manual ("Turbo_Pascal_Version_3.0_Reference_Manual_1986.pdf") ------------------------------------------------------------------------------------ Official user manual Borland TurboPascal included in the pascal disk image. -Cowgol Lanaguage (Cowgol Language.pdf) +The Cowgol Lanaguage ("The Cowgol Language.pdf") +Cowgol Compiler Manual ("Cowgol Compiler Manual.pdf") + -------------------------------------- -Documentation for Cowgol Language included in the cowgol disk image +Documentation for Cowgol Language included in the cowgol disk image. +The Cowgol Language describes the Cowgol Language itself while the +Cowgol Compiler Manual describes the compiler operation. -HI-TECH C Compiler User Manual (HI-TECH Z80 C Compiler Manual.txt) +HI-TECH C Compiler User Manual ("HI-TECH Z80 C Compiler Manual.txt") +HI-TECH C Compiler Messages ("HI-TECH Z80 C Compiler Messages.txt") ------------------------------------------------------------------ Official user manual for the HI-TECH C Compiler included in the -hitechc disk image. - +hitechc disk image. The Compiler Messages file provides textual +descriptions of all compiler error and warning codes. These textual +messages have been omitted from the size optimized version of +HI-TECH C found in User Area 1 of the disk image. See the ReadMe.txt +file in the hitechc disk image for more information. -Microsoft Basic-80 Reference Manual v5.0 (Microsoft Basic-80 Reference Manual v5.0.pdf) +Microsoft Basic-80 Reference Manual v5.0 ("Microsoft Basic-80 Reference Manual v5.0.pdf") --------------------------------------------------------------------------------------- Official manual for Microsoft BASIC as included in RomWBW. -Microsoft FORTRAN-80 User Manual (Microsoft_FORTRAN-80_Users_Manual_1977.pdf) +Microsoft FORTRAN-80 User Manual ("Microsoft_FORTRAN-80_Users_Manual_1977.pdf") ----------------------------------------------------------------------------- Official user manual for Microsoft's FORTRAN-80 compiler included in the fortran disk image. -Z80 Assembler User Manual (z80asm (SLR Systems).pdf) +Z80 Assembler User Manual ("z80asm (SLR Systems).pdf") ---------------------------------------------------- Official user manual for the Z80 Macro Assembler by SLR Systems diff --git a/Doc/ReadMe.txt b/Doc/ReadMe.txt index b78528d3..61594c4b 100644 --- a/Doc/ReadMe.txt +++ b/Doc/ReadMe.txt @@ -28,6 +28,7 @@ ChangeLog.txt Log of changes in RomWBW by version. +RomWBW Introduction ("RomWBW Introduction.pdf") RomWBW User Guide ("RomWBW User Guide.pdf") RomWBW System Guide ("RomWBW System Guide.pdf") RomWBW Applications ("RomWBW Applications.pdf") @@ -84,4 +85,4 @@ UCSD p-System Users Manual ("UCSD p-System Users Manual.pdf") Official user manual for p-System operating system included with RomWBW. ---WBW 5:18 PM 6/14/2023 +--WBW 8:37 AM 6/6/2025 diff --git a/Doc/RomWBW Applications.pdf b/Doc/RomWBW Applications.pdf index f480fe75..6563a185 100644 Binary files a/Doc/RomWBW Applications.pdf and b/Doc/RomWBW Applications.pdf differ diff --git a/Doc/RomWBW Disk Catalog.pdf b/Doc/RomWBW Disk Catalog.pdf index 406f9d29..e26862f5 100644 Binary files a/Doc/RomWBW Disk Catalog.pdf and b/Doc/RomWBW Disk Catalog.pdf differ diff --git a/Doc/RomWBW Hardware.pdf b/Doc/RomWBW Hardware.pdf index b3a38686..4379b959 100644 Binary files a/Doc/RomWBW Hardware.pdf and b/Doc/RomWBW Hardware.pdf differ diff --git a/Doc/RomWBW Introduction.pdf b/Doc/RomWBW Introduction.pdf index 2e5d408f..6753e46c 100644 Binary files a/Doc/RomWBW Introduction.pdf and b/Doc/RomWBW Introduction.pdf differ diff --git a/Doc/RomWBW System Guide.pdf b/Doc/RomWBW System Guide.pdf index 340d1332..988c44df 100644 Binary files a/Doc/RomWBW System Guide.pdf and b/Doc/RomWBW System Guide.pdf differ diff --git a/Doc/RomWBW User Guide.pdf b/Doc/RomWBW User Guide.pdf index e11b341c..cbcfb3f4 100644 Binary files a/Doc/RomWBW User Guide.pdf and b/Doc/RomWBW User Guide.pdf differ diff --git a/Dockerfile b/Dockerfile index d2e716e1..0a9d0f28 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:jammy-20240111 as basebuilder +FROM ubuntu:jammy-20240111 AS basebuilder # This docker file can be used to build a tool chain docker image for building RomWBW images. @@ -10,7 +10,7 @@ FROM ubuntu:jammy-20240111 as basebuilder # After you have built the above image (called romwbw-chain), you can use it to compile and build the RomWBW images # as per the standard make scripts within RomWBW. # Start a new terminal, cd to where you have clone RomWBW, and then run this command: -# docker run -v ${PWD}:/src/ --privileged=true -u $(id -u ${USER}):$(id -g ${USER}) -it romwbw-chain:latest +# docker run --rm -v ${PWD}:/src/ --privileged=true -u $(id -u ${USER}):$(id -g ${USER}) -it romwbw-chain # you can now compile and build the required images: @@ -21,13 +21,11 @@ FROM ubuntu:jammy-20240111 as basebuilder # when finish, type 'exit' to return to back to your standard terminal session LABEL Maintainer="Dean Netherton" \ - Description="spike to use clang for ez80 target" + Description="RomWBW builder platform" ENV DEBIAN_FRONTEND=noninteractive - RUN dpkg --add-architecture i386 -RUN sed -i 's/http:\/\/archive\.ubuntu\.com\/ubuntu/http:\/\/au.archive.ubuntu.com\/ubuntu/g' /etc/apt/sources.list RUN apt update -y RUN apt dist-upgrade -y RUN apt install -y --no-install-recommends cmake lzip ca-certificates mtools build-essential dos2unix libboost-all-dev texinfo texi2html libxml2-dev subversion bison flex zlib1g-dev m4 git wget dosfstools curl @@ -35,10 +33,10 @@ RUN apt install -y --no-install-recommends cmake lzip ca-certificates mtools bui RUN mkdir work WORKDIR /work -FROM basebuilder as main +FROM basebuilder AS main LABEL Maintainer="Dean Netherton" \ - Description="spike to build RomWBW" + Description="RomWBW builder platform" RUN mkdir /src WORKDIR /src/ diff --git a/Makefile b/Makefile index 87fb9244..91b8f819 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: tools source clean clobber diff dist .ONESHELL: -.SHELLFLAGS = -cex +.SHELLFLAGS = -ce all: tools source @@ -22,6 +22,11 @@ clobber: clean diff: $(MAKE) --directory Source diff +# Convert c code to assembly code +transpile-c-code: + @cd Source/HBIOS/ch376-native + $(MAKE) -j + dist: $(MAKE) ROM_PLATFORM=dist $(MAKE) --directory Tools clean diff --git a/ReadMe.md b/ReadMe.md index 5192d03c..f487c156 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -7,12 +7,12 @@ **RomWBW Introduction** \ Version 3.6 \ Wayne Warthen ([wwarthen@gmail.com](mailto:wwarthen@gmail.com)) \ -23 May 2025 +22 Jul 2025 # Overview RomWBW software provides a complete, commercial quality implementation -of CP/M (and workalike) operating systems and applications for modern +of CP/M (and work-alike) operating systems and applications for modern Z80/180/280 retro-computing hardware systems. A wide variety of platforms are supported including those produced by @@ -49,7 +49,7 @@ Supported hardware features of RomWBW include: - Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip, Iomega - Serial drivers including UART (16550-like), ASCI, ACIA, SIO -- Video drivers including TMS9918, SY6545, MOS8563, HD6445 +- Video drivers including TMS9918, SY6545, MOS8563, HD6445, Xosera - Keyboard (PS/2) drivers via VT8242 or PPI interfaces - Real time clock drivers including DS1302, BQ4845 - Support for CP/NET networking using Wiznet, MT011 or Serial @@ -191,6 +191,9 @@ documentation: discusses much of the internal design and construction of RomWBW. It includes a reference for the RomWBW HBIOS API functions. +An online HTML version of this documentation is hosted at +. + Each of the operating systems and ROM applications included with RomWBW are sophisticated tools in their own right. It is not reasonable to fully document their usage. However, you will find complete manuals in @@ -287,8 +290,12 @@ let me know if I missed you! - Tasty Basic is a product of Dimitri Theulings. -- Dean Netherton contributed eZ80 CPU support, the sound driver - interface, and the SN76489 sound driver. +- Dean Netherton contributed multiple components: + + - eZ80 CPU support + - Sound driver infrastructure + - SN76489 sound driver + - Native USB driver (keyboard, floppy, mass storage) - The RomWBW Disk Catalog document was produced by Mykl Orders. @@ -304,8 +311,10 @@ let me know if I missed you! - significant content in the Disk Catalog and User Guide - creation of the Introduction and Hardware documents - Z3PLUS operating system disk image - - COPYSL utility - - SLABEL utility + - Infocom text adventure game disk image + - COPYSL, and SLABEL utilities + - Display of bootable slices via “S” command during startup + - Optimisations of HBIOS and CBIOS to reduce overall code size - a feature for RomWBW configuration by NVRAM - the /B bulk mode of disk assignment to the ASSIGN utility @@ -340,6 +349,12 @@ let me know if I missed you! - Les Bird has contributed support for the NABU w/ Option Board +- Rob Gowin created an online documentation site via MkDocs, and + contributed a driver for the Xosera FPGA-based video controller. + +- Jörg Linder has contributed disassembled and nicely commented source + for ZSDOS2 and the BPBIOS utilities. + ## Related Projects Outside of the hardware platforms adapted to RomWBW, there are a variety diff --git a/ReadMe.txt b/ReadMe.txt index 2a73568e..ef5dbc91 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -1,6 +1,6 @@ RomWBW Introduction Wayne Warthen (wwarthen@gmail.com) -23 May 2025 +22 Jul 2025 @@ -11,7 +11,7 @@ OVERVIEW RomWBW software provides a complete, commercial quality implementation -of CP/M (and workalike) operating systems and applications for modern +of CP/M (and work-alike) operating systems and applications for modern Z80/180/280 retro-computing hardware systems. A wide variety of platforms are supported including those produced by @@ -46,7 +46,7 @@ Supported hardware features of RomWBW include: - Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip, Iomega - Serial drivers including UART (16550-like), ASCI, ACIA, SIO -- Video drivers including TMS9918, SY6545, MOS8563, HD6445 +- Video drivers including TMS9918, SY6545, MOS8563, HD6445, Xosera - Keyboard (PS/2) drivers via VT8242 or PPI interfaces - Real time clock drivers including DS1302, BQ4845 - Support for CP/NET networking using Wiznet, MT011 or Serial @@ -193,6 +193,9 @@ documentation: construction of RomWBW. It includes a reference for the RomWBW HBIOS API functions. +An online HTML version of this documentation is hosted at +https://wwarthen.github.io/RomWBW. + Each of the operating systems and ROM applications included with RomWBW are sophisticated tools in their own right. It is not reasonable to fully document their usage. However, you will find complete manuals in @@ -294,8 +297,12 @@ let me know if I missed you! - Tasty Basic is a product of Dimitri Theulings. -- Dean Netherton contributed eZ80 CPU support, the sound driver - interface, and the SN76489 sound driver. +- Dean Netherton contributed multiple components: + + - eZ80 CPU support + - Sound driver infrastructure + - SN76489 sound driver + - Native USB driver (keyboard, floppy, mass storage) - The RomWBW Disk Catalog document was produced by Mykl Orders. @@ -311,8 +318,10 @@ let me know if I missed you! - significant content in the Disk Catalog and User Guide - creation of the Introduction and Hardware documents - Z3PLUS operating system disk image - - COPYSL utility - - SLABEL utility + - Infocom text adventure game disk image + - COPYSL, and SLABEL utilities + - Display of bootable slices via “S” command during startup + - Optimisations of HBIOS and CBIOS to reduce overall code size - a feature for RomWBW configuration by NVRAM - the /B bulk mode of disk assignment to the ASSIGN utility @@ -347,6 +356,12 @@ let me know if I missed you! - Les Bird has contributed support for the NABU w/ Option Board +- Rob Gowin created an online documentation site via MkDocs, and + contributed a driver for the Xosera FPGA-based video controller. + +- Jörg Linder has contributed disassembled and nicely commented source + for ZSDOS2 and the BPBIOS utilities. + Related Projects diff --git a/Source/Apps/Tune/cli.inc b/Source/Apps/Tune/cli.inc index cd9eaecf..5b998664 100644 --- a/Source/Apps/Tune/cli.inc +++ b/Source/Apps/Tune/cli.inc @@ -23,6 +23,19 @@ CLI_HAVE_HBIOS_SWITCH1 ; NOT MATCHED --HBIOS LD (HBIOSMD), A RET +CLI_HAVE_DELAY_SWITCH: + LD HL, CLIARGS ; TEST FOR --DELAY ON COMMAND LINE + LD DE, DELAYOPT + CALL STRINDEX + JR NZ, CLI_HAVE_DELAY_SWITCH1 + OR $FF ; MATCHED --DELAY + LD (DELAYMD), A + RET +CLI_HAVE_DELAY_SWITCH1 ; NOT MATCHED --HBIOS + XOR A + LD (DELAYMD), A + RET + CLI_PORTS: LD HL, CLIARGS ; TEST FOR -MSX ON COMMAND LINE LD DE, OPT_MSX @@ -101,7 +114,8 @@ CLI_OCTAVE_ADJST5: OPT_MSX .DB "-MSX", 0 ; USE MSX PORTS OPT_RC .DB "-RC", 0 ; USE RC PORTS -HBIOSOPT: .DB "--HBIOS", 0 +HBIOSOPT: .DB "--HBIOS", 0 ; USE HBIOS API FOR PLAYBACK +DELAYOPT: .DB "-DELAY",0 ; FORCE DELAY MODE DOWN1 .DB "-t1", 0 ; DOWN AN OCTAVE DOWN2 .DB "-t2", 0 ; DOWN TWO OCTAVE UP1 .DB "+t1", 0 ; UP AN OCTAVE diff --git a/Source/Apps/Tune/hbios.inc b/Source/Apps/Tune/hbios.inc index cba06045..e56a67c8 100644 --- a/Source/Apps/Tune/hbios.inc +++ b/Source/Apps/Tune/hbios.inc @@ -7,6 +7,6 @@ BF_SND .EQU $50 BF_SNDRESET .EQU BF_SND + 0 ; RESET SOUND SYSTEM BF_SNDVOL .EQU BF_SND + 1 ; REQUEST SOUND VOL - L CONTAINS VOLUME (255 MAX, 0 SILENT) - SCALED AS REQUIRED BY DRIVER (EG: MAPS TO JUST 4 BIT RESOLUTION FOR SN76489) BF_SNDPRD .EQU BF_SND + 2 ; REQUEST SOUND PERIOD - HL CONTAINS DRIVER SPECIFIC VALUE -BF_SNDNOTE .EQU BF_SND + 3 ; REQUEST NOTE - L CONTAINS NOTE - EACH VALUE IS QUARTER NOTE +BF_SNDNOTE .EQU BF_SND + 3 ; REQUEST NOTE - L CONTAINS NOTE - EACH VALUE IS AN EIGHTH TONE BF_SNDPLAY .EQU BF_SND + 4 ; INITIATE THE REQUESTED SOUND COMMAND BF_SNDQUERY .EQU BF_SND + 5 ; E IS SUBFUNCTION diff --git a/Source/Apps/Tune/timing.inc b/Source/Apps/Tune/timing.inc index 857e4d2c..dbf7e86a 100644 --- a/Source/Apps/Tune/timing.inc +++ b/Source/Apps/Tune/timing.inc @@ -41,8 +41,14 @@ DLY1 DEC BC ; [6] ; Test for timer running to determine if it can be used for delay ; Return string message in DE ; Assigned (WMOD) with 0 if no hardware time, 1 if hardware timer found +; If -DELAY on command line, force delay mode ; PROBETIMER: + LD A,(DELAYMD) ; GET COMMAND LINE DELAY FLAG + OR A ; TEST IT + LD A,0 ; ASSUME NO TIMER + LD DE,MSGDLY ; DELAY MODE MESSAGE + JR NZ,SETDLY ; IF TRUE, DONE LD B,BF_SYSGET ; HBIOS: GET function LD C,$D0 ; TIMER subfunction RST 08 ; DE:HL := current tick count diff --git a/Source/Apps/Tune/tune.asm b/Source/Apps/Tune/tune.asm index 32202d2e..41abfe92 100644 --- a/Source/Apps/Tune/tune.asm +++ b/Source/Apps/Tune/tune.asm @@ -53,6 +53,7 @@ ; 2024-07-11 [WBW] Updated, Les Bird's module now uses same settings as EB6 ; 2024-09-17 [WBW] Add support for HEATH H8 with Les Bird's MSX Card ; 2024-12-12 [WBW] Add options to force standard MSX or RC ports +; 2025-05-28 [WBW] Add option to force delay mode ;_______________________________________________________________________________ ; ; ToDo: @@ -113,6 +114,7 @@ Id .EQU 1 ; 5) Insert official identificator CALL CLI_ABRT_IF_OPT_FIRST CALL CLI_PORTS CALL CLI_HAVE_HBIOS_SWITCH + CALL CLI_HAVE_DELAY_SWITCH CALL CLI_OCTAVE_ADJST JP CONTINUE @@ -703,15 +705,16 @@ FILTYP .DB 0 ; Sound file type (TYPPT2, TYPPT3, TYPMYM) TMP .DB 0 ; work around use of undocumented Z80 HBIOSMD .DB 0 ; NON-ZERO IF USING HBIOS SOUND DRIVER, ZERO OTHERWISE +DELAYMD .DB 0 ; FORCE DELAY MODE IF TRUE (NON-ZERO) OCTAVEADJ .DB 0 ; AMOUNT TO ADJUST OCTAVE UP OR DOWN USEPORTS .DB 0 ; AUDIO CHIP PORT SELECTION MODE -MSGBAN .DB "Tune Player for RomWBW v3.12, 12-Dec-2024",0 -MSGUSE .DB "Copyright (C) 2024, Wayne Warthen, GNU GPL v3",13,10 +MSGBAN .DB "Tune Player for RomWBW v3.13, 28-May-2025",0 +MSGUSE .DB "Copyright (C) 2025, Wayne Warthen, GNU GPL v3",13,10 .DB "PTxPlayer Copyright (C) 2004-2007 S.V.Bulba",13,10 .DB "MYMPlay by Marq/Lieves!Tuore",13,10,13,10 - .DB "Usage: TUNE .[PT2|PT3|MYM] [-msx|-rc] [--hbios] [+tn|-tn]",0 + .DB "Usage: TUNE .[PT2|PT3|MYM] [-msx|-rc] [-delay] [--hbios] [+tn|-tn]",0 MSGBIO .DB "Incompatible BIOS or version, " .DB "HBIOS v", '0' + RMJ, ".", '0' + RMN, " required",0 MSGPLT .DB "Hardware error, system not supported!",0 diff --git a/Source/Apps/assign/assign.asm b/Source/Apps/assign/assign.asm index 2f760568..15c3b45b 100644 --- a/Source/Apps/assign/assign.asm +++ b/Source/Apps/assign/assign.asm @@ -38,6 +38,7 @@ ; 2024-12-17 [MAP] Added new /B=opt feaure to assign drives ; 2024-12-21 [MAP] Added CBIOS heap estimation to /B to prevent ; overflow when the drives are finally added +; 2025-07-19 [D?N] Support for native USB drivers ;_______________________________________________________________________________ ; ; ToDo: @@ -1179,8 +1180,9 @@ makdphwbw: ; determine appropriate dpb (WBW mode, unit number in A) jr makdph0 ; jump ahead makdph00: ld e,MID_FD144 ; assume floppy - cp DIODEV_FD ; floppy? - jr z,makdph0 ; yes, jump ahead + ;cp DIODEV_FD ; floppy? + bit 7,c ; floppy? + jr nz,makdph0 ; yes, jump ahead ld e,MID_RF ; assume ram floppy cp DIODEV_RF ; ram floppy? jr z,makdph0 ; yes, jump ahead @@ -1560,7 +1562,7 @@ drvmap: jr nz,drvmapu ; do UNA mode drvmap ; ; determine device code by scanning for string - ld b,16 ; device table always has 16 entries + ld b,devcnt ; number of entries in devtbl ld c,0 ; c is used to track table entry num ld de,tmpstr ; de points to specified device name ld hl,devtbl ; hl points to first entry of devtbl @@ -1826,7 +1828,7 @@ prtdev: rst 08 ; call hbios, D := device, E := unit push de ; save results ld a,d ; device to A - and $0F ; mask out undesired bits + and $1F ; mask out undesired bits push hl ; save HL add a,a ; multiple A by two for word table ld hl,devtbl ; point to start of device name table @@ -2427,6 +2429,7 @@ devtbl: ; device table .dw dev04, dev05, dev06, dev07 .dw dev08, dev09, dev10, dev11 .dw dev12, dev13, dev14, dev15 + .dw dev16 ; devunk .db "?",0 dev00 .db "MD",0 @@ -2444,9 +2447,10 @@ dev11 .db "IMM",0 dev12 .db "SYQ",0 dev13 .db "CHUSB",0 dev14 .db "CHSD",0 -dev15 .equ devunk +dev15 .db "USB",0 +dev16 .equ devunk ; -devcnt .equ 10 ; 10 devices defined +devcnt .equ 17 ; 17 device types defined ; udevram .db "RAM",0 udevrom .db "ROM",0 @@ -2464,13 +2468,13 @@ stack .equ $ ; stack top ; Messages ; indent .db " ",0 -msgban1 .db "ASSIGN v2.0 for RomWBW CP/M ",0 +msgban1 .db "ASSIGN v2.1 for RomWBW CP/M ",0 msg22 .db "2.2",0 msg3 .db "3",0 -msbban2 .db ", 21-Dec-2024",0 +msbban2 .db ", 19-Jul-2025",0 msghb .db " (HBIOS Mode)",0 msgub .db " (UBIOS Mode)",0 -msgban3 .db "Copyright 2024, Wayne Warthen, GNU GPL v3",0 +msgban3 .db "Copyright 2025, Wayne Warthen, GNU GPL v3",0 msguse .db "Usage: ASSIGN D:[=[{D:|[]:[]}]][,...]",13,10 .db " ex. ASSIGN (display all active assignments)",13,10 .db " ASSIGN /? (display version and usage)",13,10 diff --git a/Source/Apps/slabel/slabel.asm b/Source/Apps/slabel/slabel.asm index 9fbf167a..c17ff828 100644 --- a/Source/Apps/slabel/slabel.asm +++ b/Source/Apps/slabel/slabel.asm @@ -4,6 +4,9 @@ ;============================================================================== ; ; Author: Mark Pruden +; +; This is a SUPERSET of INVNTSLC.ASM -> Please See this program also when +; making changes, as code ( in routine prtslc: ) exists there also ;______________________________________________________________________________ ; ; Usage: @@ -32,6 +35,7 @@ ; table once (per device), and work out all the LBA's from this single read. ; Note this doesnt omit the fact that the 3 rd sector of each slice wold need to be read regarless. ; To slightly reduce some IO only slices < 64 are considered. +; - Output formatting misaligned with storage units enumerated as greater than 9 (ie 2 digits) ; ; This code will only execute on a Z80 CPU (or derivitive) ; This code requirs the use of HBIOS @@ -42,6 +46,7 @@ ; 2024-12-11 [MAP] Started - Reboot v1.0 used as the basis for this code ; 2024-12-14 [MAP] Initial 0.9 alpha with basic working functionality ; 2025-04-21 [MAP] Initial v1.0 release for distribution, fixing all issues +; 2025-07-12 [MR] Minor tweak to partially tidy up output formatting ;______________________________________________________________________________ ; ; Include Files @@ -91,7 +96,7 @@ exit: jp restart ; return to CP/M via restart ; ;=============================================================================== -; Initialization +; Initialisation ; init: ; check for UNA (UBIOS) @@ -208,10 +213,10 @@ prtslc2a: ld a,c ; slice number ld (currslice),a ; save slice number ; - push bc ; save loop + push bc ; save loop counter call prtslc3 ; print detals of the slice - pop bc ; restore loop - ret nz ; if error dont continie + pop bc ; restore loop counter + ret nz ; if error don't continue ; inc c ; next slice number djnz prtslc2a ; loop if more slices @@ -245,15 +250,25 @@ prtslc3: cp c ; compare jr nz,prtslc5 ; ignore missing signature and loop ; - ; Print volume label string at HL, '$' terminated, 16 chars max + ; Print slice label string at HL, '$' terminated, 16 chars max ld a,(currunit) call prtdecb ; print unit number as decimal call pdot ; print a DOT - ld a,(currslice) + ld a, (currslice) ; fetch the current slice numeric call prtdecb +; +;------------------------------------------------------------------------------- +; Added by MartinR, July 2025, to help neaten the output formatting. +; Note - this is not a complete fix and will still result in misaligned output +; where the unit number exceeds 9 (ie - uses 2 digits). + cp 10 ; is it less than 10? ld a,' ' + jr nc,jr01 ; If not, then we don't need an extra space printed + call cout ; print the extra space necessary +jr01: call cout ; print a space call cout ; print a space - call cout ; print a space +;------------------------------------------------------------------------------- +; ld hl,bb_label ; point to label call pvol ; print it call crlf @@ -435,6 +450,7 @@ pdot: ; ;------------------------------------------------------------------------------- ; Print character in A without destroying any registers +; Use CP/M BDOS function $02 - Console Output ; prtchr: cout: @@ -684,7 +700,7 @@ diskwrite: ;=============================================================================== ; str_banner .db "\r\n" - .db "Slice Label, v1.0, April 2025 - M.Pruden",0 + .db "Slice Label, v1.1, July 2025 - M.Pruden",0 ; str_err_una .db " ERROR: UNA not supported by application",0 str_err_inv .db " ERROR: Invalid BIOS (signature missing)",0 @@ -703,7 +719,7 @@ str_usage .db "\r\n\r\n" .db " Options are case insensitive.\r\n",0 ; PRTSLC_HDR .TEXT "\r\n\r\n" - .TEXT "Un.Sl Drive \r\n" + .TEXT "Un.Sl Label \r\n" .TEXT "----- ----------------\r\n" .DB 0 ; diff --git a/Source/BPBIOS/@WBW Issues.txt b/Source/BPBIOS/@WBW Issues.txt index ae68d9a6..99649c81 100644 --- a/Source/BPBIOS/@WBW Issues.txt +++ b/Source/BPBIOS/@WBW Issues.txt @@ -15,8 +15,7 @@ as needed. The RomWBW ASSIGN command is not supported. BPBIOS will boot from the first hard disk unit number you assign and always from the first slice. -BPBIOS does not yet understand the 1024 directory entry -hard disk format. You must use the 512 directory entry -format images. +BPBIOS is hard-coded to use the 1024 directory entry hard disk +format (hd1k). The hd512 format is not supported at all. ---WBW 1:25 PM 10/7/2021 \ No newline at end of file +--WBW 5:04 PM 6/16/2025 \ No newline at end of file diff --git a/Source/BPBIOS/Build.cmd b/Source/BPBIOS/Build.cmd index b83df0c4..7460512e 100644 --- a/Source/BPBIOS/Build.cmd +++ b/Source/BPBIOS/Build.cmd @@ -2,6 +2,7 @@ setlocal pushd ZCPR33 && call Build || exit /b & popd +pushd UTIL && call Build || exit /b & popd set TOOLS=..\..\Tools set PATH=%PATH%;%TOOLS%\zxcc;%TOOLS%\cpmtools; diff --git a/Source/BPBIOS/Clean.cmd b/Source/BPBIOS/Clean.cmd index c0174859..69ed8e43 100644 --- a/Source/BPBIOS/Clean.cmd +++ b/Source/BPBIOS/Clean.cmd @@ -11,3 +11,4 @@ if exist *.bak del *.bak if exist def-ww.lib del def-ww.lib pushd ZCPR33 && call Clean.cmd & popd +pushd UTIL && call Clean.cmd & popd diff --git a/Source/BPBIOS/Makefile b/Source/BPBIOS/Makefile index fd405b9f..15a600d7 100644 --- a/Source/BPBIOS/Makefile +++ b/Source/BPBIOS/Makefile @@ -13,7 +13,7 @@ OTHERS = zcpr33.rel bp*.prn bp*.rel \ TOOLS = ../../Tools -SUBDIRS = ZCPR33 +SUBDIRS = ZCPR33 UTIL include $(TOOLS)/Makefile.inc zcpr33.rel: diff --git a/Source/BPBIOS/UTIL/Build.cmd b/Source/BPBIOS/UTIL/Build.cmd new file mode 100644 index 00000000..6a94b476 --- /dev/null +++ b/Source/BPBIOS/UTIL/Build.cmd @@ -0,0 +1,55 @@ +@echo off +setlocal + +set TOOLS=..\..\..\Tools +set PATH=%PATH%;%TOOLS%\zxcc;%TOOLS%\cpmtools; +set CPMDIR80=%TOOLS%/cpm/ + +zxcc Z80ASM -BPBUILD/RFS || exit /b +zxcc SLRNK -BPBUILD/N,/A:100,/D:23E0,BPBUILD,B:SLINK0,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -BPCNFG/RFS || exit /b +zxcc SLRNK -BPCNFG/N,/A:100,/D:3A55,BPCNFG,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -BPSWAP/RFS || exit /b +zxcc SLRNK -BPSWAP/N,/A:100,/D:0854,BPSWAP,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -BPSYSGEN/RFS || exit /b +zxcc SLRNK -BPSYSGEN/N,/A:100,/D:08CD,BPSYSGEN,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -CONFZ4/RFS || exit /b +zxcc SLRNK -CONFZ4/N,/A:100,/D:080A,CONFZ4,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -HASHINI/RFS || exit /b +zxcc SLRNK -HASHINI/N,/A:100,/D:09E5,HASHINI,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -LDSYS/RFS || exit /b +zxcc SLRNK -LDSYS/N,/A:100,/D:0CF8,LDSYS,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -SHOWHD/RFS || exit /b +zxcc SLRNK -SHOWHD/N,/A:100,/D:064D,SHOWHD,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -SIZERAM/RFS || exit /b +zxcc SLRNK -SIZERAM/N,/A:100,/D:0750,SIZERAM,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + +zxcc Z80ASM -ZSCFG2/RFS || exit /b +zxcc SLRNK -ZSCFG2/N,/A:100,/D:145E,ZSCFG2,B:VLIBS/S,B:Z3LIBS/S,B:SYSLIBS/S,/E || exit /b + + + + + + + + + + + + + + + + + +:: zxcc Z80ASM +:: zxcc ZMAC -zcpr33.z80 -/P || exit /b diff --git a/Source/BPBIOS/UTIL/Clean.cmd b/Source/BPBIOS/UTIL/Clean.cmd new file mode 100644 index 00000000..96451c7d --- /dev/null +++ b/Source/BPBIOS/UTIL/Clean.cmd @@ -0,0 +1,6 @@ +@echo off +setlocal + +if exist *.com del *.com +if exist *.lst del *.lst +if exist *.rel del *.rel diff --git a/Source/BPBIOS/UTIL/Makefile b/Source/BPBIOS/UTIL/Makefile new file mode 100644 index 00000000..d09154f8 --- /dev/null +++ b/Source/BPBIOS/UTIL/Makefile @@ -0,0 +1,40 @@ +OBJECTS = bpbuild.com bpcnfg.com bpswap.com bpsysgen.com confz4.com hashini.com \ + ldsys.com showhd.com sizeram.com zscfg2.com +TOOLS = ../../../Tools +# DEST = .. +OTHERS = *.rel + +include $(TOOLS)/Makefile.inc + +%.rel: %.z80 + @$(ZXCC) $(CPM)/Z80ASM -$(basename $<)/RFS + +bpbuild.com : bpbuild.rel + $(ZXCC) $(CPM)/SLRNK -bpbuild/n,/a:100,/d:23e0,bpbuild,b:slink0,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e + +bpcnfg.com : bpcnfg.rel + $(ZXCC) $(CPM)/SLRNK -bpcnfg/n,/a:100,/d:3a55,bpcnfg,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e + +bpswap.com : bpswap.rel + $(ZXCC) $(CPM)/SLRNK -bpswap/n,/a:100,/d:0854,bpswap,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e + +bpsysgen.com : bpsysgen.rel + $(ZXCC) $(CPM)/SLRNK -bpsysgen/n,/a:100,/d:08cd,bpsysgen,b:z3libs/s,b:syslibs/s,/e + +confz4.com : confz4.rel + $(ZXCC) $(CPM)/SLRNK -confz4/n,/a:100,/d:080a,confz4,b:z3libs/s,b:syslibs/s,/e + +hashini.com : hashini.rel + $(ZXCC) $(CPM)/SLRNK -hashini/n,/a:100,/d:09e5,hashini,b:z3libs/s,b:syslibs/s,/e + +ldsys.com : ldsys.rel + $(ZXCC) $(CPM)/SLRNK -ldsys/n,/a:100,/d:0cf8,ldsys,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e + +showhd.com : showhd.rel + $(ZXCC) $(CPM)/SLRNK -showhd/n,/a:100,/d:064d,showhd,b:syslibs/s,/e + +sizeram.com : sizeram.rel + $(ZXCC) $(CPM)/SLRNK -sizeram/n,/a:100,/d:0750,sizeram,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e + +zscfg2.com : zscfg2.rel + $(ZXCC) $(CPM)/SLRNK -zscfg2/n,/a:100,/d:145e,zscfg2,b:vlibs/s,b:z3libs/s,b:syslibs/s,/e diff --git a/Source/BPBIOS/UTIL/bpbuild.z80 b/Source/BPBIOS/UTIL/bpbuild.z80 new file mode 100644 index 00000000..e427b741 --- /dev/null +++ b/Source/BPBIOS/UTIL/bpbuild.z80 @@ -0,0 +1,2357 @@ + TITLE "B/P Bios Build System Image" +;************************************************************************ +;* B P B U I L D * +;* Create a system image file containing B/P Bios * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Jan 2025 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB * +;* and SLINK0.REL module (as included in ZSDOS v1 GNU public release) * +;* * +;* A>Z80ASM BPBUILD/RS * +;* A>SLRNK BPBUILD/N,/A:100,/D:23E0,BPBUILD,SLINK0,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 10 +REV EQU ' ' + +DATE MACRO + DEFB '31 Aug 92' + ENDM + + +CTRLC EQU 03H ; Control-C character +BEL EQU 07H ; Bell character +TAB EQU 09H ; Tab character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character +ESC EQU 1BH ; Escape character + +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) +CPMDMA EQU 80H ; CP/M standard DMA buffer + + +; SLINK0 M-Rel linker module + EXTRN LINK ; get + PUBLIC @GBYTE ; make visible + +; From VLIB Get.. + EXTRN Z3VINIT, GXYMSG, VPRINT, EREOL, TINIT, DINIT, CLS, GOTOXY + +; From Z3LIB Get.. + EXTRN GETNAME, PRTNAME, ZFNAME, GZMTOP, WHRENV + +; From SYSLIB Get.. + EXTRN PUTUD, RETUD, SETDMA, INITFCB, BLINE, CRLF, CAPINE, CAPIN, PFN1, PFN3 + EXTRN F$EXIST, F$MOPEN, F$CLOSE, F$DELETE, F$OPEN, F$READ, F$RENAME, F$WRITE + EXTRN PADC, PHLFDC, PHL4HC, COUT, EVAL10, EVAL16, ISALNUM, CODEND + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +BPBUILD: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0 ; addr of Z3 environment + +START: LD HL,(CPMBDOS) ; ##### BUG: should rather be CPMBDOS+1 + CALL WHRENV ; find Z3 Environment Descriptor + LD (ENVADR),HL ; store ENV ptr locally + CALL Z3VINIT ; ..and init for VLIB/Z3LIB routines + CALL TINIT ; init terminal characteristics + CALL GETNAME ; get actual program name + CALL GETQFLG ; get quiet flag + AND A ; check if verbose mode + JR NZ,START0 ; ..if not, skip over (= quiet) + + CALL VPRINT + DEFB 1,'B/P System Build',2,' V',VER/10+'0','.',VER MOD 10 + '0',REV,' ' + DATE + DEFB ' ',CR,LF + DEFB 0 + +START0: CALL GZMTOP ; get top of memory (first byte _not_ to be used) + DEC HL ; -1 + EX DE,HL ; save temporarily + CALL CODEND ; get available page after code end (WSPC area) + EX DE,HL ; swap regs back + XOR A ; reset C-Flag + SBC HL,DE ; calc remaining TPA size + EX DE,HL ; use DE as counter + +CLRTPA: LD (HL),0 ; clear TPA memory + INC HL ; ..from end of program to top of memory + DEC DE + LD A,E + OR D ; counter = zero ? + JR NZ,CLRTPA ; ..loop till done + + LD (STACK),SP ; set local stackpointer + LD SP,STACK + CALL RETUD ; get current drive (B) and user (C) + LD (OLDDU),BC ; ..and store + + ; evaluate command line + LD A,(CPMFCB+1) ; get first char of command line (in FCB #1) + CP '/' ; is this a help request ? + JP Z,HELP ; ..if so, jump display help and exit + CP ' ' ; is file name blank ? + JR Z,INITRAM ; ..if so, jump to ask for manual input + + ; a file name was specified (= image file), attempt to read header + LD HL,CPMFCB+9 ; check file type + LD A,(HL) + CP ' ' ; is first char ? + JR NZ,RDFILE ; ..if not, skip over + EX DE,HL ; else, swap regs + LD HL,FTYPES+3 ; ptr to standard file type 'IMG' + LD BC,3 ; ..and copy 3 chars + LDIR +RDFILE: LD HL,CPMFCB+1 ; ptr to file name in standard FCB #1 + LD DE,IMGFN_I ; ptr to default file name for system image + LD BC,11 ; copy 11 chars from FCB to IMG Header area + LDIR + CALL CODEND ; get addr WSPC + CALL RDHDR ; read first page of IMG file + OR A ; check if successful + JR NZ,RDFILE0 ; ..if not, jump to display msg + CALL CODEND ; get addr WSPC + LD DE,IMGHD_I ; point to area for IMG file header + JR RDFILE1 ; ..and jump to continue +RDFILE0: CALL VPRINT + DEFB CR,LF,"+++ Can't Read...any key to continue w/defaults +++" + DEFB 0 + CALL CAPINE ; get input (any key) + CALL CODEND ; get addr WSPC + EX DE,HL ; swap regs + LD HL,IMGHD_I ; point to area for IMG file hdr + +RDFILE1: LD BC,0100H ; bytes to copy (1 page) + LDIR ; ..from hdr to WSPC (no file, or read error) + ; or from WSPC to hdr (file read successfully) + + ; initialize ram storage +INITRAM: LD HL,CCPFCB + XOR A ; nullify A + LD B,IMGFCB+36-CCPFCB ; B= 179 +INITRM0: LD (HL),A ; clear variables + INC HL ; with (180 bytes) + DJNZ INITRM0 + LD BC,11 ; bytes to copy + PUSH BC + LD HL,CFNAM_I ; copy ZCPR file name + LD DE,CCPFCB+1 + LDIR + POP BC ; restore # bytes + PUSH BC + LD HL,DFNAM_I ; copy ZSDOS file name + LD DE,DOSFCB+1 + LDIR + POP BC ; restore # bytes + PUSH BC + LD HL,BFNAM_I ; copy B/P Bios file name + LD DE,BIOSFCB+1 + LDIR + POP BC ; restore # bytes + LD HL,IMGFN_I ; copy IMG file name + LD DE,IMGFCB+1 + LDIR + + +;::::: MAIN MENU + +M0MAIN: CALL M0SHOW ; display menu + CALL MSELECT ; get user for input + CP ' ' ; is it ? + JP Z,MKSYS ; ..build new system + CP CR ; ? + JP Z,MKSYS ; ..build new system + CP ESC ; ? + JP Z,M$ABORT ; ..quit program + CP CTRLC ; ? + JP Z,M$ABORT ; ..quit program + CP '1' ; '1' ? + JR Z,M0GOM1 ; ..go to Files menu + CP '2' ; '2' ? + JP Z,M0GOM2 ; ..go to Bios config menu + CP '3' ; '3' ? + JP Z,M0GOM3 ; ..go to Environment menu + JR M0MAIN + +M0GOM1: CALL M1FILE + JR M0MAIN + +M0GOM2: CALL M2BIOS + JR M0MAIN + +M0GOM3: CALL M3ENV + JR M0MAIN + + +;::::: MAKE (build) NEW SYSTEM + +MKSYS: CALL CLS + CALL VPRINT + DEFB CR,LF,'..building system..',CR,LF,LF + DEFB 0 + + + ;----- Pre-run to determine addr/size of linked system segments + + ; determine CPR size/addr + LD HL,0 + LD (COMTB6),HL ; clear org B2RAM Common + LD (COMTB5),HL ; clear org BANK2 Common + LD DE,CCPFCB + LD HL,COMTBL + CALL LNKDSZ ; determine CCP segment sizes + LD (CCNBSZ),HL ; store CCP CSEG Non-banked size + ADD HL,BC ; add DSEG size + CALL ALIGN ; ..align to next sector boundary + LD (CNBSZ_I),HL ; ..and store CCP Non-banked total size + LD HL,(COMTB6) ; get B2RAM Common + LD (CDBKSZ),HL ; ..and store CCP DSEG Banked size + EX DE,HL + LD HL,(COMTB5) ; get BANK2 Common + LD (CCBKSZ),HL ; ..and store CCP CSEG Banked size + ADD HL,DE ; add values + CALL ALIGN ; ..align to next sector boundary + LD (CBKSZ_I),HL ; ..and store as CCP Banked total size + CALL PB2ADR ; display addr's + + ; determine DOS size/addr + LD DE,DOSFCB + LD HL,COMTBL + CALL LNKDSZ ; determine DOS segment sizes + LD (DCNBSZ),HL ; store DOS CSEG Non-banked size + ADD HL,BC ; add DSEG size + CALL ALIGN ; ..align to next sector boundary + LD (DNBSZ_I),HL ; ..and store DOS Non-banked total size + LD HL,(COMTB6) ; get B2RAM Common + LD (DDBKSZ),HL ; ..and store DOS DSEG Banked size + EX DE,HL + LD HL,(COMTB5) ; get BANK2 Common + LD (DCBKSZ),HL ; ..and store DOS CSEG Banked size + ADD HL,DE ; add values + CALL ALIGN ; ..align to next sector boundary + LD (DBKSZ_I),HL ; ..and store as DOS Banked total size + CALL PB2ADR ; display addr's + + ; determine B/P BIOS size/addr + LD DE,BIOSFCB + LD HL,COMTBL + CALL LNKDSZ ; determine BIOS segment sizes + LD (BCNBSZ),HL ; store BIOS CSEG Non-banked size + ADD HL,BC ; add DSEG size + CALL ALIGN ; ..align to next sector boundary + LD (BNBSZ_I),HL ; ..and store BIOS Non-banked total size + LD HL,(COMTB6) ; get B2RAM Common + LD (BDBKSZ),HL ; ..and store BIOS DSEG Banked size + EX DE,HL + LD HL,(COMTB5) ; get BANK2 Common + LD (BCBKSZ),HL ; ..and store BIOS CSEG Banked size + ADD HL,DE ; add values + LD (BBKSZ_I),HL ; ..and store as BIOS Banked total size + CALL PB2ADR ; display addr's + LD HL,(COMTB7) ; get org RESVD Common + LD (BRSVDO),HL ; ..and store it + + + ;----- Auto-size system segments + +AUTOSZ: LD HL,(Z3ENV_I+63) ; get start addr CCP from ENV + LD (CNBADR),HL + LD HL,(Z3ENV_I+66) ; " DOS from ENV + LD (DNBADR),HL + LD HL,(Z3ENV_I+69) ; " BIOS from ENV + LD (BNBADR),HL + + CALL VPRINT + DEFB CR,LF,'Auto-size system ([Y]/N)? : ' + DEFB 0 + CALL CAPIN ; get user input (capitalized) + CALL EXITRQ ; quit program ? + CALL YESNO ; get (Y)es/no input + CP 'N' ; entered 'N' ? + LD A,0FFH ; prepare indicator byte for 'Yes' + JR NZ,PRELINK ; ..if not 'N', skip over + XOR A ; else, clear A (indicator byte for 'No') + + + ;----- Prelink BIOS + +PRELINK: LD (AUTOSIZ),A ; ..and store indicator + CALL VPRINT + DEFB CR,LF,'-- Pre-linking Bios for Info --' + DEFB 0 + LD HL,(Z3ENV_I+27) ; get addr Env Descriptor + LD (COMTB1),HL ; ..and store in org _ENV_ Common + LD HL,0 + LD (COMTB0),HL ; set org _BIOS_ Common to zero + LD HL,(COMTB5) ; get BIOS BANK2 Common (= Banked CSEG size) + LD DE,(DBKSZ_I) ; DOS Banked size + ADD HL,DE ; add values + LD (COMTB5),HL ; ..and store as org BANK2 Common + ; (BIOS Banked CSEG addr) + LD DE,(BCBKSZ) ; BIOS Banked CSEG size + ADD HL,DE ; add values + LD (COMTB6),HL ; ..and store as org B2RAM Common + ; (BIOS Banked DSEG addr) + + ; prepare alt. registers for linking + ; BC'= offset to add to CSEG, DE'= offset to add to DSEG + ; ( HL'= dest. addr bitmap -- not used ) + EXX + LD BC,(BNBAD_I) ; BIOS Non-banked addr + LD HL,(BCNBSZ) ; BIOS Non-banked CSEG size + ADD HL,BC ; calc Non-banked DSEG start + EX DE,HL ; ..keep in DE + EXX + + CALL CODEND ; get addr WSPC + LD DE,0100H ; move beyond header (1 page) + ADD HL,DE + LD B,H + LD C,L ; ..store addr in BC + LD (LPHYADR),HL ; ..and in local var for link module + LD HL,(BNBSZ_I) ; get BIOS Non-banked size + ADD HL,BC ; calc BIOS phys. load location CSEG + LD (COMTB5+2),HL ; (in BANK2 Common) + LD DE,(BCBKSZ) ; get BIOS Banked CSEG addr + ADD HL,DE ; calc BIOS phys. load location DSEG + LD (COMTB6+2),HL ; (in B2RAM Common) + LD HL,(BCNBSZ) ; get BIOS Non-Banked CSEG size + ADD HL,BC ; add to dest. addr + LD DE,BIOSFCB ; ptr to BIOS FCB + + ; link file with BC= phys. addr CSEG, HL= phys. addr DSEG, DE= addr FCB + CALL LNKFILE + + LD HL,(LPHYADR) ; get dest. addr (start of linked file) + LD DE,128 ; offset to OPTF1 (option flag) + ADD HL,DE ; in B/P Bios config area + LD A,(HL) ; get byte + LD (OPTF1),A ; store it + AND 00001000B ; mask bit 3 (ALV/CSV in TPA, or in bank) + LD (BNKDSYS),A ; store indicator + JR NZ,PRELNK0 ; ..if bit 3= 1 (in bank), skip over + CALL VPRINT ; else, display 'Non-Banked' + DEFB '(Non-Banked)' + DEFB 0 + JR CALCSIZ + +PRELNK0: CALL VPRINT + DEFB '(Banked)' + DEFB 0 + + + ;----- Calculate addr/size of System Segments + +CALCSIZ: LD HL,(BNBSZ_I) ; get BIOS Non-banked size + LD DE,(BBKSZ_I) ; ..and Banked size + ADD HL,DE ; calc total size + LD C,L ; move in BC + LD B,H + LD HL,(LPHYADR) ; dest. addr + LD E,L ; in DE + LD D,H + INC DE ; move ptr fwd + LD (HL),0 ; ..and clear memory + LDIR + LD A,(AUTOSIZ) ; get indicator for auto-sizing + OR A ; check if zero (= no) + PUSH AF + CALL NZ,CALCASZ ; ..if auto-sizing, calc base addr's + ; of Non-banked system segments + + POP AF + JR Z,STNDSZ ; ..if no auto-sizing, jump to continue + LD HL,(CNBADR) ; CCP Non-banked start addr + LD (Z3ENV_I+63),HL ; write to ENV + EX DE,HL + LD HL,(DNBADR) ; start addr DOS + LD (Z3ENV_I+66),HL ; write to ENV + XOR A + SBC HL,DE ; calc CCP size (in bytes) + ADD HL,HL ; and convert to 128-byte records + LD A,H + LD (Z3ENV_I+65),A ; write # records to ENV + LD HL,(BNBADR) ; BIOS Non-banked start addr + LD (Z3ENV_I+69),HL ; write to ENV + LD DE,(Z3ENV_I+66) ; get start addr DOS + XOR A + SBC HL,DE ; calc DOS size (in bytes) + ADD HL,HL ; and convert to 128-byte records + LD A,H + LD (Z3ENV_I+68),A ; write # records to ENV + JR SIZDONE ; then, jump to continue + + + ; Use Standard Sizes ? +STNDSZ: CALL VPRINT + DEFB CR,LF,'Set to "Standard" if possible? (Y/[N]) : ' + DEFB 0 + CALL CAPIN ; get user input + CALL EXITRQ ; quit program ? + CALL NOYES ; get yes/(N)o input + CP 'Y' ; is it 'Y' ? + CALL Z,CALCSSZ ; ..if so, set standard sizes for segments + + + ;----- Sizing done - addr/size of Non-banked System Segments determined + +SIZDONE: CALL PSYSNB ; display base addr's of system (Non-banked) + + ; transfer base addr's from ENV to IMG hdr + LD DE,(Z3ENV_I+69) ; base addr BIOS from ENV + LD (BNBAD_I),DE ; to IMG hdr + LD DE,(Z3ENV_I+66) ; base addr DOS from ENV + LD (DNBAD_I),DE + LD DE,(Z3ENV_I+63) ; base addr CCP from ENV + LD (CNBAD_I),DE + LD A,(OPTF1) ; get OPTF1 flag from linked BIOS + AND 00000001B ; mask bit 0 (0= unbanked, 1= banked Bios) + JR Z,ENV2COM + BIT 7,D ; check CCP base addr >32k + JP NZ,ENV2COM ; start addr of CCP in banked system must be above 32k + CALL VPRINT + DEFB CR,LF,BEL,'+++ CPR Starting Addr Too Low (<8000H) +++',CR,LF + DEFB 0 + JP AUTOSZ ; loop, ask for auto-sizing + + + ; Transfer addr's from Z3ENV to COMMON table (logical 'ORG') +ENV2COM: LD HL,(Z3ENV_I+27) ; addr Z3ENV (env. descriptor) + LD (COMTB1),HL ; org _ENV_ Common + LD HL,(Z3ENV_I+69) ; addr BIOS (start NZBIO) + LD (COMTB0),HL ; org _BIOS_ Common + LD HL,(Z3ENV_I+34) ; addr Z3MSG (msg buffer) + LD (COMTB2),HL ; org _MSG_ Common + LD HL,(Z3ENV_I+36) ; addr EXTFCB (external FCB) + LD (COMTB3),HL ; org _FCB_ Common + LD HL,(Z3ENV_I+24) ; addr Z3CL (cmd line buffer) + LD (COMTB4),HL ; org _MCL_ Common + LD HL,(Z3ENV_I+30) ; addr SHSTK (shell stack) + LD (COMTB8),HL ; org _SSTK_ Common + LD HL,(Z3ENV_I+38) ; addr EXTSTK (external stack) + LD (COMTB9),HL ; org _XSTK_ Common + + ; ##### CHECK: top of mem not used (HL immediately overwritten) + CALL GZMTOP + + ; init phys. load location addr's in COMMON table + LD HL,0080H + LD (COMTB0+2),HL + LD (COMTB1+2),HL + LD (COMTB2+2),HL + LD (COMTB3+2),HL + LD (COMTB4+2),HL + LD (COMTB7+2),HL + LD (COMTB8+2),HL + LD (COMTB9+2),HL + + + ;----- Link files + + ; link CCP + LD HL,(CNBSZ_I) ; CCP Non-banked total size + ; (make room for Non-banked CCP to.. + ; ..copy from SYS Bank to TPA Bank) + INC H ; +100H + LD (COMTB5),HL ; store as CCP Banked CSEG start (org BANK2 Common) + LD (CBKAD_I),HL ; ..and as CCP Banked base addr + EX DE,HL + LD HL,(CCBKSZ) ; CCP Banked CSEG addr + ADD HL,DE ; add to Banked base addr + LD (COMTB6),HL ; ..store as CCP Banked DSEG start (org B2RAM Common) + + ; ##### CHECK: obsolete? contents of HL and DE overwritten after EXX/EXX anyway + LD HL,(CBKSZ_I) ; CCP Banked total size + ADD HL,DE + + ; prepare alt. registers for linking + ; BC'= offset to add to CSEG, DE'= offset to add to DSEG + ; ( HL'= dest. addr bitmap -- not used ) + EXX + LD BC,(CNBAD_I) ; CCP Non-banked base addr + LD HL,(CCNBSZ) ; CCP Non-banked CSEG size + ADD HL,BC ; add (= DSEG start) + EX DE,HL ; swap into DE + EXX + + CALL CODEND ; get addr WSPC + LD DE,0100H ; move beyond header (1 page) + ADD HL,DE ; add (= destination) + LD C,L + LD B,H ; copy addr in BC + LD (LPHYADR),HL ; ..and store in var for link module + LD HL,(CNBSZ_I) ; CCP Non-banked total size + ADD HL,BC ; add to dest location + LD (COMTB5+2),HL ; ..set CCP Banked CSEG phys. load location + ; (in BANK2 Common) + LD DE,(CCBKSZ) ; CCP Banked CSEG addr + ADD HL,DE ; add to dest + LD (COMTB6+2),HL ; ..set CCP Banked DSEG phys. load location + ; (in B2RAM Common) + LD HL,COMTBL ; addr of COMMON's table + LD (LTBLADR),HL ; store in var for linker + LD HL,(CCNBSZ) ; CSEG size CCP unbanked + ADD HL,BC ; add (= dest DSEG) + LD DE,CCPFCB + + ; link file with BC= phys. addr CSEG, HL= phys. addr DSEG, DE= addr FCB + CALL LNKFILE + + ; link DOS + LD HL,(COMTB5) ; get org BANK2 Common (= CCP Banked base addr) + LD DE,(CBKSZ_I) ; CCP Banked total size + ADD HL,DE ; add + LD (COMTB5),HL ; ..store as DOS Banked CSEG addr (org BANK2 Common) + LD (DBKAD_I),HL ; ..and as DOS Banked base addr + LD DE,(DCBKSZ) ; DOS Banked CSEG size + ADD HL,DE ; add to base addr + LD (COMTB6),HL ; ..store as DOS Banked DSEG addr (org B2RAM Common) + + ; prepare alt. registers for linking + EXX + LD BC,(DNBAD_I) ; DOS Non-banked base addr + LD HL,(DCNBSZ) ; DOS Non-banked CSEG size + ADD HL,BC ; add (= DSEG start) + EX DE,HL ; swap into DE + EXX + + LD BC,(LPHYADR) ; destination addr (WSPC + 0x100) + LD HL,(CNBSZ_I) ; CCP Non-banked total size + ADD HL,BC + LD DE,(CBKSZ_I) ; CCP Banked total size + ADD HL,DE + LD C,L + LD B,H ; new dest. addr in BC + LD (LPHYADR),HL ; ..and update var for link module + + ; ##### CHECK: already done when linking CCP - obsolete ? + LD HL,COMTBL ; addr of COMMON's table + LD (LTBLADR),HL ; store in var for linker + ; ###### + + LD HL,(DNBSZ_I) ; DOS Non-banked total size + ADD HL,BC ; add to dest location + LD (COMTB5+2),HL ; ..set DOS Banked CSEG phys. load location + ; (in BANK2 Common) + LD DE,(DCBKSZ) ; DOS Banked CSEG size + ADD HL,DE ; add to dest + LD (COMTB6+2),HL ; ..set DOS Banked DSEG phys. load location + ; (in B2RAM Common) + LD HL,(DCNBSZ) ; DOS Non-banked CSEG size + ADD HL,BC ; add (= dest DSEG) + LD DE,DOSFCB + + ; link file with BC= phys. addr CSEG, HL= phys. addr DSEG, DE= addr FCB + CALL LNKFILE + + ; link BIOS + LD HL,(COMTB5) ; get org BANK2 Common (= DOS Banked base addr) + LD DE,(DBKSZ_I) ; DOS Banked total size + ADD HL,DE ; add + LD (COMTB5),HL ; ..store as BIOS Banked CSEG addr (org BANK2 Common) + LD (BBKAD_I),HL ; ..and as BIOS Banked base addr + LD DE,(BCBKSZ) ; BIOS Banked CSEG size + ADD HL,DE ; add to base addr + LD (COMTB6),HL ; ..store as BIOS Banked DSEG addr (org B2RAM Common) + + ; prepare alt. registers for linking + EXX + LD BC,(BNBAD_I) ; BIOS Non-banked base addr + LD HL,(BCNBSZ) ; BIOS Non-banked CSEG size + ADD HL,BC ; add (= DSEG start) + EX DE,HL ; swap into DE + EXX + + LD BC,(LPHYADR) ; destination addr (begin DOS) + LD HL,(DNBSZ_I) ; DOS Non-banked total size + ADD HL,BC + LD DE,(DBKSZ_I) ; DOS Banked total size + ADD HL,DE + LD C,L + LD B,H ; new dest. addr in BC + LD (LPHYADR),HL ; ..and update var for link module + LD HL,(BNBSZ_I) ; BIOS Non-banked total size + ADD HL,BC ; add to dest location + LD (COMTB5+2),HL ; ..set BIOS Banked CSEG phys. load location + ; (in BANK2 Common) + LD DE,(BCBKSZ) ; BIOS Banked CSEG size + ADD HL,DE ; add to dest + LD (COMTB6+2),HL ; ..set BIOS Banked DSEG phys. load location + ; (in B2RAM Common) + LD DE,(BDBKSZ) ; BIOS Banked DSEG size + ADD HL,DE ; add (= end addr in WSPC) + LD (SYSEADR),HL ; ..and store in var + LD HL,(BCNBSZ) ; BIOS Non-Banked CSEG size + ADD HL,BC ; add (= dest DSEG) + LD DE,BIOSFCB + + ; link file with BC= phys. addr CSEG, HL= phys. addr DSEG, DE= addr FCB + CALL LNKFILE + + ;----- Link finished + + LD DE,(SYSEADR) ; end addr of linked system in WSPC + CALL CODEND ; addr start of WSPC + EX DE,HL + XOR A + SBC HL,DE ; calc length in bytes + CALL ALIGN ; ..and align to next sector boundary + + ; divide by 8 (dump lower bits 6..0) + LD A,L ; move low byte to A + LD L,H ; move high byte to L + LD H,0 ; and dump high byte + RLC A ; rotate MSB to C-Flag + ADC HL,HL ; double HL plus C-Flag + LD (SYSBLKS),HL ; ..store system length (in blocks) in var + PUSH HL + CALL UPDINFO ; update 'k Bios' info + POP HL + + CALL VPRINT + DEFB CR,LF,' Total ' + DEFB 0 + LD DE,IMGFCB+1 ; ptr to IMG file name + CALL PFN3 ; ..display it + CALL VPRINT + DEFB ' size = ' + DEFB 0 + CALL PHL4HC + CALL VPRINT + DEFB 'H sectors',CR,LF + DEFB 0 + + + ;----- Update Z3ENV <---> B/P Bios (vice versa) + + LD DE,(LPHYADR) ; get last dest. addr (BIOS) + LD HL,152 ; offset to Env. Descriptor (CONFIG+26) + ADD HL,DE ; move ptr fwd + LD BC,(Z3ENV_I+27) ; addr Z3ENV (env. descriptor) + LD (HL),C ; ..store actual addr Z3ENV + INC HL + LD (HL),B + LD BC,4 + ADD HL,BC ; move ptr to CPU Clock Rate (CONFIG+31) + LD A,(HL) ; get value + LD (Z3ENV_I+43),A ; ..and store in ENV + LD HL,67 ; offset to BIOS fn #22 (get addr DRVTBL) + ADD HL,DE ; move ptr forward + LD A,(HL) + INC HL + LD H,(HL) ; get addr of fn call in HL + LD L,A + LD BC,(BNBAD_I) ; BIOS Non-banked base addr in BC + OR A + SBC HL,BC ; ..calc difference + ADD HL,DE ; ..set ptr to start of fn in WSPC memory + INC HL ; move ptr beyond opcode 0x21 (LD HL,nnnn) + LD A,(HL) + INC HL + LD H,(HL) ; addr of drive table in HL + LD L,A + OR A + SBC HL,BC ; calc diff to BIOS base addr + ADD HL,DE ; ..and set ptr to location in WSPC memory + LD B,16 ; counter (16 drives, A..P) + LD DE,0 + DEC HL ; prior to loop, set ptr back + + ; create bit mask for drive vector +MKDRVEC: INC HL + LD A,(HL) ; check if high byte + INC HL + OR (HL) ; .and low byte are zero + JR Z,MKDRVE0 ; ..if so, skip drive + SCF ; else, set C-Flag for existing byte +MKDRVE0: RR D ; and rotate bit into position + RR E + DJNZ MKDRVEC ; loop till done + LD (Z3ENV_I+52),DE ; set DRVEC (drive vector) + LD HL,(UNBAD_I) + LD (Z3ENV_I+60),HL ; set USRSP addr (resident user space) + LD A,(UNBSZ_I) + LD (Z3ENV_I+59),A ; set remaining user space + LD (Z3ENV_I+62),A ; ..and size of user space + + + ;----- Write IMG file to disk + + ; copy IMG header to workspace (0x100 bytes before linked new system) + CALL CODEND ; get addr WSPC + EX DE,HL ; dest in DE + LD HL,IMGHD_I ; src addr (IMG hdr) in HL + LD BC,0100H ; bytes to copy + LDIR + + ; save file + LD BC,(SYSBLKS) ; # of sectors to write + CALL CODEND ; addr WSPC + CALL WRFILE ; write IMG file + JP NC,EXIT ; ..if ok, jump and exit program + CALL VPRINT + DEFB CR,LF,'..Error Writing output file..',BEL,CR,LF + DEFB 0 + JP EXIT + + +;::::: SUPPORT FUNCTIONS + + ; check if user requested to abort program ( or entered) + ; in: A= char +EXITRQ: CP ESC ; is it ? + JR Z,EXITRQ0 ; ..if so, jump forward and abort + CP CTRLC ; ? + RET NZ ; ..if not, return + ; else, fall through and abort +EXITRQ0: CALL CRLF + +M$ABORT: CALL VPRINT + DEFB ' ...aborting...',CR,LF + DEFB 0 + JP EXIT + + +;::::: HELP SCREEN + +HELP: CALL VPRINT + DEFB CR,LF,1 + DEFB 0 + CALL PRGNAME + CALL VPRINT + DEFB 2,' builds banked and non-banked parts of a B/P Bios.',CR,LF + DEFB ' It operates with layered Menus and supports tailoring of defaults.',CR,LF + DEFB ' Starting locations of BIOS, DOS and CPR may be automatically computed',CR,LF + DEFB ' or Specified. If ZSDOS2 is the selected Dos, Bit Allocation buffers',CR,LF + DEFB ' for Hard Drives are located in the System Bank.',CR,LF,LF + DEFB 'Syntax:',CR,LF,' ' + DEFB 0 + CALL PRGNAME + CALL VPRINT + DEFB ' - Generate system w/defaults',CR,LF,' ' + DEFB 0 + CALL PRGNAME + CALL VPRINT + DEFB ' fn[.ft] - Make/Modify a specific system',CR,LF + DEFB ' (Default type is .IMG)',CR,LF + DEFB ' ' + DEFB 0 + CALL PRGNAME + CALL VPRINT + DEFB ' // - Display this Message',CR,LF + DEFB 0 + + +;::::: EXIT PROGRAM + +EXIT: LD SP,(STACK) ; restore stackpointer + CALL DINIT ; de-init terminal characteristics + LD BC,(OLDDU) + CALL PUTUD ; log initial Drive/User + RET + + + ; display main menu +M0SHOW: CALL CLS + CALL VPRINT + DEFB CR,LF,1,' Main ',2,CR,LF,CR,LF,LF + DEFB TAB,1,' 1 ',2,' File Names',CR,LF,LF + DEFB TAB,1,' 2 ',2,' BIOS Configuration',CR,LF,LF + DEFB TAB,1,' 3 ',2,' Environment' + DEFB 0 + RET + + +;::::: MENU 1 - FILES + +M1FILE: CALL CLS + CALL VPRINT + DEFB CR,LF,1,' Files (1.1) ',2,CR,LF,CR,LF,LF + DEFB TAB,1,' 1 ',2,' Command Processor File : ' + DEFB 0 + LD DE,CCPFCB+1 ; ptr file name in CCP FCB + CALL PFN1 ; ..display file name + type + CALL VPRINT + DEFB CR,LF,LF,TAB,1,' 2 ',2,' Operating System File : ' + DEFB 0 + LD DE,DOSFCB+1 ; ptr file name in DOS FCB + CALL PFN1 + CALL VPRINT + DEFB CR,LF,LF,TAB,1,' 3 ',2,' B/P Bios Source File : ' + DEFB 0 + LD DE,BIOSFCB+1 ; ptr file name in BIOS FCB + CALL PFN1 + CALL VPRINT + DEFB CR,LF,LF,TAB,1,' 4 ',2,' B/P Executable Image : ' + DEFB 0 + LD DE,IMGFCB+1 ; ptr file name in IMG FCB + CALL PFN1 + + CALL MSELECT ; get user input + CP ' ' ; is it ? + RET Z ; ..return + CP CR ; ? + RET Z ; ..return + CP ESC ; ? + JP Z,M$ABORT ; ..quit program + CP CTRLC ; ? + JP Z,M$ABORT ; ..quit program + CP '4'+1 ; is it above '4' ? + JP NC,M1FILE ; ..if so, display Files menu again + ; else, fall through + LD DE,CCPFCB + LD HL,CFNAM_I ; ZCPR FCB+name ptr's + CP '1' ; option '1' ? + JR Z,M1FNAME ; ..if so, jump to continue + LD DE,DOSFCB + LD HL,DFNAM_I ; ZSDOS FCB+name ptr's + CP '2' ; option '2' ? + JR Z,M1FNAME ; ..if so, jump to continue + LD DE,BIOSFCB + LD HL,BFNAM_I ; B/P Bios FCB+name ptr's + CP '3' ; option '3' ? + JR Z,M1FNAME ; ..if so, jump to continue + LD DE,IMGFCB ; else, set IMG FCB+name ptr's + LD HL,IMGFN_I ; ..and fall through + + ; enter file name +M1FNAME: LD (MSELOPT),A ; store selected option + PUSH HL ; save HL regs + CALL VPRINT + DEFB CR,LF,TAB,TAB,' FileName[.Typ] : ' + DEFB 0 + CALL CINPUTL ; get user input (line editor) + PUSH DE + LD DE,CPMFCB ; ptr to standard FCB #1 + CALL INITFCB ; init FCB + CALL ZFNAME ; ..and parse user input as fn/ft into FCB + POP DE ; restore regs + POP HL + OR A ; check if file name is unambiguous + JR Z,M1FCB ; ..if so, jump to continue + + ; error, file name invalid +M1FNERR: LD A,BEL ; else, send to CON: + CALL COUT + JP M1FILE ; ..and loop, ask for new input + + ; file name ok, init FCB +M1FCB: LD A,(CPMFCB+1) ; check first char of file name + CP ' ' ; is it ? + JR Z,M1FNERR ; ..if so, file name is invalid + ; jump, alert and ask for new input + PUSH HL ; save regs + LD A,(CPMFCB+9) ; get first char of file type + CP ' ' ; is it ? + JR NZ,M1FCB1 ; ..if not, jump to continue + LD A,(MSELOPT) ; get selected menu option (to set file type) + PUSH DE + LD DE,CPMFCB+9 + LD BC,3 ; bytes to copy + LD HL,FTYPES+3 ; prepare ptr for .IMG file type + CP '4' ; was option '4' (image file) selected ? + JR Z,M1FCB0 ; ..if so, jump to continue + LD HL,FTYPES+6 ; prepare ptr for .REL file type + CP '3' ; was option '3' (B/P Bios file) selected ? + JR Z,M1FCB0 ; ..if so, jump to continue + LD HL,FTYPES+9 ; else, set ptr to .ZRL file type + +M1FCB0: LDIR ; ..and copy + POP DE ; DE= ptr to respective FCB in temp area + ; (Stack)= ptr to file name in IMG file header area +M1FCB1: LD HL,CPMFCB ; ptr to standard FCB #1 + LD BC,15 ; copy 15 bytes to FCB in temp area + LDIR + POP DE + LD HL,CPMFCB+1 ; ptr to file name in standard FCB #1 + LD BC,11 ; copy 11 bytes (fn.ft) to IMG file hdr + LDIR + JP M1FILE ; ..and loop + + +;::::: MENU 2 - BIOS CONFIG + +M2BIOS: CALL CLS + CALL VPRINT + DEFB 1,' Environment (2.1) ',2 + DEFB 0 + CALL GXYMSG ; display w/ positioning + DEFB 3,3,'COMMON (Bank 0) MEMORY BANK 2 MEMORY' + DEFB 0 + CALL GXYMSG + DEFB 4,2,'---------------------- ------------------------' + DEFB 0 + CALL GXYMSG ; col 2 (on the left) + DEFB 5,2,1,' A ',2,' Common BIOS - ' + DEFB 0 + CALL GXYMSG + DEFB 6,2,' Size - ' + DEFB 0 + CALL GXYMSG + DEFB 7,2,1,' B ',2,' Common BDOS - ' + DEFB 0 + CALL GXYMSG + DEFB 8,2,' Size - ' + DEFB 0 + CALL GXYMSG + DEFB 9,2,1,' C ',2,' Command Proc - ' + DEFB 0 + CALL GXYMSG + DEFB 10,2,' Size - ' + DEFB 0 + CALL GXYMSG + DEFB 11,2,1,' D ',2,' User Space - ' + DEFB 0 + CALL GXYMSG + DEFB 12,2,' Size - ' + DEFB 0 + CALL GXYMSG ; col 34 (on the right) + DEFB 5,34,1,' E ',2,' Banked BIOS - ' + DEFB 0 + CALL GXYMSG + DEFB 6,34,' Size - ' + DEFB 0 + CALL GXYMSG + DEFB 7,34,1,' F ',2,' Banked BDOS - ' + DEFB 0 + CALL GXYMSG + DEFB 8,34,' Size - ' + DEFB 0 + CALL GXYMSG + DEFB 9,34,1,' G ',2,' Command Proc - ' + DEFB 0 + CALL GXYMSG + DEFB 10,34,' Size - ' + DEFB 0 + CALL GXYMSG + DEFB 11,34,1,' H ',2,' User Space - ' + DEFB 0 + CALL GXYMSG + DEFB 12,34,' Size - ' + DEFB 0 + + ; display BIOS addr and size + LD HL,0516H ; row 5 / col 22 + CALL GOTOXY ; position cursor + LD HL,(Z3ENV_I+69) ; ptr to start addr BIOS in ENV + CALL PHLXH ; display as hex + 'H' + EX DE,HL ; keep value + LD HL,0616H ; row 6 / col 22 + CALL GOTOXY + PUSH DE + CALL ENVLOW ; lowest addr of ENV component in HL + POP DE + LD BC,(UNBAD_I) ; get addr User Space in IMG hdr + LD A,B ; check if invalid (= zero) + OR C + CALL NZ,MINHLBC ; ..if not, get the lower of both addr's in HL + OR A + SBC HL,DE ; calc size [lowest ENV] - [start addr BIOS] + ADD HL,HL ; *2 + LD A,L ; check for page boundary + OR A ; (low byte = zero) + JR Z,M2ADRSZ ; ..if so, skip over + INC H ; else, increase before displaying + + ; display addr and size of other system segments +M2ADRSZ: LD A,H + CALL PSPCAD ; display + value as dec (size high byte) + LD HL,0716H ; row 7 / col 22 + LD DE,Z3ENV_I+66 ; ptr start addr DOS in Z3ENV + CALL PSEGXY ; print Segment addr/size at coordinates + LD HL,0916H ; row 9 / col 22 + LD DE,Z3ENV_I+63 ; ..start addr ZCPR in Z3ENV + CALL PSEGXY + LD HL,0B16H ; row 11 / col 22 + LD DE,UNBAD_I ; ..addr User Space in IMG hdr + CALL PSEGXY + LD HL,0536H ; row 5 / col 54 + LD DE,BBKAD_I ; ..base addr BIOS Banked in IMG hdr + CALL PSEGXY + LD HL,0736H ; row 7 / col 54 + LD DE,DBKAD_I ; ..base addr DOS Banked in IMG hdr + CALL PSEGXY + LD HL,0936H ; row 9 / col 54 + LD DE,CBKAD_I ; ..base addr ZCPR Banked in IMG hdr + CALL PSEGXY + LD HL,0B36H ; row 11 / col 54 + LD DE,UBKAD_I ; ..addr User Space Banked (RESVD ??) in IMG hdr + CALL PSEGXY + + ; select option from Menu 2 Bios Config +M2SELCT: CALL MSELECT ; get user input + CP ' ' ; is it ? + RET Z ; ..return + CP CR ; ? + RET Z ; ..return + CP ESC ; ? + JP Z,M$ABORT ; ..quit program + CP CTRLC ; ? + JP Z,M$ABORT ; ..quit program + + LD HL,Z3ENV_I+69 + CP 'A' ; 'A' (Common Bios) ? + JR Z,M2EXEC + LD HL,Z3ENV_I+66 + CP 'B' ; 'B' (Common BDOS) ? + JR Z,M2EXEC + LD HL,Z3ENV_I+63 + CP 'C' ; 'C' (Common ZCPR) ? + JR Z,M2EXEC + LD HL,UNBAD_I + CP 'D' ; 'D' (Common User Space) ? + JR Z,M2EXEC + LD HL,BBKAD_I + CP 'E' ; 'E' (Banked Bios) ? + JR Z,M2EXEC + LD HL,DBKAD_I + CP 'F' ; 'F' (Banked BDOS) ? + JR Z,M2EXEC + LD HL,CBKAD_I + CP 'G' ; 'G' (Banked ZCPR) ? + JR Z,M2EXEC + LD HL,UBKAD_I + CP 'H' ; 'H' (Banked User Space) ? + + JR NZ,M2SELCT + +M2EXEC: CALL PHLXSIZ ; execute selected option (display addr and size, + ; ask for new values, convert) + JP M2BIOS ; ..then loop, display again + + +;::::: SUPPORT FUNCTIONS (Menu 2 - Bios Config) + + ; return the lower of HL and BC ("min" function) + ; in: BC, HL = values to compare + ; out: HL= the lower of both values +MINHLBC: LD A,H ; test high byte first + SUB B + RET C ; if borrowed from C-Flag, return (HL < BC) + JR NZ,MINHLB0 ; if delta <> zero, jump (HL > BC) + LD A,L ; ..else, test low byte too + SUB C + RET C ; if borrowed from C-Flag, return (BC > HL) +MINHLB0: LD L,C ; ..else, copy contents of BC into HL + LD H,B + RET + + +;::::: MENU 3 - ENVIRONMENT + +M3ENV: CALL CLS + CALL VPRINT + DEFB 1,' Environment (3.1) ',2 + DEFB 0 + CALL GXYMSG + DEFB 3,2,1,' A ',2,' - Environment - ' + DEFB 0 + CALL GXYMSG + DEFB 4,2,' Size (# recs)- ' + DEFB 0 + CALL GXYMSG + DEFB 5,2,1,' B ',2,' - Flow Ctrl Pkg - ' + DEFB 0 + CALL GXYMSG + DEFB 6,2,' Size (# recs)- ' + DEFB 0 + CALL GXYMSG + DEFB 7,2,1,' C ',2,' - I/O Package - ' + DEFB 0 + CALL GXYMSG + DEFB 8,2,' Size (# recs)- ' + DEFB 0 + CALL GXYMSG + DEFB 9,2,1,' D ',2,' - Res Cmd Proc - ' + DEFB 0 + CALL GXYMSG + DEFB 10,2,' Size (# recs)- ' + DEFB 0 + CALL GXYMSG + DEFB 11,2,1,' E ',2,' - Command Line - ' + DEFB 0 + CALL GXYMSG + DEFB 12,2,' Size (bytes) - ' + DEFB 0 + CALL GXYMSG + DEFB 3,34,1,' F ',2,' - Named Dirs - ' + DEFB 0 + CALL GXYMSG + DEFB 4,34,' # of Entries - ' + DEFB 0 + CALL GXYMSG + DEFB 5,34,1,' G ',2,' - External Path - ' + DEFB 0 + CALL GXYMSG + DEFB 6,34,' # of Entries - ' + DEFB 0 + CALL GXYMSG + DEFB 7,34,1,' H ',2,' - Shell Stack - ' + DEFB 0 + CALL GXYMSG + DEFB 8,34,' # of Entries - ' + DEFB 0 + CALL GXYMSG + DEFB 9,34,' Entry Size - ' + DEFB 0 + CALL GXYMSG + DEFB 10,34,1,' I ',2,' - Msg Buffer - ' + DEFB 0 + CALL GXYMSG + DEFB 11,34,1,' J ',2,' - Ext. FCB - ' + DEFB 0 + CALL GXYMSG + DEFB 12,34,1,' K ',2,' - Ext. Stack - ' + DEFB 0 + + ; display addr and size of ENV components + ; stored as (16-bit) (8-bit) + LD HL,0318H ; row 3 / col 24 + LD DE,Z3ENV_I+27 ; ptr addr Z3ENV (ZCPR3 Environment Descriptor) + CALL PSEGXY ; print Segement addr/size at coordinates + LD HL,0518H ; row 5 / col 24 + LD DE,Z3ENV_I+18 ; ptr addr FCP (Flow Cmd Pkg) + CALL PSEGXY + LD HL,0718H ; row 7 / col 24 + LD DE,Z3ENV_I+15 ; ptr addr IOP (I/O Pkg) + CALL PSEGXY + LD HL,0918H ; row 9 / col 24 + LD DE,Z3ENV_I+12 ; ptr addr RCP (Resident Cmd Pkg) + CALL PSEGXY + LD HL,0B18H ; row 11 / col 24 + LD DE,Z3ENV_I+24 ; ptr addr Z3CL (ZCPR3 cmd line buffer) + CALL PSEGXY + LD HL,0339H ; row 3 / col 57 + LD DE,Z3ENV_I+21 ; ptr addr Z3NDIR (named dir buffer) + CALL PSEGXY + LD HL,0539H ; row 5 / col 57 + LD DE,Z3ENV_I+9 ; ptr addr EXPATH (external path) + CALL PSEGXY + LD HL,0739H ; row 7 / col 57 + LD DE,Z3ENV_I+30 ; ptr addr SHSTK (shell stack) + CALL PSEGXY + + ; single value entries (8-bit or 16-bit) + LD HL,0939H ; row 9 / col 57 + CALL GOTOXY + LD A,(Z3ENV_I+33) ; SHSIZE (size of a shell stack entry) + CALL PSPCAD ; display + value as dec + LD HL,0A39H ; row 10 / col 57 + CALL GOTOXY + LD HL,(Z3ENV_I+34) ; addr Z3MSG (ZCPR3 message buffer) + CALL PHLXH ; display as hex + 'H' + LD HL,0B39H ; row 11 / col 57 + CALL GOTOXY + LD HL,(Z3ENV_I+36) ; addr EXTFCB (external File Control Block) + CALL PHLXH + LD HL,0C39H ; row 12 / col 57 + CALL GOTOXY + LD HL,(Z3ENV_I+38) ; addr EXTSTK (external stack) + CALL PHLXH + +M3SELCT: CALL MSELECT + CP ' ' ; is it ? + RET Z ; ..return + CP CR ; ? + RET Z ; ..return + CP ESC ; ? + JP Z,M$ABORT ; ..quit program + CP CTRLC ; ? + JP Z,M$ABORT ; ..quit program + CP 'A' ; 'A' (ENV) ? + JR C,M3SELCT ; ..if below ascii 'A', loop ask for new input + + LD HL,Z3ENV_I+27 ; ptr to addr of ZCPR3 Env Descriptor + JR Z,M3EXEC1 + LD HL,Z3ENV_I+18 ; ..of FCP + CP 'B' + JR Z,M3EXEC1 + LD HL,Z3ENV_I+15 ; ..of IOP + CP 'C' + JR Z,M3EXEC1 + LD HL,Z3ENV_I+12 ; ..of RCP + CP 'D' + JR Z,M3EXEC1 + LD HL,Z3ENV_I+24 ; ..of Z3CL (cmd line buffer) + CP 'E' + JR Z,M3EXEC1 + LD HL,Z3ENV_I+21 ; ..of Z3NDIR (named dir buffer) + CP 'F' + JR Z,M3EXEC2 + LD HL,Z3ENV_I+9 ; ..of EXPATH (external path) + CP 'G' + JR Z,M3EXEC2 + LD HL,Z3ENV_I+30 ; ..of SHSTK + CP 'H' + JR Z,M3EXEC4 + LD HL,Z3ENV_I+34 ; ..of Z3MSG (msg buffer) + CP 'I' + JR Z,M3EXEC3 + LD HL,Z3ENV_I+36 ; ..of EXTFCB + CP 'J' + JR Z,M3EXEC3 + LD HL,Z3ENV_I+38 ; ..of EXTSTK + CP 'K' + JR Z,M3EXEC3 + + JP M3ENV + + + ; ##### CHECK: redundant JR C loop in case of error, + ; because called routines handle errors +M3EXEC1: CALL PHLXSIZ ; print addr and size + get input (converted) + JR C,M3EXEC1 +M3EXEC: JP M3ENV ; ..and loop + +M3EXEC2: CALL PHLXENT ; print addr and # entries + get input (converted) + JR C,M3EXEC2 + JR M3EXEC + +M3EXEC3: CALL PHLXCIN ; print (only) addr + get input (converted) + JR C,M3EXEC3 + JR M3EXEC + +M3EXEC4: CALL PADENSZ ; print addr, # entries, and size + get input (converted) + JR C,M3EXEC4 + JR M3EXEC + + +;::::: SUPPORT FUNCTIONS (all Menus) + + ; select an option from menu (validate user input) +MSELECT: CALL VPRINT + DEFB CR,LF,LF + DEFB 0 +MSELCT0: CALL VPRINT + DEFB CR,TAB,TAB,'Selection : ' + DEFB 0 + CALL EREOL ; clear end of line + CALL CAPIN ; get input and capitalize it + CP ' ' ; is it ? + RET Z ; ..return + CP CR ; ? + RET Z ; ..return + CP ESC ; ? + RET Z ; ..return + CP CTRLC ; ? + RET Z ; ..return + CP '0' ; is it a control char (below ascii '0') ? + JR C,MSELCT0 ; ..then loop and ask for new input + CP '9'+1 ; is it an ascii number ? + JR C,MSELCT1 ; ..if so, jump to display + CP 'A' ; is it below ascii 'A' ? + JR C,MSELCT0 ; ..then loop and ask for new input + CP 'Z'+1 ; is it above ascii 'Z' ? + JR NC,MSELCT0 ; ..then loop and ask for new input +MSELCT1: JP COUT ; display on CON: and let return from there + + + ; validate input for (Y)/N query, and echo + ; Yes is default + ; in: A= char (capitalized) +YESNO: CP 'N' ; is it 'N' ? + JR Z,YESNO0 ; ..if so, skip over + LD A,'Y' ; else, set 'Y' for any other char +YESNO0: JP COUT ; print on CON: and let return from there + + ; validate input for Y/(N) query, and echo + ; No is default + ; in: A= char (capitalized) +NOYES: CP 'Y' ; is it 'Y' ? + JR Z,YESNO0 ; ..if so, jump to display + LD A,'N' ; else, set 'N' for any other char + JR YESNO0 ; and jump to display + + + ; determine CSEG and DSEG sizes of linked file + ; (SLINK0 linker module provides a dedicated sizing function) + ; in: DE= ptr FCB + ; HL= addr COMTBL + ; out: BC= DSEG size + ; HL= CSEG size +LNKDSZ: LD (LFCBADR),DE ; store addr of FCB + LD (LTBLADR),HL ; store addr of COMMON table + PUSH DE + INC DE + CALL PFN1 ; display file name + POP DE + CALL INITFCB ; init FCB + CALL F$EXIST ; check if file exists + OR A + JP Z,E$NFND ; ..if not, jump and let return from there + CALL INITFCB ; init FCB + CALL F$OPEN ; open file + OR A + JP NZ,E$OPEN ; ..if error, jump and let return from there + LD A,128 + LD (LBYTPOS),A ; set byte pos for @GBYTE function (= initiate load) + XOR A ; clear A (= just sizing info) + LD HL,(LTBLADR) ; set ptr COMMON table + + CALL LINK + + OR A ; check error status + JP NZ,E$LINK ; ..if not ok, jump + PUSH BC ; save DSEG size + PUSH DE ; save CSEG size + PUSH BC + PUSH DE + LD DE,(LFCBADR) ; get FCB addr + CALL F$CLOSE ; close file + CALL VPRINT + DEFB ' - CSEG=' + DEFB 0 + POP HL ; restore CSEG size + CALL PHL4HC ; ..and display as hex + CALL VPRINT + DEFB 'H, DSEG=' + DEFB 0 + POP HL ; restore DSEG size + CALL PHL4HC ; ..and display as hex + CALL VPRINT + DEFB 'H',CR,LF + DEFB 0 + POP HL ; restore CSEG size in HL + POP BC ; restore DSEG size in BC + RET + + + ; print addr's of BANK2 and B2RAM Common +PB2ADR: LD HL,(COMTB6) ; get org B2RAM Common + LD A,H ; check if zero + OR L + LD HL,(COMTB5) ; prepare, and get org BANK2 Common + JR NZ,PB2ADR0 ; ..if addr <> zero, jump to continue + LD A,H ; else, check org BANK2 Common + OR L ; if also zero + RET Z ; ..if so, return + ; else, fall through and print +PB2ADR0: CALL VPRINT + DEFB ' Bank2=' + DEFB 0 + LD HL,(COMTB5) ; get org BANK2 Common + CALL PHL4HC + CALL VPRINT + DEFB 'H B2Ram=' + DEFB 0 + LD HL,(COMTB6) ; get org B2RAM Common + CALL PHL4HC + CALL VPRINT + DEFB 'H',CR,LF + DEFB 0 + RET + + + ; Standard sizes - calculate base addr's of system segments Non-banked + ; in: - + ; out: - (addr's in ram storage locations) +CALCSSZ: LD DE,(CNBSZ_I) ; compare CCP Non-banked size + LD HL,0800H ; with CP/M standard 2.0 kB + OR A + SBC HL,DE + JR C,E$LARGE ; ..if too large, jump error + LD DE,(DNBSZ_I) ; compare DOS Non-banked size + LD HL,0E00H ; with CP/M standard 3.5 kB + SBC HL,DE + JR C,E$LARGE ; ..if too large, jump error + CALL ENVLOW ; addr of lowest ENV component in HL + CALL USPCSZ ; size of User Space in DE + JR NZ,CALCSS0 ; ..if User Space size <> zero, skip over + LD HL,0 ; else, nullify HL before calc +CALCSS0: OR A ; reset C-Flag + SBC HL,DE ; calc User Space base addr + LD (UNBAD_I),HL ; ..and store it + LD HL,(Z3ENV_I+69) ; start addr BIOS (from ENV) + LD (BNBADR),HL ; ..and store in var (BIOS Non-banked addr) + LD DE,0E00H ; DOS standard size + SBC HL,DE ; calc base addr + LD (Z3ENV_I+66),HL ; store in ENV + LD (DNBADR),HL ; ..and in var (DOS Non-banked addr) + LD A,1CH ; DOS standard size in 128-byte recs + LD (Z3ENV_I+68),A ; ..store in ENV + LD DE,0800H ; CCP standard size + SBC HL,DE ; calc base addr + LD (Z3ENV_I+63),HL ; store in ENV + LD (CNBADR),HL ; ..and in var (CCP Non-banked addr) + LD A,10H ; CCP standard size in 128-byte recs + LD (Z3ENV_I+65),A ; store in ENV + RET + + ; too large +E$LARGE: CALL VPRINT + DEFB CR,LF,BEL,TAB,TAB,'+++ CPR or DOS too Large +++',CR,LF + DEFB 0 + JP AUTOSZ ; loop, ask for auto-sizing + + + ; link file (using SLINK0 LINK routine) + ; in: DE= ptr FCB, BC= phys. addr CSEG, HL= phys. addr DSEG + ; alt. registers set, addr of COMMON table in var + ; out: BC= size DSEG, DE= size CSEG +LNKFILE: PUSH BC + PUSH HL + LD (LFCBADR),DE ; store addr of FCB + CALL INITFCB ; init FCB + CALL F$EXIST ; check if file exists + OR A + JR Z,E$NFND0 ; ..if not, jump and let return from there + CALL INITFCB ; init FCB + CALL F$OPEN ; open file + OR A + JR NZ,E$OPEN0 ; ..if error, jump and let return from there + LD A,128 + LD (LBYTPOS),A ; set ptr for @GBYTE function (= initiate load) + LD A,00000001B ; set flag to link (bit 0= 1), no bitmap (bit 1= 0) + LD HL,(LTBLADR) ; set addr COMMON table + POP DE ; restore DSEG addr + POP BC ; restore CSEG addr + CALL LINK ; ..and link + OR A + JR NZ,E$LINK ; ..if error, jump error and exit + RET + + + ; error messages + +E$NFND0: POP HL ; clear stack + POP HL ; ..then fall through +E$NFND: CALL VPRINT + DEFB '..not found..' + DEFB 0 + JP CRLF + +E$OPEN0: POP HL + POP HL +E$OPEN CALL VPRINT + DEFB '..Open Error..' + DEFB 0 + LD DE,(LFCBADR) ; addr of FCB + CALL F$CLOSE ; close file + JP CRLF + +E$LINK: PUSH AF + CALL VPRINT + DEFB CR,LF,BEL,'..Link Error..' + DEFB 0 + POP AF + CP 'A' + JR NC,E$INFIL + CALL PADC + LD A,' ' + +E$INFIL: CALL COUT + CALL VPRINT + DEFB ' in ' + DEFB 0 + LD DE,(LFCBADR) ; addr of FCB + INC DE ; move ptr to file name + CALL PFN3 + DEC DE + CALL F$CLOSE ; close file + JP EXIT + + +;::::: SLINK0 MODULE SUPPORT FUNCTION AND COMMONs TABLE + + ; get one byte from input file + ; used by SLINK0 linker module + ; (saves all registers) +@GBYTE: PUSH BC ; save regs + PUSH DE + PUSH HL + LD A,(LBYTPOS) ; check pos for file read + CP 128 + JR C,GBYTE0 ; while below 128, bypass reading a sector + LD HL,CPMDMA ; input buffer starts here + CALL SETDMA ; set file DMA buffer + LD DE,(LFCBADR) ; addr of FCB + CALL F$READ ; ..read one sector (sequential) + OR A + SCF ; set C-Flag in case of error + JR NZ,GBYTE1 ; jump w/ error code C-Flag set + + ; valid data is in sector buffer, get a byte and move ptr fwd +GBYTE0: LD E,A ; set ptr for offset + LD D,0 ; high byte is zero + LD HL,CPMDMA ; start from base + ADD HL,DE + INC A ; move ptr fwd + LD (LBYTPOS),A ; ..and save + LD A,(HL) ; get a byte + OR A ; set return status OK (NC) +GBYTE1: POP HL ; restore regs + POP DE + POP BC + RET + + + ; table of Named COMMONs + ; for the various system segments + ; used by SLINK0 linker module + ; (12 bytes per entry) +COMTBL: DEFB '_BIOS_',80H,0 ; name (1-7 char, 80H terminated) - 8 byte field +COMTB0: DEFW 0 ; logical load location ('ORG') of segment + DEFW 0 ; phys. load location of segment + DEFB '_ENV_',80H,0,0 +COMTB1: DEFW 0FE00H + DEFW 0 + DEFB '_MSG_',80H,0,0 +COMTB2: DEFW 0 + DEFW 0 + DEFB '_FCB_',80H,0,0 +COMTB3: DEFW 0 + DEFW 0 + DEFB '_MCL_',80H,0,0 +COMTB4: DEFW 0 + DEFW 0 + DEFB 'BANK2',80H,0,0 +COMTB5: DEFW 0 + DEFW 0 + DEFB 'B2RAM',80H,0,0 +COMTB6: DEFW 0 + DEFW 0 + DEFB 'RESVD',80H,0,0 +COMTB7: DEFW 0 + DEFW 0 + DEFB '_SSTK_',80H,0 +COMTB8: DEFW 0 + DEFW 0 + DEFB '_XSTK_',80H,0 +COMTB9: DEFW 0 + DEFW 0 + DEFB 80H ; end-of-table mark + + + + ; update info string w/ size information "k Bios" + ; in linked BIOS +UPDINFO: LD DE,(LPHYADR) ; last destination addr (BIOS) in WSPC + LD HL,(SYSEADR) ; end addr of linked system in WSPC + XOR A + SBC HL,DE ; calc length in bytes + LD C,L ; and move to BC + LD B,H ; (# of bytes to scan) + EX DE,HL + + ; find string 'k Bios' in linked Bios + ; (similar to Z3LIB's CHKENV routine) +UPDFND: LD DE,S$KBIOS ; point to string to search for ('k Bios') + LD A,(DE) ; do a quick scan for first char in string + CPIR + RET PO ; ..if not found, return + PUSH BC ; save count and addr + PUSH HL + CALL UPDFND0 ; and check remaining chars in string + POP HL + POP BC + JR NZ,UPDFND ; ..if no match, loop + + ; string is stored as "60.00k Bios" + LD DE,-6 ; move 6 bytes back to first digit char + ADD HL,DE + EX DE,HL ; swap regs (ptr in DE) + LD A,(BNBAD_I+1) ; get high byte base addr BIOS Non-banked + ADD A,6 ; ??? # recs User Space ??? + PUSH AF + RRA ; divide by 4 + RRA ; (1.024 = 256 *4 = 0x100 *4) + AND 00111111B ; mask off upper bits + + ; divide by subtraction + LD BC,10 ; B= 0, C= 10 +UPDDIV: SUB C ; A= A-10 + JR C,UPDPAT ; ..if negative, exit loop and write to memory + INC B ; B= B+1 + JR UPDDIV ; continue division + + ; patch new info string +UPDPAT: ADD A,10 ; compensate underflow + LD C,A ; B contains 10's, C contains 1's + LD HL,3030H ; HL= ascii '0' '0' + ADD HL,BC ; convert digits to ascii (add '0') + EX DE,HL ; swap digits/ptr + LD (HL),D ; store 1st digit char + INC HL + LD (HL),E ; store 2nd digit char + INC HL ; move ptr to decimal places + INC HL + EX DE,HL ; and swap regs again + POP AF ; restore AF + AND 00000011B ; mask bits 1 and 0 + LD HL,S$KDECPL ; ptr to list of strings for decimal places + ADD A,A ; strings of 2 bytes each (pos *2) + CALL ADDHLA ; move ptr forward + LDI ; ..and copy 2 bytes + LDI + RET + + ; string 'k Bios' +S$KBIOS: DEFB 'k Bios' + + ; check remaining chars in string +UPDFND0: LD BC,5 ; chars remaining in string + LD DE,S$KBIOS+1 ; find this string +UPDFND1: LD A,(DE) + CPI + RET NZ ; ..if no match, return + INC DE ; move source ptr fwd + JP PE,UPDFND1 ; ..if not yet done, continue checking + RET + + ; strings for decimal places +S$KDECPL: DEFB '00','25','50','75' + + + ; read IMG file header + ; in: file name in standard FCB #1 +RDHDR: LD DE,CPMFCB + CALL F$OPEN ; attempt to open file + OR A ; check if successful + JR NZ,RDHDR0 ; ..if not, jump + CALL CODEND ; get addr WSPC + CALL SETDMA ; ..and set as buffer addr + LD DE,CPMFCB + CALL F$READ ; read file sequentially + JR NZ,RDHDR0 ; ..if error, jump + LD DE,128 ; else, move forward + ADD HL,DE ; by 1 sector + CALL SETDMA ; set file buffer addr + LD DE,CPMFCB + CALL F$READ ; read another sector + RET Z ; ..if successful, return + ; else, fall through +RDHDR0: OR 0FFH ; set Z-Flag + SCF ; and C-Flag (error status) + RET + + + ; write IMG file to disk + ; in: HL= addr IMG in memory + ; BC= # sectors to write + ; out: C-Flag reset (NC) if successful (will not return from error, anyway) +WRFILE: PUSH BC + PUSH HL + LD DE,IMGFCB + CALL INITFCB ; init FCB + CALL F$EXIST ; check if file exists + JR Z,WRFIL0 ; ..if not, jump to continue + LD HL,IMGFCB ; else, try to rename existing file + LD DE,CPMFCB + LD BC,9 ; bytes to copy + LDIR + LD HL,FTYPES ; ptr to standard file type 'BAK' + LD BC,3 ; bytes to copy + LDIR + LD DE,CPMFCB + CALL INITFCB ; init FCB + CALL F$DELETE ; delete an existing .BAK file + EX DE,HL ; HL= ptr to FCB (old file name) + LD DE,IMGFCB ; ptr to FCB (new file name) + CALL F$RENAME ; try to rename + JR Z,E$IMGREN ; ..if error, jump error and exit + +WRFIL0: LD DE,IMGFCB + CALL INITFCB ; init FCB + CALL F$MOPEN ; open file (create if not exists) + POP HL ; clear stack and fall through + POP BC +WRFIL1: PUSH BC ; save regs + PUSH HL + CALL SETDMA ; set file buffer addr + CALL F$WRITE ; write one 128-byte sector + POP HL ; restore regs + POP BC + OR A ; check error status + JR NZ,E$IMGWRI ; ..if error, jump error and exit + PUSH DE + LD DE,128 ; move forward by 1 sector + ADD HL,DE + POP DE + DEC BC ; reduce counter + LD A,B + OR C ; counter = zero ? + JR NZ,WRFIL1 ; ..if not, loop + CALL F$CLOSE ; close file + OR A ; set C-Flag (status = ok) + RET + + + ; error messages + +E$IMGREN: CALL VPRINT + DEFB CR,LF,BEL,' +++ ..Error Renaming: ' + DEFB 0 + +E$IMGFIL: LD DE,IMGFCB+1 ; ptr to file name in IMG FCB + CALL PFN1 ; display it + CALL CRLF + JP EXIT + +E$IMGWRI: CALL VPRINT + DEFB CR,LF,BEL,' +++ ..Error Writing to: ' + DEFB 0 + JR E$IMGFIL + + + ; ##### unreferenced code (not used) +JUMPHL JP (HL) + ; ##### + + + ; get Quiet Flag from Z3 Environment + ; in: - + ; out: A= Quiet Flag, defaults to A= 0 (not quiet) +GETQFLG: LD HL,(ENVADR) ; get local ENVPTR + LD A,H ; check if invalid (= zero) + OR L + RET Z ; ..if so, return + LD A,40 ; else, move ptr forward to Quiet Flag + CALL ADDHLA + LD A,(HL) ; get value + RET + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PRGNAME: LD A,(ENVADR+1) ; get high byte of local ENVPTR + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; ..and let return from there + CALL VPRINT ; else, display default + DEFB 'BPBUILD' + DEFB 0 + RET + + + ; ##### unreferenced code (not used) + LD B,8 +UNUSED1 + INC HL + LD A,(HL) + AND 01111111B + CP ' ' + CALL NZ,COUT + DJNZ UNUSED1 + RET + ; ##### + + + ; add A to HL (result in HL) +ADDHLA: ADD A,L ; add L + LD L,A ; store result in L + RET NC ; ..if no overflow, return + INC H ; else, increment H + RET + + + ; align addr to next 128-byte boundary + ; in: HL= addr + ; out: HL= aligned addr +ALIGN: LD DE,7FH ; add offset for partial 128-byte block + ADD HL,DE + LD A,L ; get low byte + AND 80H ; sector alignment + LD L,A + RET + + + ; Auto-sizing - calculate base addr's of system segments Non-banked + ; in: - + ; out: - (addr's in ram storage locations) +CALCASZ: CALL ENVLOW ; addr of lowest ENV component in HL + CALL VPRINT + DEFB CR,LF,'Sizing from lowest ENV element = ' + DEFB 0 + CALL PHL4HC + CALL USPCSZ ; User Space size (USPCS) in bytes + OR A + SBC HL,DE ; calc User Space start addr + LD (UNBAD_I),HL ; ..and store in IMG hdr + LD A,(BNKDSYS) ; get banking indicator (0= Non-banked) + OR A + JR NZ,CALCAS0 ; ..if Non-banked, skip over + LD DE,(BRSVDO) ; get org RESVD Common + XOR A ; reset flags + SBC HL,DE ; ..and calc base addr +CALCAS0: LD DE,(BNBSZ_I) ; BIOS Non-banked total size + XOR A ; reset flags + SBC HL,DE ; ..and calc BIOS Non-banked base addr + LD L,0 ; align to page boundary + LD (BNBADR),HL ; store it + LD DE,(DNBSZ_I) ; DOS Non-banked total size + SBC HL,DE ; ..calc base addr + LD (DNBADR),HL + LD DE,(CNBSZ_I) ; CCP Non-banked total size + SBC HL,DE ; ..calc base addr + LD (CNBADR),HL + RET + + + ; print base addr's of System (Non-banked Segments) on CON: + ; in: - +PSYSNB: LD HL,(UNBAD_I) ; base addr User Space (from IMG hdr) + LD A,H + OR L ; check if zero + JR NZ,PSYSNB0 ; ..and branch accordingly + CALL VPRINT + DEFB CR,LF,' ' + DEFB 0 + JR PSYSNB1 +PSYSNB0: CALL VPRINT + DEFB CR,LF,' Base of Usr Sp = ' + DEFB 0 + CALL PHL4HC ; display HL as hex +PSYSNB1: CALL VPRINT + DEFB CR,LF,' Base of Bios = ' + DEFB 0 + LD HL,(BNBADR) ; BIOS Non-banked base addr (from var) + CALL PHL4HC ; ..display as hex + CALL VPRINT + DEFB CR,LF,' Base of Dos = ' + DEFB 0 + LD HL,(DNBADR) ; DOS Non-banked base addr (from var) + CALL PHL4HC + CALL VPRINT + DEFB CR,LF,' Base of Cpr = ' + DEFB 0 + LD HL,(CNBADR) ; CCP Non-banked base addr (from var) + JP PHL4HC ; ..display and let return from there + + + ; size of User Space in bytes + ; in: - + ; out: DE= size, Z-Flag set if size = 0 +USPCSZ: LD DE,UNBSZ_I ; User Space # records in IMG hdr + LD A,(DE) + LD D,A ; convert to 16-bit word + LD E,0 ; ..and multiply by 256 + SRL D ; /2 (blocks * 128 = size in bytes) + RR E + OR A ; if User Space size = zero, set Z-Flag + RET + + + ; get lowest addr in Z3ENV + ; ( from offs. +9 EXPAT to +30 SHSTK = 8x 16-/8-bit value combo + ; from offs. +34 Z3MSG to +38 EXTSTK = 3x 16-bit value ) + ; in: - + ; out: HL= lowest addr of Z3ENV components +ENVLOW: LD HL,Z3ENV_I ; ptr to Z3ENV base + LD DE,9 ; start w/ offset to addr EXPATH (ext. path) + ADD HL,DE + LD C,(HL) ; get addr in BC + INC HL + LD B,(HL) + DEC HL ; move ptr back prior to loop + LD A,8 ; 8 entries (from EXPATH to SHSTK) +ENVLOW0: PUSH AF + CALL ADRLOWC ; find the lower of two addresses + INC HL ; skip byte following the addr + POP AF + DEC A ; decrease counter + JR NZ,ENVLOW0 ; ..loop till done + LD A,3 ; 3 entries (from Z3MSG to EXTSTK) +ENVLOW1: PUSH AF + CALL ADRLOWS ; find the lower of two addresses + POP AF + DEC A ; decrement counter + JR NZ,ENVLOW1 ; ..loop till done + INC HL ; skip Quiet flag + CALL ADRLOWS ; check also Z3WHL addr + LD L,C ; finally, copy lowest addr to HL + LD H,B + RET + + + ; returns lowest addr of Z3ENV components w/ 16-/8-bit value combo (e.g. RCP, IOP) + ; in: HL= ptr to current addr + ; BC= lowest addr so far + ; out: BC= lowest addr +ADRLOWC: LD E,(HL) ; get low byte + INC HL + LD D,(HL) ; ..and high byte + INC HL + LD A,D + OR E ; check if high = low = zero + RET Z ; ..if so, return + LD A,(HL) ; get high byte again + OR A ; check if zero + RET Z ; ..if so, return + LD A,E ; get low byte again + SUB C + LD A,D ; get high byte again + SBC A,B ; ..and check against lowest addr so far + RET NC ; ..no C-Flag means, old addr is lower + LD C,E ; else, copy current addr + LD B,D + RET + + + ; returns lowest addr of Z3ENV components w/ 16-bit value (e.g. Z3MSG) + ; in: HL= ptr to byte ahead of current addr + ; BC= lowest addr so far + ; out: BC= lowest addr +ADRLOWS: INC HL ; move ptr fwd to addr + LD A,(HL) ; get low byte + INC HL + OR (HL) ; check if high = low = zero + RET Z ; ..if so, return + DEC HL ; move ptr back + LD A,(HL) ; get low byte again + INC HL + SUB C + LD A,(HL) ; get high byte again + SBC A,B ; ..and check against lowest addr so far + RET NC ; ..no C-Flag means, old addr is lower + LD B,(HL) ; else, copy current addr + DEC HL + LD C,(HL) + INC HL + RET + + + ; print HL as four-digit hex + closing bracket + ; then get user input and convert to number + ; in: HL= 16-bit value + ; A= 0 no conversion, <> 0 convert to number + ; out: DE= converted number +PHLXCNV: PUSH HL ; save regs + CALL PHL4HC ; display as hex + LD A,'H' ; display additional 'H' + CALL COUT + POP DE ; prepare for no input (restore value in DE) + CALL PRBRCIN ; display closing bracket and get user input + RET Z ; ..if input empty, return + JP EVAL16 ; else, convert as hexadecimal + ; ..and let return from there + + + + ; print HL as decimal + closing bracket + ; then get user input and convert to number + ; in: HL= 16-bit value + ; A= 0 no conversion, <> 0 convert to number + ; out: DE= converted number +PHLDCNV: PUSH HL ; save regs + CALL PHLFDC ; display as dec + POP DE ; prepare for no input (restore value in DE) + CALL PRBRCIN ; display closing bracket and get user input + RET Z ; ..if input empty, return + JP EVAL10 ; else, convert as decimal number + ; ..and let return from there + + + ; print right (closing) bracket, then fall through to get user input +PRBRCIN: CALL VPRINT + DEFB ']',TAB,': ' + DEFB 0 + + + ; get console input (based based on line editor) + ; in: - + ; out: HL= ptr to first char of nul-terminated input string + ; ##### CHECK: buffer location could interfere with STACK +CINPUTL: LD HL,CINBUF ; set ptr to buffer + LD (HL),30 ; set buffer size + INC HL + LD (HL),0 ; init char count (filled by BLINE) + INC HL + LD (HL),0 ; init first char (filled by BLINE) + DEC HL ; move ptr back to start of buffer + DEC HL + OR 0FFH ; set flag to capitalize + JP BLINE ; get line input, and let return from there + + + ; ##### unreferenced code (not used) +UNUSED2 + CALL BASEROW + LD L,10 + CALL GOTOXY + CALL VPRINT + DEFB 'Selection (ESC/Ctrl-C Aborts) : ' + DEFB 0 + CALL CAPINE + CP ESC + RET Z + CP CTRLC + RET Z + CALL ISALNUM + JR NZ,UNUSED2 + RET + ; ##### + + + ; print segment information - addr, # entries, and size + ; ask for new values and convert, replacing old values at orig. location + ; in: HL= ptr to 16-bit value (addr), + ; followed by 8-bit values (entries, size) +PADENSZ: CALL PHLXENT ; print addr and # entries, get input (converted) + PUSH HL ; save ptr + CALL BASEROW + INC HL ; row 4 from bottom + JR PHLXSZ1 ; ..jump to continue displaying size + + + ; print string "Address" and 16-bit value as hex on CON: + ; ask for new value, convert it, and store at original addr + ; then print "Size" and following byte, ask for new value, + ; convert it, and store at original addr + ; in: HL= ptr to 16-bit value (addr), followed by 8-bit value (entries) +PHLXSIZ: CALL PHLXCIN ; print addr, get input and convert +PHLXSZ0: PUSH HL ; save ptr + CALL BASEROW ; row 5 from bottom +PHLXSZ1: INC H ; 2* row down + INC H + LD L,16 ; col 16 + CALL GOTOXY ; position cursor + CALL VPRINT + DEFB 'Size',TAB,' [' + DEFB 0 + POP HL ; restore ptr + LD A,(HL) ; get byte + PUSH HL + LD L,A ; copy byte to L + LD H,0 ; set high byte to zero + CALL PHLDCNV ; ..display as dec and get user input (converted) + POP HL ; restore ptr + JR NC,PHLXSZ2 ; ..if conversion successful, skip over + LD A,BEL ; else, send to CON: + CALL COUT + JR PHLXSZ0 ; ..and loop + +PHLXSZ2: LD A,E ; copy converted number to A + LD (HL),A ; ..and store at orig. location + RET + + + ; print string "Address" and 16-bit value as hex on CON: + ; ask for new value, convert it, and store at original addr + ; then print "Entries" and following byte, ask for new value, + ; convert it, and store at original addr + ; in: HL= ptr to 16-bit value (addr), followed by 8-bit value (entries) +PHLXENT: CALL PHLXCIN ; print addr, get input and convert +PHLXEN0: PUSH HL ; save ptr + CALL BASEROW ; row 5 from bottom + INC H ; 2* row down + INC H + LD L,16 ; col 16 + CALL GOTOXY ; position cursor + CALL VPRINT + DEFB '# Entries [' + DEFB 0 + POP HL ; restore ptr + LD A,(HL) ; get byte + PUSH HL + LD L,A ; copy byte to L + LD H,0 ; set high byte to zero + CALL PHLDCNV ; ..display as dec and get user input (converted) + POP HL ; restore ptr + JR NC,PHLXSZ2 ; ..if conversion successful, jump to continue + LD A,BEL ; else, send to CON: + CALL COUT + JR PHLXEN0 ; ..and loop + + + ; print string "Address" and 16-bit value as hex on CON: + ; in row 4 from bottom, col 15 + ; then ask for new value, convert it, and store at original addr + ; in: HL= ptr to 16-bit value +PHLXCIN: PUSH HL + CALL BASEROW ; row 5 from bottom + INC H ; row down + LD L,15 ; col 15 + CALL GOTOXY ; position cursor + CALL VPRINT ; ..and display + DEFB 'Address',TAB,'[' + DEFB 0 + POP HL ; restore ptr in HL + LD E,(HL) ; get 16-bit value in DE + INC HL + LD D,(HL) + DEC HL + PUSH HL ; save ptr again + EX DE,HL ; swap regs + CALL PHLXCNV ; display hex value and get user input (converted) + POP HL ; restore ptr + JR NC,PHLXCI0 ; check for overflow in number conversion + ; ..if not, jump + ; else, fall through + LD A,BEL ; alert user (send to CON:) + CALL COUT + JR PHLXCIN ; ..and loop + +PHLXCI0: LD (HL),E ; store converted number in DE + INC HL ; at orig. location + LD (HL),D + INC HL + RET + + + ; print addr and value of segment to CON: at xy coordinates + ; in: HL= row/col + ; DE= ptr to addr (value byte follows) +PSEGXY: CALL GOTOXY ; position cursor + PUSH HL ; save coordinates + LD A,(DE) ; get low byte + INC DE ; move ptr fwd + LD L,A + LD A,(DE) ; get high byte + INC DE ; ptr fwd + LD H,A + CALL PHLXH ; display 16-bit value as hex and 'H' + POP HL ; restore coordinates + INC H ; row +1 + CALL GOTOXY ; position cursor + LD A,(DE) ; get byte + JR PSPCAD ; display + value as dec, return from there + + + ; print addr in HL as four-digit hex and append 'H' + ; in: HL= addr +PHLXH: CALL PHL4HC ; display as 4-digit hex + LD A,'H' ; append 'H' + JP COUT ; ..and let return from there + + + ; ###### unreferenced code (not used) +UNUSED3: CALL ALIGN ; align to next sector boundary + ADD HL,HL + LD A,H + ; ##### + + ; print and A as decimal +PSPCAD: PUSH AF ; save regs + LD A,' ' ; send to CON: + CALL COUT + POP AF ; restore A + JP PADC ; display as decimal, let return from there + + + ; returns row # of 5 lines above bottom of screen + ; in: - + ; out: H= row (max. row -5) +BASEROW: PUSH DE ; save regs + LD HL,(ENVADR) ; get ptr to ENV + LD DE,50 ; offset to number of rows (CRT) + ADD HL,DE ; move ptr + LD H,(HL) ; get value + DEC H ; -5 + DEC H + DEC H + DEC H + DEC H + POP DE ; restore regs + RET + + +;::::: Standard file types + +FTYPES: DEFB 'BAK','IMG','REL','ZRL' + DEFS 23 + + +;::::: HEADER OF IMAGE FILE (all labels end with "_I") + + ; area for building the IMG file header + ; if an image file was specified on the command line, the header is read + ; and copied here, else default values are used and updated accordingly +IMGHD_I: JP 0 + +UNBAD_I: DEFW 0E900H ; addr User Space Non-banked +UNBSZ_I: DEFB 6 ; # recs +UBKAD_I: DEFW 0 ; addr User Space Banked + DEFS 8 + +CFNAM_I: DEFB 'ZCPR33 REL' ; default name ZCPR file +CNBAD_I: DEFW 0 ; Non-banked base addr +CNBSZ_I: DEFW 0 ; " size +CBKAD_I: DEFW 0 ; Banked base addr +CBKSZ_I: DEFW 0 ; " size + DEFS 13 + +DFNAM_I: DEFB 'ZSDOS ZRL' ; default name ZSDOS file +DNBAD_I: DEFW 0 +DNBSZ_I: DEFW 0 +DBKAD_I: DEFW 0 +DBKSZ_I: DEFW 0 + DEFS 13 + +BFNAM_I: DEFB 'B/P-18 REL' ; default name B/P Bios file +BNBAD_I: DEFW 0 +BNBSZ_I: DEFW 0 +BBKAD_I: DEFW 0 +BBKSZ_I: DEFW 0 + DEFS 13 + +IMGFN_I: DEFB 'BPSYS IMG' ; default name system image file + DEFS 5 + + +;::::: Z3ENV DESCRIPTOR (in IMG header) + +Z3ENV_I: JP 0 ; Leading jump (address is CBIOS when NZCOM) + DEFB 'Z3ENV' ; Environment ID + DEFB 81H ; Env type (=>80H means extended) + ; ##### should rather be 90H for B/P Bios + + ; offset + ; (dec / hex) + DEFW 0FDF4H ; EXPATH 9 / 09 + DEFB 05H + DEFW 0F200H ; RCP 12 / 0C + DEFB 10H + DEFW 0EC00H ; IOP 15 / 0F + DEFB 0CH + DEFW 0FA00H ; FCP 18 / 12 + DEFB 04H + DEFW 0FC00H ; Z3NDIR 21 / 15 + DEFB 0EH + DEFW 0FF00H ; Z3CL 24 / 18 + DEFB 0CBH + DEFW 0FE00H ; Z3ENV 27 / 1B + DEFB 02H + DEFW 0FD00H ; SHSTK 30 / 1E + DEFB 04H + DEFB 20H + DEFW 0FD80H ; Z3MSG 34 / 22 + DEFW 0FDD0H ; EXTFCB 36 / 24 + DEFW 0FFD0H ; EXTSTK 38 / 26 + DEFB 00H ; Quiet Flag 40 / 28 + DEFW 0FDFFH ; Z3WHL 41 / 29 + DEFB 4 ; Proc. Speed (MHz) 43 / 2B + + DEFB 'P'-'@' ; Max Disk Letter + DEFB 31 ; Max User Number + DEFB 1 ; DU flag + DEFB 0 ; CRT Selection + DEFB 0 ; Printer Selection + DEFB 80 ; CRT 0: Width (# Columns) + DEFB 24 ; # of Lines + DEFB 22 ; # of Text Lines + + DEFW 0001000011111111B ; DRVEC (valid drives) 52 / 34 + DEFB 0 ; + + DEFB 80 ; PRT 0: Width (# Columns) + DEFB 66 ; # of Lines + DEFB 58 ; # of Text Lines + DEFB 1 ; FF Flag + + ; storage for Resident User Space Vectors (replaces PRT1 definitions) + DEFB 06H ; remaining free recs 59 / 3B + DEFW 0E900H ; base addr (xx00H/xx80H) 60 / 3C + DEFB 06H ; size in 128-byte recs 62 / 3E + + DEFW 0BE00H ; CPR 63 / 3F + DEFB 10H + DEFW 0C600H ; DOS 66 / 42 + DEFB 1CH + DEFW 0D400H ; BIOS 69 / 45 + + DEFB 'SH ' ; Shell variable filename + DEFB 'VAR' ; Shell variable filetype + DEFB ' ' ; File 1 + DEFB ' ' ; + DEFB ' ' ; File 2 + DEFB ' ' ; + DEFB ' ' ; File 3 + DEFB ' ' ; + DEFB ' ' ; File 4 + DEFB ' ' ; + DEFB 0 ; Public Drive Area (ZRDOS +) + DEFB 0 ; Public User Area (ZRDOS +) + + ; *** end of Z3ENV descriptor and IMG header *** + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; LINK - 0x1980 +; VLIB - 0x1bfb +; Z3LIB - 0x1e3a +; SYSLIB - 0x20f4 +; end addr 0x23e0 (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;::::: RAM STORAGE + + DSEG + +MSELOPT: DEFB 0 ; selected Menu option + + ; room for FCB's of system segments +CCPFCB: DEFS 36 ; CCP (ZCPR) +DOSFCB: DEFS 36 ; (ZS)DOS +BIOSFCB: DEFS 36 ; (B/P) BIOS + +CCNBSZ: DEFW 0 ; CCP CSEG Non-banked Size (in TPA bank) +DCNBSZ: DEFW 0 ; DOS CSEG Non-banked Size +BCNBSZ: DEFW 0 ; BIOS CSEG Non-banked Size +BCBKSZ: DEFW 0 ; BIOS CSEG Banked Size (org 'BANK2', in System bank) +BDBKSZ: DEFW 0 ; BIOS DSEG Banked Size (org 'B2RAM') +DCBKSZ: DEFW 0 ; DOS CSEG Banked Size ('BANK2') +DDBKSZ: DEFW 0 ; DOS DSEG Banked Size ('B2RAM') +CCBKSZ: DEFW 0 ; CCP CSEG Banked Size ('BANK2') +CDBKSZ: DEFW 0 ; CCP DSEG Banked Size ('B2RAM') + +SYSBLKS: DEFW 0 ; Size of new system in 128-byte blocks (# sectors) +AUTOSIZ: DEFB 0 ; Auto-sizing flag (0= no, 0xFF= yes) +BNKDSYS: DEFB 0 ; Banked system flag (bit 3 of OPTF1 = indicator ALV/CSV in bank) +OPTF1: DEFB 0 ; OPTF1 option flag of linked BIOS +BRSVDO: DEFW 0 ; BIOS org RESVD common +BNBADR: DEFW 0 ; BIOS Non-banked base addr +DNBADR: DEFW 0 ; DOS Non-banked base addr +CNBADR: DEFW 0 ; CCP Non-banked base addr + +LPHYADR: DEFW 0 ; phys. destination addr when linking system segment (from WSPC onwards) +SYSEADR: DEFW 0 ; end addr of new system in WSPC (total of all segments) + +IMGFCB: DEFS 36 ; room for FCB of image file + + ; used by linker related fn's +LBYTPOS: DEFB 0 ; byte ptr @GBYTE function +LFCBADR: DEFW 0 ; addr current FCB +LTBLADR: DEFW 0 ; addr COMTBL + +CINBUF: ; console input buffer + DEFS 60H ; room for stack +STACK: DEFW 0 ; stack storage location +OLDDU: DEFW 0 ; logged Drive/User at program start + + END + + +;************************************************************************ +; Remarks jxl: +; BPBUILD.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file matches exactly the +; original ZSCFG2.COM, i.e. no changes to the source were made. Possible +; optimisations detected during disassembly are marked with "#####" in the +; comment. +; +; The program makes use of linker module which was included in the +; distributed package of ZSDOS v1 sources (SLINK0.Z80/.REL), to generate +; its output from M-REL files - an interesting piece of software! +; The embedded Image header and Z3 Environment descriptor could be +; externalised in .LIB files. However, this was not done (yet) to provide +; the complete source code "as is." +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/bpcnfg.z80 b/Source/BPBIOS/UTIL/bpcnfg.z80 new file mode 100644 index 00000000..4e8476fc --- /dev/null +++ b/Source/BPBIOS/UTIL/bpcnfg.z80 @@ -0,0 +1,4539 @@ + TITLE "Change B/P Bios Configuration Settings" +;************************************************************************ +;* B P C O N F I G * +;* Set user-configurable parameters in a B/P Bios * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Nov 2024 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB * +;* * +;* A>Z80ASM BPCNFG/RS * +;* A>SLRNK BPCNFG/N,/A:100,/D:3A55,BPCNFG,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 21 +REV EQU 'a' + +DATE MACRO + DEFB '21 Apr 97' + ENDM + + +CTRLC EQU 03H ; Control-C character +BEL EQU 07H ; Bell character +BS EQU 08H ; Backspace character +TAB EQU 09H ; Tab character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character +CTRLZ EQU 1AH ; Control-Z character (end of file) +ESC EQU 1BH ; Escape character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) +CPMFCB2 EQU 6CH ; CP/M standard FCB #2 + + +; For SYSLIB make visible... + PUBLIC CIN + +; From VLIB Get.. + EXTRN Z3VINIT, VPRINT, CLS, VPSTR, EREOL + +; From Z3LIB Get.. + EXTRN WHRENV, GETNAME, PRTNAME, ZFNAME, FCB1CHK, Z3LOG + +; From SYSLIB Get.. + EXTRN RETUD, LOGUD, CODEND, COUT, CRLF, PAFDC, PHLFDC, PHL4HC, PAFDC, PFN3, EVAL + EXTRN CAPIN, CAPINE, INLINE, SETDMA, F$EXIST, F$OPEN, R$READ, F$WRITE, F$CLOSE, F$READ + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +BPCNFG: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0h ; addr of Z3 environment + DEFW BPCNFG ; type 4 filler + DEFB 'BPCNFG ' ; configuration name + DEFB 0 +FTYPE: DEFB 'IMG' ; standard file types + DEFB 'CNF' + +START: LD (STACK),SP ; save stack pointer + LD SP,STACK ; ..and set local stack + CALL RETUD ; get currently logged drive/user + LD (OLDDU),BC ; ..store + CALL CODEND ; determine begin of WSPC + LD (WSPCBEG),HL ; ..store + LD (WRKSTRT),HL ; ..plus a copy to work with + EX DE,HL ; clear workspace area up to 0x8000 + LD HL,8000H + OR A + SBC HL,DE ; calc length + LD C,L + LD B,H + DEC BC ; actual bytecount is one less + LD L,E ; restore HL + LD H,D + INC DE ; move fwd + LD (HL),0 ; set first byte to 0x00 + LDIR ; ..clear + + ; save 2nd token of cmdline (script file) + LD HL,CPMFCB2 ; ptr to 2nd token of cmdline + LD DE,CFFCB ; ptr to local FCB + LD BC,16 ; copy 16 bytes + LDIR + CALL CFINFT ; add standard filetype, if necessary + + ; find/init Z3 Environment + LD HL,(CPMBDOS+1) + CALL WHRENV ; locate Env descriptor + LD (ENVADR),HL ; ..save addr + CALL Z3VINIT ; and init for VLIB/Z3LIB routines + CALL GETNAME ; get actual program name + CALL GETQFLG ; get quiet flag + AND A + JR NZ,START0 ; ..if quiet, skip over + + ; display message (verbosely) + CALL VPRINT + DEFB CR,LF,1,'B/P CONFIG Utility',2,' V' + DEFB VER/10+'0','.',VER MOD 10 + '0',REV,' ' + DATE + DEFB CR,LF,' Copyright 1991-3 by H.F.Bower/C.W.Cotrill',CR,LF + DEFB 0 + + ; init BIOS shortcuts and evaluate cmdline (FCB #1) +START0: LD HL,(CPMBIOS+1) ; ptr to BIOS WBOOT JP + LD A,8*3 ; ..skip 8 JP's + CALL ADDHLA ; HL= ptr to JP of BIOS fn #9 (SELDSK) + LD DE,BIOSELD ; target addr + LD BC,8*3 ; make local copies of 8 fn jumps + LDIR + LD A,(CPMFCB+1) ; get first cmdline token from FCB + CP '/' ; is this a help request ? + JP Z,HELP ; ..if so, show help screen + CP '?' ; is it an ambiguous filename ? (option '*' is expanded) + LD C,'M' + JR Z,CHKMOD1 ; ..if so, jump to (M)emory config + CP ' ' ; ? + LD C,'I' + JP NZ,CHKMOD6 ; ..if not, jump to (I)mage config + LD A,(CPMFCB) ; else get drive + OR A ; is it zero ? + JR Z,CHKMODE ; ..if so, jump to display options + ADD A,40H ; else, convert to ascii letter + LD C,'D' + JR CHKMOD4 ; ..and jump to (D)isk config + + ; --- Check running mode +CHKMODE: CALL VPRINT + DEFB CR,LF,' Configure Memory (M), Disk (D), or Image (I) ? : ' + DEFB 0 + CALL GETINP + LD C,A ; keep user input + CP 'M' ; is it 'M' ? + JR NZ,CHKMOD2 ; ..if not, jump to next + +CHKMOD1: LD A,C ; restore user input + LD (RUNMODE),A ; save (confirmed) mode + CALL RDMEM ; read B/P Bios of running system + JP CHKMOD9 + +CHKMOD2: CP 'D' ; is it 'D' ? + JR NZ,CHKMOD5 ; ..if not, jump to next + CALL VPRINT +CHKMOD3: DEFB CR,LF,TAB,'Disk Drive Letter (A..P) : ' + DEFB 0 + CALL GETINP ; get input + CALL CHKDLTR ; is a valid drive letter ? ('A'..'P') + JR C,CHKMOD3 ; ..if not, ask for new input +CHKMOD4: PUSH AF ; save AF + LD A,C ; restore user input + LD (RUNMODE),A ; save (confirmed) mode + POP AF ; restore AF (drive) + CALL RDDSK ; read system tracks and find B/P Bios + JR CHKMOD9 + +CHKMOD5: CP 'I' ; is it 'I' ? + JP NZ,CHKMODE ; ..if not, loop ask user again + CALL VPRINT + DEFB CR,LF,TAB,'Image File to Configure : ' + DEFB 0 + CALL CINPUTL ; get input (inline editor) + JP Z,EXIT + LD DE,CPMFCB ; ptr to CP/M standard FCB #1 + CALL ZFNAME ; parse FCB + OR A + JR NZ,CHKMOD7 ; ..if error, display msg and quit program +CHKMOD6: LD A,C ; restore user input + LD (RUNMODE),A ; save (confirmed) mode + CALL FCB1CHK ; check 1st cmdline token + JR Z,CHKMOD8 ; ..if valid filename, skip over + +CHKMOD7: CALL E$MSG + CALL VPRINT + DEFB 'Error in File Name Parse !' + DEFB 0 + JP EXIT +CHKMOD8: CALL RDIMG ; read image file + + ; fall through and try to open script file +CHKMOD9: XOR A + LD (CFBYTE),A ; clear current byte + LD A,(CFFCB+1) ; get first char of script file name + CP ' ' ; is it ? + CALL NZ,CFINOPN ; ..if not, open script file + + ; * + + +;::::: MENU 0 - MAIN + + +M0MAIN: LD SP,STACK ; reset SP to local stack + XOR A ; clear A + LD (CFMENU),A ; ..and store as indicator + CALL CLS + CALL VPRINT + DEFB CR,LF,'Main Menu - Configuring ' + DEFB 0 + + ; eval user selection + ; configure (M)emory, (D)isk, or default to (I)mage + LD A,(RUNMODE) + CP 'M' + JR NZ,M0MAIN1 + CALL VPRINT + DEFB 'Running Memory' + DEFB 0 + JR M$BVER +M0MAIN1: CP 'D' + JR NZ,M0MAIN2 + CALL VPRINT + DEFB 'Drive ' + DEFB 0 + LD A,(DISKNO) ; get disk number + ADD A,40H ; ..convert to ascii letter for display + CALL COUT + LD A,':' + CALL COUT + CALL VPRINT + DEFB ' Boot Sectors' + DEFB 0 + JR M$BVER +M0MAIN2: CALL VPRINT + DEFB 'Image File [' + DEFB 0 + LD BC,(IMGDU) + LD A,B + ADD A,'A' + CALL COUT + LD A,C + CALL PAFDC ; print byte in A as 1-3 decimal chars + LD A,':' + CALL COUT + LD DE,CPMFCB+1 ; filename in CP/M standard FCB + CALL PFN3 ; display fn/ft on CON: + LD A,']' + CALL COUT + + ; msg B/P Bios Vers x.x +M$BVER: CALL VPRINT + DEFB CR,LF,' Bios Ver ' + DEFB 0 + LD A,(BPVERS) ; get version # + PUSH AF ; save AF + RRCA ; reverse nybbles in A + RRCA + RRCA + RRCA + CALL PLOWAX ; print lower nybble as hex + LD A,'.' + CALL COUT + POP AF ; restore AF + CALL PLOWAX ; ..and print lower nybble as hex + + ; display Main menu + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 1 ',2,' System Options' + DEFB CR,LF,LF,' ',1,' 2 ',2,' Character IO Options' + DEFB CR,LF,LF,' ',1,' 3 ',2,' Floppy Subsystem Options' + DEFB CR,LF,LF,' ',1,' 4 ',2,' Hard Disk Subsystem Options' + DEFB CR,LF,LF,' ',1,' 5 ',2,' Logical Drive Layouts' + DEFB CR,LF,LF,' ',1,' 6 ',2,' Configure from Script File' + DEFB 0 + +M0SLCT: LD A,'6' ; max. possible option in this menu as ascii number + CALL MSELECT + OR A + JR Z,WRCONF + CP '1' + JP Z,M1SYS + CP '2' + JP Z,M2CIO + CP '3' + JP Z,M3FD + CP '4' + JP Z,M4HD + CP '5' + JP Z,M5DL + CP '6' + JP Z,M6CNF + CALL CFEVAL ; eval script file input + JR M0SLCT ; loop + + ; write configuration +WRCONF: CALL VPRINT + DEFB CR,LF,'..Writing New Configuration to ' + DEFB 0 + LD A,(RUNMODE) ; get mode + CP 'D' ; config mode (D)rive ? (system tracks) + JR NZ,WRCONF1 ; ..if not, jump to next + + CALL VPRINT + DEFB 'Drive : ' + DEFB 0 + LD A,(DISKNO) ; get disk number + ADD A,40H ; convert to ascii letter for display + CALL COUT + CALL WRDSK ; write to disk + JR WRCONF3 ; ..and exit +WRCONF1: CP 'M' ; config mode (M)emory ? (running system) + JR NZ,WRCONF2 ; ..if not, jump to next + + CALL VPRINT + DEFB 'Memory..' + DEFB 0 + CALL WRMEM ; write to memory + JR WRCONF3 ; ..and exit +WRCONF2: CALL VPRINT ; config mode (I)mage + DEFB ' : ' + DEFB 0 + LD DE,CPMFCB+1 ; filename in CP/M standard FCB + CALL PFN3 ; display fn.ft on CON: + CALL VPRINT + DEFB '..' + DEFB 0 + CALL WRIMG ; write to image file +WRCONF3: LD BC,(OLDDU) + CALL LOGUD ; restore previously logged DU: + CALL CRLF + JP EXIT + + ; * + + +;::::: MENU 1 - SYSTEM OPTIONS (display) + + +M1SYS: LD A,1 + LD (CFMENU),A ; store flag (sub-)menu entered + CALL CLS + CALL VPRINT + DEFB CR,LF,'Menu 1 - System Options' + DEFB CR,LF,LF,LF,' ',1,' 1 ',2,' System Drive = ' + DEFB 0 + LD A,7FH ; offset to SYSDRV in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get system drive # + ADD A,'A' ; ..convert to ascii letter + CALL COUT ; display it + CALL VPRINT + DEFB ':',CR,LF,LF,' ',1,' 2 ',2,' Startup Command = "' + DEFB 0 + LD A,8EH ; offset to AUTOCMD in Config area + CALL WSPCPTR ; set ptr + INC HL ; get past leading 'DEFB 8' + CALL VPSTR ; ..and display nul-terminated string + CALL VPRINT + DEFB '"',CR,LF,LF,' ',1,' 3 ',2,' Reload Constant = ' + DEFB 0 + LD A,9FH ; offset to RELOD0 in Config area (const counter/timer) + CALL WSPCPTR ; set ptr + LD A,(HL) ; get low byte of 16-bit value + INC HL ; ptr fwd + LD H,(HL) ; get high byte + LD L,A + CALL PHLFDC ; display value in HL as dec + CALL VPRINT + DEFB ' (' + DEFB 0 + CALL PHL4HC ; ..and as hex + CALL VPRINT + DEFB 'H)', + DEFB LF,CR,LF,' ',1,' 4 ',2,' Processor Speed = ' + DEFB 0 + LD A,9DH ; offset to SPEED in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get processor speed + CALL PAFDC ; ..and display it + CALL VPRINT + DEFB ' MHz' + DEFB CR,LF,LF,' ',1,' 5 ',2,' Memory Waits = ' + DEFB 0 + LD A,9EH ; offset to WAITS in Config area (MEM + IO combined) + CALL WSPCPTR ; set ptr + LD A,(HL) ; get value + RRCA ; reverse nybbles in A + RRCA + RRCA + RRCA + AND 00001111B ; mask off upper nybble + CALL PAFDC ; ..and display value + CALL VPRINT + DEFB ', IO Waits = ' + DEFB 0 + LD A,(HL) ; get value + AND 00001111B ; mask off upper nybble + CALL PAFDC ; ..and display value + LD A,'6' ; max. possible option in this menu as ascii number + ; (hidden option 6: Menu 1.1 System Banks) + CALL MSELECT + OR A + JP Z,M0MAIN + + +;::::: MENU 1 - SYSTEM OPTIONS (configure) + + ; subsequent labels start with "SY_" +M1CFG: CP '1' ; option '1' selected ? + JR NZ,SY_CMD ; ..if not, jump to next + CALL CRLF + + ; --- option 1 System Drive +SY_DRV: CALL VPRINT + DEFB CR,TAB,TAB,'System Drive Letter',TAB,TAB,'[' + DEFB 0 + LD A,7FH ; offset to SYSDRV in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get system drive # + ADD A,'A' ; ..convert to ascii letter + CALL COUT ; display it + CALL VPRINT + DEFB ']',TAB,': ' + DEFB 0 + CALL EREOL ; clear CON: to end of line + CALL GETINP + JP Z,M1SYS ; ..if no input, jump display menu again + CP CR ; entered ? + JP Z,M1SYS ; ..if so, jump display menu + CALL CHKDLTR ; check is drive letter A..P ? + JR NC,SY_DRV1 ; ..if so, jump to continue + CALL CFEVAL ; eval script file input + JR SY_DRV ; loop (ask for new input) +SY_DRV1: SUB 'A' ; convert ascii to number + LD C,A + LD A,7FH ; offset to SYSDRV in Config area + CALL WSPCPTR ; set ptr in WSPC + LD (HL),C ; store new SYSDRV value + JP M1SYS ; loop, jump to display menu + + ; --- option 2 Startup Command +SY_CMD: CP '2' ; option 2 selected ? + JR NZ,SY_TMR ; ..if not, jump to next + CALL CRLF +SY_CMD1: CALL VPRINT + DEFB CR,TAB,TAB,'Enter New Startup Command : ' + DEFB 0 + CALL EREOL ; clear CON: to end of line + CALL CINPUTL ; get input (inline editor) + JR Z,SY_CMD1 ; ..if empty, jump ask for new input + EX DE,HL ; DE= ptr input buffer + LD A,8EH ; offset to AUTOCMD in Config area + CALL WSPCPTR ; set ptr in WSPC + INC HL ; move past leading 'DEFB 8' + EX DE,HL ; swap pointers + LD B,8 ; copy up to 8 chars +SY_CMD2: LD A,(HL) ; get char from input buffer + OR A ; is it a ? (= end) + JR Z,SY_CMD3 ; ..if so, exit loop + LD (DE),A ; store char in AUTOCMD + INC HL ; move ptr's fwd + INC DE + DJNZ SY_CMD2 ; ..and loop til done + JR SY_CMD5 ; at this point, 8 chars were copied + ; no filling up with +SY_CMD3: EX DE,HL ; swap pointers (HL= AUTOCMD) +SY_CMD4: LD (HL),' ' ; fill remaining bytes with + INC HL + DJNZ SY_CMD4 +SY_CMD5: JP M1SYS ; loop, display menu + + ; --- option 3 Timer Reload Value +SY_TMR: CP '3' ; option 3 selected ? + JR NZ,SY_PRC ; ..if not, jump to next + CALL CRLF +SY_TMR1: CALL VPRINT + DEFB CR,TAB,TAB,'Timer Reload Value',TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD A,9FH ; offset to RELOD0 in Config area + CALL WSPCPTR ; set ptr + LD E,(HL) ; get low-byte of 16-bit value + INC HL + LD D,(HL) ; ..and high-byte + PUSH HL ; save ptr + EX DE,HL ; swap regs + CALL PHLDCNV ; display value and ask for input + POP HL ; restore ptr + JR NC,SY_TMR2 ; ..if input is valid, skip over + CALL CFEVAL ; eval script file input + JR SY_TMR1 ; loop (ask for input) +SY_TMR2: LD (HL),D ; store high-byte of new value + DEC HL ; move ptr back + LD (HL),E ; ..and low-byte + JR SY_CMD5 ; jump to display menu again + ; (use of two consecutive JR's saves one byte) + + + ; --- option 4 Processor Speed +SY_PRC: CP '4' ; was option 4 selected ? + JP NZ,SY_WT ; ..if not, jump to next + CALL CRLF +SY_PRC1: CALL VPRINT + DEFB CR,TAB,TAB,'Processor Speed in MHz',TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD A,9DH ; offset to SPEED in Config area + CALL WSPCPTR ; set ptr + LD E,(HL) ; get Processor Speed + LD D,0 + PUSH HL ; save ptr + EX DE,HL ; swap regs + CALL PHLDCNV ; display value and ask for input + POP HL ; restore ptr + JR C,SY_PRC2 ; ..if input is invalid, jump + LD A,D ; else, evaluated input in DE + OR A ; high-byte must be zero + JR Z,SY_PRC3 ; ..if zero, jump to continue +SY_PRC2: CALL CFEVAL ; eval script file input + JR SY_PRC1 ; loop (ask for input) +SY_PRC3: LD D,(HL) ; get new Processor Speed + LD (HL),E ; ..and store value + PUSH DE ; also save it + CALL VPRINT + DEFB CR,LF,TAB,TAB,' Scale Timer Constant?',TAB,'([Y]/N) : ' + DEFB 0 + CALL GETINP ; get input + CP 'N' ; entered 'N' ? + POP DE + JP Z,M1SYS ; ..if so, exit and display menu again + LD A,9FH ; offset to RELOD0 in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get low-byte of 16-bit value + INC HL + LD H,(HL) ; ..and high-byte + LD L,A ; HL= constant for counter/timer refresh + LD C,D ; Processor Speed in C + LD B,0 ; prepare BC as divisor + INC C ; check if Processor Speed = 0 + DEC C + JP Z,M1SYS ; ..if so, exit and display menu + PUSH DE ; else, save Processor Speed + LD DE,0 ; DE is quotient + OR A ; clear Flags +SY_PRC4: SBC HL,BC ; division by subtraction + JR C,SY_PRC5 ; ..if below zero, exit loop + INC DE ; increase counter (quotient) + JR SY_PRC4 ; and loop +SY_PRC5: POP BC ; restore Processor Speed in BC + LD HL,0 ; set initial value +SY_PRC6: ADD HL,DE ; multiply by addition + DEC C ; decrease counter + JR NZ,SY_PRC6 ; ..loop till done + EX DE,HL ; swap regs (DE= new RELOD0 value) + LD A,9FH ; offset to RELOD0 in Config area + CALL WSPCPTR ; set ptr + INC HL ; move ptr fwed + JP SY_TMR2 ; ..and re-use code to store value in DE + + ; --- option 5 Memory Waits +SY_WT: CP '6' ; option 6 selected ? + JP Z,M11ASK ; ..if so, jump to continue + CALL CRLF ; else, must be config of waits +SY_WT1: CALL VPRINT + DEFB CR,TAB,TAB,'Number of Memory Waits',TAB,'[' + DEFB 0 + CALL EREOL + LD A,9EH ; offset to WAITS in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get value + RRCA ; shift upper nybble to lower + RRCA ; WAITS combines Mem (bits 7-4) + RRCA ; and IO (bits 3-0) wait states + RRCA + AND 00001111B ; mask off higher nybble + LD L,A ; Mem wait states in HL + LD H,0 + CALL PHLDCNV ; display value and ask for input + JR C,SY_WT2 ; ..if input is not valid, jump + LD A,D ; evaluated input in DE + OR A ; high-byte must be zero + JR NZ,SY_WT2 ; ..if not, jump + LD A,E + CP 00010000B ; check if value exceeds limit + JR C,SY_WT3 ; ..if not, skip over +SY_WT2: CALL CFEVAL ; eval script file input + JR SY_WT1 ; loop (ask for new input) +SY_WT3: RLCA ; move new value to high nybble + RLCA + RLCA + RLCA + LD C,A ; ..and remember it + CALL CRLF +SY_WT4: CALL VPRINT ; now IO waits + DEFB CR,TAB,TAB,'Number of IO Waits',TAB,'[' + DEFB 0 + CALL EREOL + LD A,9EH ; offset to WAITS in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get value + PUSH HL ; save ptr + AND 00001111B ; mask off high nybble (bits 3-0 = IO waits) + LD L,A ; get value in HL + LD H,0 + CALL PHLDCNV ; display value and ask for input + POP HL ; restore ptr + JR C,SY_WT5 ; ..if input not valid, jump + LD A,D ; evaluated input in DE + OR A ; high-byte must be zero + JR NZ,SY_WT5 ; ..if not, jump + LD A,E + CP 00010000B ; check if value exceeds limit + JR C,SY_WT6 ; ..if not, skip over +SY_WT5: CALL CFEVAL ; eval script file input + JR SY_WT4 ; loop (ask for new input) +SY_WT6: OR C ; combine values (C= Mem waits, A= IO waits) + LD (HL),A ; store new value + JP M1SYS ; ..loop, display menu + + ; * + + + ; --- option 6 System Banks (hidden menu 1.1) +M11ASK: CALL VPRINT ; ask for confirmation before entering menu + DEFB CR,LF,TAB,'-- This is DANGEROUS...Proceed? (Y/[N]) : ' + DEFB 0 + CALL GETINP ; get input + CP 'Y' ; entered 'Y' ? + JP NZ,M1SYS ; ..if not, jump display main menu again + ; else, fall through + + +;::::: MENU 1.1 - SYSTEM BANK NUMBERS (display) + + +M11BNK: CALL CLS + CALL VPRINT + DEFB CR,LF,'Menu 1.1 - System Bank Numbers' + DEFB CR,LF,LF,LF,' ',1,' 1 ',2,' TPA Bank # = ' + DEFB 0 + LD A,82H ; offset to TPABANK in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get TPABANK # + CALL PAFDC ; ..display as decimal + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 2 ',2,' System Bank # = ' + DEFB 0 + LD A,83H ; offset to SYSBNK in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get SYSBNK # + CALL PAFDC ; ..and display + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 3 ',2,' User Bank # = ' + DEFB 0 + LD A,81H ; offset to UABNK in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get UABNK # + CALL PAFDC ; ..and display + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 4 ',2,' RAM Drive Bank # = ' + DEFB 0 + LD A,84H ; offset to RAMBNK in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get RAMBNK # + CALL PAFDC ; ..and display + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 5 ',2,' Maximum Bank # = ' + DEFB 0 + LD A,85H ; offset to MAXBNK in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get MAXBNK # + CALL PAFDC ; ..and display + LD A,'5' ; max. possible option in this menu as ascii number + CALL MSELECT + OR A ; valid option selected ? + JP Z,M1SYS ; ..if not, jump to display system menu + ; else, fall through + + +;::::: MENU 1.1 - SYSTEM BANKS (configure) + +M11CFG: CALL CRLF + SUB '1' ; convert input (ascii) to zero-based index + LD HL,BKOTBL ; ptr lookup table of offset values + CALL ADDHLA ; adjust ptr + LD A,(HL) ; ..and get offset + CALL SB_BNK ; configure + JP M11BNK ; loop, display menu + + ; Lookup table for offsets in config area + ; to the different RAM banks +BKOTBL: DEFB 82H ; TPABNK + DEFB 83H ; SYSBNK + DEFB 81H ; UABNK + DEFB 84H ; RAMBNK + DEFB 85H ; MAXBNK + + + ; --- configure System Banks +SB_BNK: LD (SELBNK),A ; store offset +SB_BNK1: CALL VPRINT + DEFB CR,TAB,' Enter Bank Number',TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD A,(SELBNK) ; get offset value for selected RAM bank + CALL WSPCPTR ; ..and set ptr in WSPC + LD E,(HL) ; bank # + LD D,0 + PUSH HL ; save ptr + EX DE,HL ; swap regs + CALL PHLDCNV ; display value and ask for input + POP HL ; restore ptr + JR C,SB_BNK1 ; ..if input not value, loop + LD A,D ; evaluated number in DE + OR A ; high-byte must be zero + JR NZ,SB_BNK1 ; ..if not, loop ask for new input + LD (HL),E ; else, store new value + RET + + ; * + + +;::::: MENU 2 - CHARACTER I/O (display) + + +M2CIO: LD A,1 + LD (CFMENU),A ; store flag (sub-)menu entered + CALL CLS + CALL VPRINT + DEFB CR,LF,'Menu 2 - Character IO Options' + DEFB CR,LF,LF,LF,' ',1,' 1 ',2,' IOBYTE Assignment:' + DEFB CR,LF,TAB,TAB,'Console = ' + DEFB 0 + LD A,7EH ; offset IOBYT in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get IO Byte + PUSH AF ; ..and save + CALL PIOASSG ; display name of assigned device + CALL VPRINT + DEFB CR,LF,TAB,TAB,'Auxiliary = ' + DEFB 0 + POP AF ; restore IOBYT + PUSH AF + RRCA ; shift bits 3-2 to position 1-0 + RRCA + CALL PIOASSG ; display name of assigned device + CALL VPRINT + DEFB CR,LF,TAB,TAB,'Printer = ' + DEFB 0 + POP AF ; restore IOBYT + RLCA ; ..and shift bits 7-6 to pos 1-0 (other direction) + RLCA + CALL PIOASSG ; display name of assigned device + XOR A ; nullify A + LD (DEVASSG),A ; clear temp data storage +M2CIO1: CALL IO_PTR ; ptr to DEVCFG table + LD A,(HL) ; get byte + OR A ; is it ? + JR Z,M2CFG ; ..if so, exit loop + LD (DEVTBL),HL ; else, save addr + LD A,(DEVASSG) + INC A ; counter +1 + LD (DEVASSG),A ; ..store + CP 6 ; display additional for first five devices + CALL C,CRLF + CALL VPRINT + DEFB CR,LF,' ',1,' ' + DEFB 0 + LD A,(DEVASSG) + ADD A,'1' ; convert number to ascii + CALL COUT ; ..display + CALL VPRINT + DEFB ' ',2,' ' + DEFB 0 + LD HL,(DEVTBL) ; ptr to DEVCFG (Char IO device table) + CALL PIOPARM ; display parameters + JR M2CIO1 ; ..loop + + +;::::: MENU 2 - CHARACTER I/O (configure) + + ; subsequent labels start with "IO_" +M2CFG: LD A,(DEVASSG) ; get last device # + ADD A,'1' ; convert to ascii + LD (DEVLAST),A ; ..and store it (later used as max. option in this menu) + LD A,(BPVERS) ; get B/P Bios version + CP 20H ; less than 2.0 ? + LD A,(DEVLAST) + JR C,IO_ASS ; ..if <2.0, swap devices not possible + CALL VPRINT + DEFB CR,LF,LF,' ',1,' ' + DEFB 0 + LD A,(DEVASSG) ; get last device # (num) + ADD A,'2' ; ..convert to ascii +1 (adjust for menu option) + CALL COUT + CALL VPRINT + DEFB ' ',2,' Swap Devices' + DEFB 0 + LD A,(DEVLAST) ; get last device # (ascii) + INC A ; make max. possible option in this menu as ascii number + + ; --- configure IO Device Assignment (IOBYT) +IO_ASS: CALL MSELECT + OR A ; input not valid ? + JP Z,M0MAIN ; ..if so, jump to main menu + CP '1' ; else, option 1 selected ? + JP NZ,IO_SWP ; ..if not, jump to next + CALL VPRINT + DEFB CR,LF,TAB,'Set [C]onsole, [A]uxiliary, or [P]rinter : ' + DEFB 0 +IO_ASS1: CALL CAPINE ; get input + CP CR ; is it ? + JP Z,M2CIO ; ..if so, display menu 2 again + CP 'C' ; assign (C)onsole ? + JR NZ,IO_ASS2 ; ..if not, jump + CALL CIOASSG ; configure CON IO Dev Assignment + JP C,M2CIO ; ..if error, display menu again + LD C,11111100B ; set bit mask + JR IO_ASS5 ; ..and finish +IO_ASS2: CP 'A' ; assign (A)uxiliary ? + JR NZ,IO_ASS3 ; ..if not, jump + CALL CIOASSG ; configure AUX IO Dev Assignment + JP C,M2CIO ; ..if error, display menu again + RLC B ; device number in B + RLC B ; ..shift bits to position 3-2 + LD A,B ; copy to bits 5-4 by multiplication + ADD A,A ; *2 + ADD A,A ; *4 + ADD A,B ; *5 + LD B,A ; B= AUX Out (bits 5-4) and In (bits 3-2) + LD C,11000011B ; set bit mask + JR IO_ASS5 ; ..and finish +IO_ASS3: CP 'P' ; assign (P)rinter ? + JR Z,IO_ASS4 ; ..if so, jump + CP ' ' ; else, entered ? + JP Z,M2CIO ; ..then display menu again + CP ESC ; or ? + JP Z,M2CIO ; ..then also display menu again + CALL CFEVAL ; eval script file input + CALL VPRINT ; notify user, and loop + DEFB BEL,BS + DEFB 0 + JR IO_ASS1 +IO_ASS4: CALL CIOASSG ; configure PRT IO Dev Assignment + JP C,M2CIO ; ..if error, display menu again + RRC B ; device in B + RRC B ; shift bits from pos 1-0 to 7-6 + LD C,00111111B ; set bit mask + ; ..and fall through + + ; set new IO Dev Assignment +IO_ASS5: LD A,7EH ; offset to IOBYT in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get IOBYT + AND C ; apply bit mask + OR B ; combine with new assignment + LD (HL),A ; ..and store back + JP M2CIO ; loop display menu + + ; --- Swap Device Assignment +IO_SWP: PUSH AF + LD A,(DEVLAST) ; get last device # (ascii) + INC A ; increase + LD C,A ; this menu option is created dynamically + POP AF + CP C ; so check if selection matches + JP NZ,IO_CFG ; ..if not, jump + CALL VPRINT + DEFB CR,LF,TAB,'Swap [2..' + DEFB 0 + LD A,(DEVLAST) ; get last device # (ascii) + CALL COUT ; ..display + CALL VPRINT + DEFB '] : ' + DEFB 0 +IO_SWP1: CALL GETINP ; get input + JP Z,M2CIO ; ..if empty, jump display menu again + CP '2' ; entered value below '2' ? + JR C,IO_SWP2 ; ..if so, jump and loop + LD HL,DEVLAST + DEC A + CP (HL) ; else, also check above max. + JR C,IO_SWP3 ; ..if not, jump to continue + ; else, fall through and loop +IO_SWP2: CALL VPRINT ; notify user (), and remove char () + DEFB BS,BEL + DEFB 0 + CALL CFEVAL ; eval script file input + JR IO_SWP1 ; loop (ask for new input) +IO_SWP3: SUB '1' ; convert ascii to number (already reduced by 1 before) + LD (DEV1SWP),A ; ..store it + CALL VPRINT + DEFB ' with [2..' + DEFB 0 + LD A,(DEVLAST) ; get ascii number of last device + CALL COUT ; ..and display it + CALL VPRINT + DEFB '] : ' + DEFB 0 +IO_SWP4: CALL GETINP ; get input + JP Z,M2CIO ; ..if empty, jump display menu again + CP '2' ; check if input is below '2' + JR C,IO_SWP5 ; ..if so, jump and loop + LD HL,DEVLAST + DEC A + CP (HL) ; else, check if input is above max. + JR C,IO_SWP6 ; ..if not, jump + ; else, fall through and loop +IO_SWP5: CALL VPRINT ; remove char () and notify user () + DEFB BS,BEL + DEFB 0 + CALL CFEVAL ; eval script file input + JR IO_SWP4 ; loop (ask for new input) +IO_SWP6: SUB '1' ; convert ascii to number (already reduced by 1, so only -'1') + LD (DEVASSG),A ; ..and store + CALL IO_PTR ; get ptr to entry in DEVCFG + PUSH HL ; save + LD A,(DEV1SWP) ; get device to swap + LD (DEVASSG),A ; ..and store + CALL IO_PTR ; get ptr to entry in DEVCFG + POP DE ; restore 1st ptr + LD B,16 ; length of an entry in DEVCFG + ; (swap is only displayed for version above 2.0 + ; no additional check/adjustment of length needed) + + ; perform device swapping (copy bytes from one entry to the other) +IO_SWP7: LD C,(HL) ; get byte from entry #1 + LD A,(DE) ; get byte from entry #2 + EX DE,HL ; swap regs (ie. ptr's) + LD (DE),A ; save bytes to other entry + LD (HL),C + EX DE,HL ; ..swap pointers back + INC HL ; move fwd + INC DE + DJNZ IO_SWP7 ; loop till done + JP M2CIO ; finally, jump to display menu again + + + ; --- Configure Char IO Device + ; menu option entries are created dynamically according to existing devices + ; A= selected option ('1' is fixed, so devices start with '2') +IO_CFG: SUB '2' ; convert selected option to device # (num) + LD (DEVASSG),A ; ..store + CALL IO_PTR ; display, and get ptr in DEVCFG + PUSH HL ; move ptr to IX + POP IX + LD A,(HL) ; check if entry is valid (<> zero) + OR A + JR NZ,IO_CFG1 ; ..if so, jump to continue + CALL VPRINT ; else, display msg and loop + DEFB BEL,CR,LF,'-- Nothing There !! --' + DEFB 0 + CALL CFEVAL ; eval script file input + JP M2CIO ; loop, display Char IO menu again + + + ; IX= ptr to first byte of entry in DEVCFG table + ; +4 baud rate, +5 data transmission, +6 input data mask, +7 output data mask +IO_CFG1: CALL VPRINT + DEFB CR,LF,TAB,'Configuring ' + DEFB 0 + CALL P4CHRS ; display name of device + LD A,' ' ; and + CALL COUT + CALL PIOIO ; display In/Out configuration of device + LD A,':' ; and colon + CALL COUT + + ; configure baud rate + LD A,(IX+4) ; get baud rate + AND 11110000B ; check high nybble (capabilities) + JP Z,IO_FLW ; ..if none, jump + CALL VPRINT ; else, continue displaying + DEFB CR,LF,TAB,' Baud Rate ' + DEFB 0 + LD A,(IX+4) ; get baud rate + CPL ; complement + AND 11110000B ; check high nybble (capabilities) + JR Z,IO_BDR ; ..if zero, skip option 'Max' + CALL VPRINT + DEFB ' (Max=' + DEFB 0 + LD A,(IX+4) ; get baud rate + RRCA ; move high nybble to lower + RRCA + RRCA + RRCA + AND 00001111B ; mask off high nybble + LD (BAUDRT),A ; ..store value + CALL PIOBDRT ; and display it + CALL VPRINT + DEFB ') = ' + DEFB 0 +IO_BDR: CALL VPRINT + DEFB ' Selections are:' + DEFB 0 + LD A,1 ; set initial value + PUSH AF +IO_BDR1: DEC A ; insert + AND 3 ; after output of 4 values + JR NZ,IO_BDR2 + CALL VPRINT + DEFB CR,LF,TAB + DEFB 0 +IO_BDR2: LD A,TAB ; print + CALL COUT + POP AF ; restore counter + PUSH AF + CALL PAFDC ; display value + LD A,'-' + CALL COUT + POP AF ; restore counter again + PUSH AF + CALL PIOBDRT ; ..and display corresponding baud rate + POP AF + PUSH AF + LD HL,BAUDRT ; get value for max. baud rate + CP (HL) ; check if reached + JR NC,IO_BDR3 ; ..if so, exit loop + POP AF ; else, restore counter + INC A ; +1 + PUSH AF ; ..save again + JR IO_BDR1 ; loop +IO_BDR3: CALL CRLF +IO_BDR4: CALL VPRINT + DEFB CR,TAB,' Select',TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD A,(IX+4) ; get current baud rate + AND 00001111B ; mask off high nybble + LD L,A ; value in HL + LD H,0 + CALL PHLDCNV ; display and ask for input + JR C,IO_BDR5 ; ..if input is not valid, jump + LD A,D ; evaluated number in DE + OR A ; high-byte must be zero + JR NZ,IO_BDR5 ; ..if not, jump + LD A,E ; check if low-byte is zero + OR A + JR Z,IO_BDR5 ; ..if so, jump + DEC A ; make zero-based + LD HL,BAUDRT ; get value for max. baud rate + CP (HL) ; check if new value exceeds limit + JR C,IO_BDR6 ; ..if not, continue +IO_BDR5: CALL CFEVAL ; eval script file input + JR IO_BDR4 ; loop (ask for new input) +IO_BDR6: LD A,(IX+4) ; get current baud rate settings + AND 11110000B ; mask off low nybble + OR E ; combine with new value + LD (IX+4),A ; ..and store + + ; configure data bits + CALL VPRINT + DEFB CR,LF,TAB,' Data = ' + DEFB 0 + LD A,(IX+5) ; get Config Byte data transmission + CPL ; complement + BIT 3,A ; ..and test bit 3 (data bits) + CALL M$87BIT ; display # of bits and ask for change + JR NZ,IO_STP ; ..if no change, jump + LD A,00001000B ; else, mask bit 4 + XOR (IX+5) ; invert current state + LD (IX+5),A ; ..and save back + + ; configure stop bits +IO_STP: CALL VPRINT + DEFB CR,LF,TAB,' Stop Bits = ' + DEFB 0 + BIT 0,(IX+5) ; test bit 0 for stop bits (0= 2, 1= 1) + LD A,'1' ; prepare for '1' + JR NZ,IO_STP1 ; ..if not set, skip over + INC A ; else, increase to '2' +IO_STP1: CALL COUT ; display current setting + CALL M$BITS ; display string and ask for change + JR NZ,IO_PTY ; ..if no change, jump + LD A,00000001B ; else, mask bit 0 + XOR (IX+5) ; invert current state + LD (IX+5),A ; ..and save back + + ; configure parity +IO_PTY: CALL VPRINT + DEFB CR,LF,TAB,' Parity = ' + DEFB 0 + LD HL,PRTY$4 ; prepare ptr to string "None" + BIT 1,(IX+5) ; test bit 1 for Parity (0= no, 1= enabled) + JR Z,IO_PTY1 ; ..if not enabled, jump + LD HL,PRTY$2 ; else point to string "Odd" + BIT 2,(IX+5) ; test bit 2 for Parity (0= odd, 1= even) + JR Z,IO_PTY1 ; ..if odd, skip over + LD HL,PRTY$1 ; else, point to string "Even" +IO_PTY1: CALL VPSTR ; display string (ptr in HL) + CALL M$CHNG ; ask for change + JR NZ,IO_FLW ; ..if no change, jump + CALL VPRINT + DEFB CR,LF,TAB,TAB,'Enable Parity' + DEFB 0 + CALL ASKYN ; ask Yes (Z) / No (NZ) + RES 1,(IX+5) ; reset bit + JR NZ,IO_FLW ; ..if 'N' was entered, jump + SET 1,(IX+5) ; else, set bit and continue + CALL VPRINT + DEFB CR,LF,TAB,TAB,'Odd or Even? (O/[E]) : ' + DEFB 0 + CALL GETINP ; get input + SET 2,(IX+5) ; set bit (even) + CP 'O' ; check if 'O' was entered + JR NZ,IO_FLW ; ..if not, skip over + RES 2,(IX+5) ; else, reset bit (odd) and fall through + + ; configure flow control +IO_FLW: CALL VPRINT ; display output + DEFB CR,LF,TAB,' XON/XOFF Flow = ' + DEFB 0 + BIT 4,(IX+5) ; test bit 4 XON/XOFF (0= no, 1= yes) in Config. Byte + CALL PNOYES ; display No/Yes accordingly + CALL M$CHNG ; ..and ask if it shall be changed + JR NZ,IO_FLW1 ; ..if not 'Y', skip + LD A,00010000B ; else, take bit 4 + XOR (IX+5) ; ..invert it + LD (IX+5),A ; ..and write back +IO_FLW1: CALL VPRINT + DEFB CR,LF,TAB,' RTS/CTS Flow = ' + DEFB 0 + BIT 5,(IX+5) ; test bit 5 CTS/RTS control (0= no, 1= enabled) + CALL PNOYES ; display No/Yes accordingly + CALL M$CHNG ; ..and ask if it shall be changed + JR NZ,IO_MSK ; ..if not 'Y', skip + LD A,00100000B ; else, take bit 5 + XOR (IX+5) ; ..invert it + LD (IX+5),A ; ..and write back + + ; configure in/out and data masks +IO_MSK: LD A,(IX+5) ; get Config. Byte + AND 11000000B ; mask high bits + JR Z,IO_NONE ; ..if zero, exit (no input, no output) + BIT 6,(IX+5) ; test bit 6 Input (0= no, 1= dev can be read) Config. Byte + JR Z,IO_MSK1 ; ..if no Input, jump to output settings + CALL VPRINT ; else, display + DEFB CR,LF,TAB,' Input is ' + DEFB 0 + BIT 7,(IX+6) ; test bit 7 of data mask + CALL M$87BIT ; display # of bits and ask for change + JR NZ,IO_MSK1 ; ..if not 'Y', skip + LD A,10000000B ; else, take bit 7 + XOR (IX+6) ; ..invert it + LD (IX+6),A ; ..and write back +IO_MSK1: BIT 7,(IX+5) ; test bit 7 Output (0= no, 1= can write dev) Config. Byte + JR Z,IO_EXIT ; ..if no Output, jump exit + CALL VPRINT ; else, display + DEFB CR,LF,TAB,' Output is ' + DEFB 0 + BIT 7,(IX+7) ; test bit 7 of data mask + CALL M$87BIT ; display # of bits and ask for change + JR NZ,IO_EXIT ; ..if not 'Y', exit + LD A,10000000B ; else, take bit 7 + XOR (IX+7) ; ..invert it + LD (IX+7),A ; ..and write back + JR IO_EXIT ; then exit to display menu again + + ; nothing configurable +IO_NONE: CALL VPRINT + DEFB CR,LF,TAB,' -- Nothing Configurable...' + DEFB '[any key to continue] --' + DEFB 0 + CALL CFIN +IO_EXIT: JP M2CIO ; display menu again + + +;::::: SUPPORT FUNCTIONS - Char IO Device Config. + + ; get ptr to entry in DEVCFG + ; (length of an entry is 16 bytes, or 8 bytes prior to B/P Bios v1.1) + ; in: variable DEVASSG, bits 1-0 + ; out: HL= ptr to entry +IO_PTR: LD A,(BPVERS) ; check B/P Bios version + LD C,8 ; length of an entry + CP 11H ; is version prior to 1.1 ? + JR C,IO_PTR1 ; ..if so, jump + LD C,16 ; else, set length of entry to 16 byte +IO_PTR1: LD A,(DEVASSG) ; assignment bits 1-0 (from IOBYT) + LD B,A ; copy to B as counter + OR A ; is it zero ? + JR Z,IO_PTR3 ; ..if so, no more calculation + XOR A ; else, clear A +IO_PTR2: ADD A,C ; add length of an entry + DJNZ IO_PTR2 ; ..and loop +IO_PTR3: LD E,A ; offset into E + LD A,0DBH ; DEVCFG offset (after Config area) + CALL WSPCPTR ; calc ptr to DEVCFG + LD D,0 + ADD HL,DE ; add offset (ptr to first byte of entry) + RET + + + ; prints "No" or "Yes" to CON: + ; in: Z-Flag set= No, NZ= Yes +PNOYES: LD HL,PRTY$3 ; ptr to string "No" + JR Z,PNOYES0 ; ..if Z-Flag set, skip over + LD HL,PRTY$5 ; else, ptr to string "Yes" +PNOYES0: JP VPSTR ; display string, and let return from there + + + ; print name of assigned device + ; mask off upper bits, get ptr to assigned device in DEVCFG table + ; in: A= device (bits shifted from IOBYT to position 1-0) + ; out: HL= ptr to baud rate + ; dev assignment stored in DEVASSG +PIOASSG: AND 00000011B ; mask off upper bits 7-2 + LD (DEVASSG),A ; store encoded device assignment + PUSH DE + CALL IO_PTR ; HL= ptr to entry in DEVCFG + POP DE + LD B,4 ; name consists of 4 chars +PIOASS1: LD A,(HL) ; get char + CALL COUT ; ..display + INC HL ; move ptr fwd + DJNZ PIOASS1 ; loop till done + RET + + + ; configure IO Device assignment, display current setting and ask for input + ; out: A= new device number, B= A (copy) + ; C-Flag set if error (no input), NC ok +CIOASSG: CALL VPRINT + DEFB CR,LF,TAB,' Set ' + DEFB 0 + XOR A ; clear A + LD (DEVASSG),A ; ..and stored assignment +CIOASS1: CALL PIOASSG ; display device name (starting with COM1) + LD A,'[' + CALL COUT + LD A,(DEVASSG) ; get device number + INC A ; ..increase it + LD (DEVASSG),A + ADD A,'0' ; convert to ascii for display + CP '4' ; maximum reached ? + PUSH AF ; save regs + CALL COUT + LD A,']' + CALL COUT + POP AF + PUSH AF + LD A,',' + CALL C,COUT + LD A,' ' + CALL COUT + POP AF ; restore flags + JR C,CIOASS1 ; ..loop till done + CALL VPRINT + DEFB '? ' + DEFB 0 +CIOASS2: CALL GETINP ; get input + SCF ; set C-Flag (error) + RET Z ; ..if input is empty, return + SUB '1' ; else, convert ascii to number + LD B,A + JR C,CIOASS3 ; ..if input below '1', jump/loop + CP 4 ; check for max. device number + CCF ; invers C-Flag + RET NC ; if input '1' to '4', return with C-Flag cleared + ; ..else, fall through and loop + +CIOASS3: CALL VPRINT ; notify user (), remove char (), and ask for new input + DEFB BS,BEL + DEFB 0 + JR CIOASS2 + + + ; display parameters of Char IO Device on CON: + ; in: HL= ptr to first byte of entry in DEVCFG +PIOPARM: PUSH HL ; move ptr to IX + POP IX + LD A,(HL) + OR A ; check entry + JR NZ,PIOPAR1 ; ..if not empty, jump to continue + CALL VPRINT ; else, display msg and return + DEFB '-- Unavailable --' + DEFB 0 + RET + + ; device is valid, display name and baud rate +PIOPAR1: CALL P4CHRS ; display name of device + CALL VPRINT + DEFB ' - ' + DEFB 0 + EX DE,HL ; swap regs, DE= ptr first byte after name + LD A,(DE) ; get baud rate + INC DE ; move ptr fwd + CP 00010000B ; is a max. baud rate set ? (upper nybble) + JR C,PIOIO ; ..if so, jump + DEC DE ; else, move ptr back + CALL PIOBDRT + CALL VPRINT + DEFB ', ' + DEFB 0 + EX DE,HL ; swap regs + INC HL ; move ptr to config. byte for data transmission + LD A,'8' ; prepare to display '8' + BIT 3,(HL) ; check # of data bits (0= 8 bit data, 1= 7 bit data) + JR Z,PIOPAR2 ; ..if 8 bits, skip + DEC A ; else, adjust A + + ; display number of data bits +PIOPAR2: EX DE,HL ; swap regs + CALL COUT ; print char in A + CALL VPRINT + DEFB ' Data, ' + DEFB 0 + LD A,(DE) ; get config. byte for data transmission + BIT 0,A ; check # of stop bits (0= 2, 1= 1) + LD A,'1' ; prpare to display '1' + JR NZ,PIOPAR3 ; ..if 1 stop bit, skip + LD A,'2' ; else, adjust A + + ; display number of stop bits +PIOPAR3: CALL COUT ; print char in A + CALL VPRINT + DEFB ' Stop, ' + DEFB 0 + LD A,(DE) ; get config. byte for data transmission + LD HL,PRTY$3 ; ptr to string "No" + BIT 1,A ; check parity (0= no parity, 1= enabled) + JR Z,PIOPAR4 ; ..if no parity, jump to output + LD HL,PRTY$1 ; else, set ptr to string "Even" + BIT 2,A ; check parity setting (0= odd, 1= even) + JR NZ,PIOPAR4 ; ..if even, jump to output + LD HL,PRTY$2 ; else, set ptr to "Odd" + + ; display parity +PIOPAR4: CALL VPSTR ; display string, HL is ptr + CALL VPRINT + DEFB ' Parity, ' + DEFB 0 + + ; display Char IO Device In/Out settings on CON: + ; in: IX= ptr to first byte of an entry in DEVCFG +PIOIO: LD A,'[' ; print left bracket + CALL COUT + BIT 6,(IX+5) ; check Input setting (0= no input, 1= dev can be read) + ; IX+5 points to config. byte for data transmission + JR Z,PIOIO2 ; ..if no Input, jump + CALL VPRINT ; else, display + DEFB 'In' + DEFB 0 + LD A,'(' ; print left parenthesis + CALL COUT + BIT 7,(IX+6) ; check Input data mask (IX+6 points to mask byte) + LD A,'7' ; prepare to display '7' + JR Z,PIOIO1 ; ..if high bit not set, skip + INC A ; else, adjust A +PIOIO1: CALL COUT ; ..and display char in A + LD A,')' ; and display closing parenthesis + CALL COUT + LD A,(IX+5) ; get config. byte for data transmission + AND 11000000B ; mask high bits (7 Input, 8 Output) + CP 11000000B + JR NZ,PIOIO2 ; ..if not both bits are set, skip + LD A,'/' ; else, display '/' as separator + CALL COUT + +PIOIO2: BIT 7,(IX+5) ; check Output setting (0= no output, 1= can write dev) + ; IX+5 points to config. byte for data transmission + JR Z,PIOIO4 ; ..if no Output, jump + CALL VPRINT ; else, display + DEFB 'Out' + DEFB 0 + LD A,'(' ; print left parenthesis + CALL COUT + BIT 7,(IX+7) ; check Output data mask (IX+7 points to mask byte) + LD A,'7' ; prepare to display '7' + JR Z,PIOIO3 ; ..if high bit not set, skip + INC A ; else, adjust A +PIOIO3: CALL COUT ; display char in A + LD A,')' ; ..and closing parenthesis + CALL COUT +PIOIO4: LD A,']' ; print right bracket + JP COUT ; ..and let return from there + + ; parity options + ; nul-terminated strings +PRTY$1: DEFB 'Even',0 +PRTY$2: DEFB 'Odd',0 +PRTY$3: DEFB 'No',0 +PRTY$4: DEFB 'None',0 +PRTY$5: DEFB 'Yes',0 + + + ; print four chars (ptr in HL), used to display name of Char IO Device + ; in: HL= ptr to first byte of entry in DEVCFG (name) + ; IX= HL (not used in this routine) +P4CHRS: LD B,4 ; number of chars +P4CHR1: LD A,(HL) ; get char + INC HL ; move ptr fwd + CALL COUT ; send char in A to CON: + DJNZ P4CHR1 ; ..loop till done + RET + + + ; displays the baud rate on CON: + ; in: A= data rate setting + ; IX= ptr to first byte of an entry in DEVCFG +PIOBDRT: AND 00001111B ; mask lower nybble + LD HL,BDRT$1 ; ptr to 1st string + CP 00001110B ; check special cases + JR NC,PIOBDR1 + LD HL,BDRT$2 ; ptr to 2nd string + CP 00000001B + JR Z,PIOBDR1 + LD HL,BDRT$3 ; followings strings are 5 bytes long + SUB 2 ; calc offset, account for 2 special cases + LD B,A + ADD A,A ; *2 + ADD A,A ; *4 + ADD A,B ; *5 + CALL ADDHLA ; add offset + LD A,B + CP 9 ; check for entry number + JR C,PIOBDR1 ; ..and display "kpbs" or "bps" + CALL VPSTR ; print string, ptr in HL + CALL VPRINT + DEFB ' kbps' + DEFB 0 + JR PIOBDR2 +PIOBDR1: CALL VPSTR ; print string, ptr in HL + CALL VPRINT + DEFB ' bps' + DEFB 0 +PIOBDR2: LD A,(IX+4) ; get 'Data Rate Capabilities' byte in DEVCFG entry + AND 11110000B ; mask upper nybble + CP 11110000B ; all upper bits set ? + RET NZ ; ..if not, return + CALL VPRINT ; else, append string and then return + DEFB ' (fixed)' + DEFB 0 + RET + + ; baud rate options + ; nul-terminated strings, from BDRT$3 onwards = table w/ 5-byte entries + ; data rate is represented by upper/lower nybble +BDRT$1: DEFB '115.2',0 ; 1110 = 115200 +BDRT$2: DEFB '134.5',0 ; 0001 = 134.5 +BDRT$3: DEFB '50',0,0,0 ; 0010 = 50 + DEFB '75',0,0,0 ; 0011 = 75 + DEFB '150',0,0 ; 0100 = 150 + DEFB '300',0,0 ; 0101 = 300 + DEFB '600',0,0 ; 0110 = 600 + DEFB '1200',0 ; 0111 = 1200 + DEFB '2400',0 ; 1000 = 2400 + DEFB '4800',0 ; 1001 = 4800 + DEFB '9600',0 ; 1010 = 9600 + DEFB '19.2',0 ; 1011 = 19200 + DEFB '38.4',0 ; 1100 = 38400 + DEFB '76.8',0 ; 1101 = 76800 + DEFB '(fixed)',0 ; 1111 = Fixed + + + ; display '8' or '7' then fall through fo following msg's and get input + ; in: Z-Flag set= '7', NZ= '8' + ; out: Z-Flag set for 'Y' entered, else NZ +M$87BIT: LD A,'8' ; prepare to display '8' + JR NZ,M$87BI1 ; ..if Z-Flag cleared, display + DEC A ; else, adjust A +M$87BI1: CALL COUT ; print char in A + ; ..and fall through + + ; msg '-bits.' +M$BITS: CALL VPRINT ; display and fall through + DEFB '-bits.' + DEFB 0 + + ; msg 'Change' +M$CHNG: CALL VPRINT ; display and fall through + DEFB TAB,'Change' + DEFB 0 + + + ; ask for user input Y/[N] + ; out: Z-Flag set if 'Y' was entered, else NZ +ASKYN: CALL VPRINT ; display + DEFB '? (Y/[N]) : ' + DEFB 0 + CALL GETINP ; get input + CP 'Y' ; check if 'Y' was entered + RET ; ..and return, Z-Flag is set accordingly + + ; * + + +;::::: MENU 3 - FLOPPY DISK (display) + +M3FD: LD A,1 + LD (CFMENU),A ; store flag (sub-)menu entered + CALL CLS + CALL VPRINT + DEFB CR,LF,'Menu 3 - Floppy Disk Options' + DEFB CR,LF,LF,LF,' ',1,' 1 ',2,' Floppy Drive Characteristics:' + DEFB CR,LF,TAB,'Drv0 = ' + DEFB 0 + LD A,0A1H ; offset to FDCSPEC (floppy drv #1) in Config area + CALL PFDPARM ; display characteristics floppy #1 + CALL VPRINT + DEFB TAB,'Drv1 = ' + DEFB 0 + LD A,0A6H ; offset to FDCSPEC+5 (floppy drv #2) in Config area + CALL PFDPARM ; display characteristics floppy #2 + CALL VPRINT + DEFB TAB,'Drv2 = ' + DEFB 0 + LD A,0ABH ; offset to FDCSPEC+10 (floppy drv #3) in Config area + CALL PFDPARM ; display characteristics floppy #3 + CALL VPRINT + DEFB TAB,'Drv3 = ' + DEFB 0 + LD A,0B0H ; offset to FDCSPEC+15 (floppy drv #4) in Config area + CALL PFDPARM ; display characteristics floppy #4 + CALL VPRINT + DEFB CR,LF,' ',1,' 2 ',2,' Motor ON Time (Tenths-of-Seconds) : ' + DEFB 0 + LD A,0B5H ; offset to MONTIM in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get Motor On Time (in tenths-of-seconds) + CALL PAFDC ; ..and display it + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 3 ',2,' Motor Spinup (Tenths-of-Seconds) : ' + DEFB 0 + LD A,0B6H ; offset to SPINUP in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get Spinup Delay (in tenths-of-seconds) + CALL PAFDC ; ..and display it + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 4 ',2,' Times to Try Disk Operations : ' + DEFB 0 + LD A,0B7H ; offset to MXRTRY in config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get Max. # of Retries on Floppy Disks + CALL PAFDC ; ..and display + LD A,'4' ; max. possible option in this menu as ascii number + CALL MSELECT + OR A ; valid input ? + JP Z,M0MAIN ; ..if not, jump to display main menu + + +;::::: MENU 3 - FLOPPY DISK (configure) + + ; subsequent labels start with "FD_" +M3CFG: CALL CRLF + CP '1' ; option 1 (Phys. Unit) selected ? + JR NZ,FD_MOTR ; ..if not, jump to next + + ; configure Floppy Disk drive physical unit +FD_UNIT: CALL VPRINT + DEFB CR,TAB,' Configure which unit [0..3] : ' + DEFB 0 + CALL EREOL + CALL GETINP ; get input + CP ' ' ; is it ? + JR Z,FD_UN3 ; ..if so, jump done and display menu again + CP CR ; ? + JR Z,FD_UN3 ; ..if so, jump done and display menu again + SUB '0' ; else, convert ascii to number + JR C,FD_UN1 ; ..if less than '0', jump + CP 4 ; else, check upper limit + JR C,FD_UN2 ; ..if within range, skip over and continue +FD_UN1: CALL M$BEL ; else, notify user + JR FD_UNIT ; ..and ask for new input +FD_UN2: LD L,A ; copy unit # in HL + LD H,0 + ADD HL,HL ; *2 + ADD HL,HL ; *4 + CALL ADDHLA ; *5 (FDCSPEC entry = 5 bytes long) + EX DE,HL ; swap regs + LD A,0A1H ; offset to FDCSPEC in Config area + CALL WSPCPTR ; set ptr + ADD HL,DE ; add calculated offset + PUSH HL ; move ptr in IX + POP IX + CALL CFDUNIT ; ..and go configure the drive +FD_UN3: JP M3FD ; loop, display menu again + + ; configure Floppy Disk motor on time +FD_MOTR: CP '2' ; option 2 (Motor On) selected ? + JR NZ,FD_SPIN ; ..if not, jump to next +FD_MOT1: CALL VPRINT + DEFB CR,TAB,TAB,'Motor On Time in 1/10 Secs',TAB,'[' + DEFB 0 + CALL EREOL + LD A,0B5H ; offset to MONTIM in Config area + CALL PVALASK ; display current value, ask for input + JR C,FD_MOT2 ; ..if error, jump + LD A,D ; else, check if input is valid + OR A ; high-byte must be zero + JR NZ,FD_MOT2 ; ..if not, do not save value + OR E ; is the entered value zero ? + JR NZ,FD_MOT3 ; ..if not, jump save value +FD_MOT2: CALL M$BEL ; else, notify user + JR FD_MOT1 ; ..and ask for new input +FD_MOT3: LD (HL),E ; save new value + JP M3FD ; ..and display Floppy menu again + + ; configure Floppy Disk motor spinup time +FD_SPIN: CP '3' ; option 3 (Motor Spinup) selected ? + JR NZ,FD_RTRY ; ..if not, jump to next +FD_SP1: CALL VPRINT + DEFB CR,TAB,TAB,'Motor Spinup in 1/10 Secs',TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD A,0B6H ; offset to SPINUP in Config area + CALL PVALASK ; display current value, ask for input + JR C,FD_SP2 ; ..if error, jump + LD A,D ; else, check if input is valid + OR A ; high-byte must be zero + JR NZ,FD_SP2 ; ..if not, do not save value + OR E ; is the entered value zero ? + JR NZ,FD_SP3 ; ..if not, jump save value +FD_SP2: CALL M$BEL ; else, notify user + JR FD_SP1 ; ..and ask for new input +FD_SP3: LD (HL),E ; save new value + JP M3FD ; ..and display Floppy menu again + + ; configure Floppy Disk number of retries +FD_RTRY: CALL EREOL +FD_RTR1: CALL VPRINT + DEFB CR,TAB,TAB,'Times to try Disk Opns',TAB,'[' + DEFB 0 + CALL EREOL + LD A,0B7H ; pointer to MXRTRY in Config area + CALL PVALASK ; display current value, ask for input + JR C,FD_RTR2 ; ..if error, jump + LD A,D ; else, check if input is valid + OR A ; high-byte must be zero + JR NZ,FD_RTR2 ; ..if not, do not save + OR E ; is the entered value zero ? + JR NZ,FD_RTR3 ; ..if not, jump save value +FD_RTR2: CALL M$BEL ; else, notify user + JR FD_RTR1 ; ..and ask for new input +FD_RTR3: LD A,E + CP 11 ; new value greater than 10 ? + JR C,FD_RTR4 ; ..if not, jump save + CALL VPRINT ; else, ask for confirmation + DEFB CR,LF,TAB,TAB,TAB,'Do you REALLY mean ' + DEFB 0 + LD A,E ; get new value again + CALL PAFDC ; ..and display it + CALL VPRINT + DEFB ' tries? (Y/[N]) : ' + DEFB 0 + CALL CAPINE + CP 'Y' ; confirmed by user ? + JR Z,FD_RTR4 ; ..if so, save and exit + CALL M$BEL ; else, notify user + JR FD_RTRY ; ..and ask for new input +FD_RTR4: LD (HL),E ; save new value + JP M3FD ; display Floppy menu again + + +;::::: SUPPORT FUNCTIONS - Floppy Disk + + ; configure Floppy Disk Physical Unit + ; in: IX= ptr to entry in FDCSPEC +CFDUNIT: CALL CRLF + + ; floppy disk size +CFDSZ: CALL VPRINT + DEFB CR,TAB,TAB,'Size 8"(1), 5.25"(2), 3.5"(3)?',TAB,'[' + DEFB 0 + CALL EREOL + LD A,(IX+0) ; get FDCSPEC + AND 00000111B ; mask lower 3 bits (floppy size) + LD L,A ; ..and move to HL + LD H,0 + CALL PHLDCNV ; display value and ask for input + JR C,CFDSZ1 ; ..if input is not valid, jump + LD A,D ; evaluated input in DE + OR A ; high-byte must be zero + JR NZ,CFDSZ1 ; ..if not, jump + LD A,E ; else, check if low-byte is zero + OR A + JR Z,CFDSZ1 ; ..if so, jump + CP 4 ; check if value is within limit + JR C,CFDSZ2 ; ..if so, skip over and continue +CFDSZ1: CALL M$BEL ; else, notify user + JR CFDSZ ; ..and loop, ask for new input +CFDSZ2: LD B,A ; copy input + LD A,(IX+0) ; get FDCSPEC + AND 11111000B ; mask off lower bits + OR B ; combine with new value + LD (IX+0),A ; ..save it back + + ; single-/double-sided +CFDSSD: CALL VPRINT + DEFB CR,TAB,TAB,'Single or Double-Sided Drive ?',TAB,TAB,'(' + DEFB 0 + LD D,'S' ; prepare available options for output + LD E,'D' ; (S)ingle / (D)ouble + BIT 3,(IX+0) ; check bit 3 (0= single-sided, 1= double-sided) + CALL PDEOPTN ; show options + CALL VPRINT + DEFB ')',TAB,': ' + DEFB 0 + CALL EREOL ; clear CON: to end of line + CALL GETINP ; get input + CALL CHRSPCR ; is or ? + JR Z,CFDMCTR ; ..if so, jump + CP 'S' ; else, is it 'S' ? + JR Z,CFDSSD1 ; ..if so, jump to continue + CP 'D' ; or, 'D' entered ? + JR Z,CFDSSD1 ; ..if so, jump to continue + CALL M$BEL ; else, notify user + JR CFDSSD ; ..loop +CFDSSD1: CP 'D' ; check input again + SET 3,(IX+0) ; set bit 3 (= double-sided) + JR Z,CFDMCTR ; ..if 'D' entered, skip over + RES 3,(IX+0) ; else, reset bit 3 (= single-sided) + + ; motor control +CFDMCTR: CALL VPRINT + DEFB CR,LF,TAB,TAB,'Motor On/Off Control Needed ?',TAB,TAB,'(' + DEFB 0 + LD D,'Y' ; prepare available options for output + LD E,'N' ; (Y)es / (N)o + LD A,(IX+0) ; get FDCSPEC + CPL ; invers value (two's complement) + BIT 5,A ; check bit 5 (motor), now reversed meaning + CALL PDEOPTN ; display options + CALL VPRINT + DEFB ')',TAB,': ' + DEFB 0 + CALL GETINP ; get input + CALL CHRSPCR ; is it or ? + JR Z,CFDMCT1 ; ..if so, jump + CP 'N' ; else, is it 'N' ? + SET 5,(IX+0) ; set bit 5 (= motor drive control) + JR NZ,CFDMCT1 ; ..if not 'N' entered, skip over + RES 5,(IX+0) ; else, reset bit 5 (= motor always on) +CFDMCT1: LD A,(IX+0) ; get FDCSPEC + AND 00000111B ; mask lower 3 bits + DEC A ; -1 + JR Z,CFDMCT4 ; ..if 8", jump (cannot be hi-density) + CALL CRLF +CFDMCT2: CALL VPRINT + DEFB CR,TAB,TAB,'Motor Speed Standard or Hi-Density',TAB,'(' + DEFB 0 + LD D,'S' ; prepare available options for output + LD E,'H' ; (H)igh / (S)tandard Density + BIT 6,(IX+0) ; check bit 6 (max. speed, 0= 300 RPM, 1= 360 RPM) + CALL PDEOPTN ; display options + CALL VPRINT + DEFB ')',TAB,': ' + DEFB 0 + CALL EREOL ; clear CON: to end of line + CALL GETINP ; get input + CALL CHRSPCR ; is it or ? + JR Z,CFDTRK ; ..if so, jump + CP 'S' ; else, is it 'S' ? + JR Z,CFDMCT3 ; ..if so, jump to continue + CP 'H' ; or, 'H' entered ? + JR Z,CFDMCT3 ; ..if so, jump to continue + CALL M$BEL ; else, notify user + JR CFDMCT2 ; ..loop, ask for new input +CFDMCT3: RES 6,(IX+0) ; reset bit 6 (= for 8" and HD max speed) + CP 'H' ; check input again, 'H' entered ? + JR NZ,CFDTRK ; ..if not, skip over +CFDMCT4: SET 6,(IX+0) ; else, set bit 6 (= max speed 5.25") + + ; tracks per side +CFDTRK: CALL CRLF +CFDTRK1: LD A,(IX+0) ; get FDCSPEC + AND 00000111B ; mask lower 3 bits + DEC A ; -1 + LD A,77 ; prepare for 77 tracks + JR Z,CFDTRK3 ; ..if 8", jump + CALL VPRINT + DEFB CR,TAB,TAB,'Tracks-per-Side (35,40,80)',TAB,TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD L,(IX+4) ; get FDCSPEC+4 (tracks per side) + LD H,0 + CALL PHLDCNV ; display value and ask for input + JR C,CFDTRK2 ; ..if input not valid, jump + LD A,D ; evaluated input in DE + OR A ; high-byte must be zero + JR NZ,CFDTRK2 ; ..if not, jump + LD A,E ; check input value (tracks) + CP 35 + JR Z,CFDTRK3 ; ..if 35, jump to continue + CP 40 + JR Z,CFDTRK3 ; ..or 40, jump to continue + CP 80 + JR Z,CFDTRK3 ; ..or 80, jump to continue +CFDTRK2: CALL M$BEL ; else, notify user + JR CFDTRK1 ; loop, ask for new input +CFDTRK3: LD (IX+4),A ; save new value at FDCSPEC+4 (tracks) + + ; step rate +CFDSTP: CALL VPRINT + DEFB CR,TAB,TAB,'Step Rate in Milli-Seconds',TAB,TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD L,(IX+1) ; get FDCSPEC+1 (step rate in mS) + LD H,0 + CALL PHLDCNV ; display value and ask for input + JR C,CFDSTP1 ; ..if input not valid, jump + LD A,D ; evaluated input in DE + OR A ; high-byte must be zero + JR NZ,CFDSTP1 ; ..if not, jump + OR E ; else, is low-byte zero ? + JR NZ,CFDSTP2 ; ..if not, skip over and continue +CFDSTP1: CALL M$BEL ; else, notify user + JR CFDSTP ; loop, ask for new input +CFDSTP2: LD (IX+1),A ; store new value (step rate) + + ; head load/unload time +CFDHLD: CALL VPRINT + DEFB CR,TAB,TAB,'Head Load Time in Milli-Seconds',TAB,TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD L,(IX+2) ; get FDCSPEC+2 (head load time in mS) + LD H,0 + CALL PHLDCNV ; display value and ask for input + JR C,CFDHLD1 ; ..if input not valid, jump + LD A,D ; evaluated input in DE + OR A ; high-byte must be zero + JR NZ,CFDHLD1 ; ..if not, jump + OR E ; else, is low-byte zero ? + JR NZ,CFDHLD2 ; ..if not, skip over to continue +CFDHLD1: CALL M$BEL ; else, notify user + JR CFDHLD ; loop, ask for new input +CFDHLD2: LD (IX+2),A ; store new value (head load time) +CFDHLD3: CALL VPRINT + DEFB CR,TAB,TAB,'Head Unload Time in Milli-Seconds',TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD L,(IX+3) ; get FDCSPEC+3 (head unload time in mS) + LD H,0 + CALL PHLDCNV ; display value and ask for input + JR C,CFDHLD4 ; ..if input not valid, jump + LD A,D ; evaluated input in DE + OR A ; high-byte must be zero + JR NZ,CFDHLD4 ; ..if not, jump + OR E ; else, is low-byte zero ? + JR NZ,CFDHLD5 ; ..if not, skip over to continue +CFDHLD4: CALL M$BEL ; else, notify user + JR CFDHLD3 ; loop, ask for new input +CFDHLD5: LD (IX+3),A ; store new value (head unload time) + RET + + ; output to CON: and continue validating script file input +M$BEL: LD A,BEL ; + CALL COUT ; output char in A to CON: + JP CFEVAL ; eval script file input + ; ..and let return from there + + + ; display Floppy Drive parameters on CON: + ; in: A= offset to first byte of FDCSPEC drive entry +PFDPARM: CALL WSPCPTR ; set ptr + LD A,(HL) ; get Drive Characteristics + PUSH HL ; save regs + LD HL,FDSZ$5 ; ptr to "Unknown" + AND 00000111B ; mask lower bits + CP 00000100B ; check for unknown Disk Size + ; 000= Fixed / 001= 8" / 010= 5.25" / 011= 3.5" + JR NC,PFDPAR1 ; ..if unknown, jump to continue + LD HL,FDS$TBL ; else, ptr to vectors of Floppy Sizes + ADD A,A ; calculate offset in vector table + CALL GWRDHLA ; ..and get addr +PFDPAR1: CALL VPSTR ; display string (HL= ptr) + LD A,' ' + CALL COUT + POP HL ; restore ptr to Drive Characteristics + BIT 3,(HL) ; check if single-sided (0), or double-sided (1) + INC HL ; move ptr fwd + PUSH HL ; save + LD A,'S' ; prepare for output 'S' + JR Z,PFDPAR2 ; ..if bit 3 not set; jump + LD A,'D' ; else, output 'D' +PFDPAR2: CALL COUT + LD A,'S' + CALL COUT + CALL VPRINT ; display string (ptr on Stack), value Step Rate + DEFB ', ' + DEFB 0 + POP HL ; restore ptr + PUSH HL + INC HL ; move ptr fwd to Tracks per Side + INC HL + INC HL + LD A,(HL) ; get # of Tracks + CALL PAFDC ; ..and display it + CALL VPRINT + DEFB ' Trks/Side',CR,LF,TAB,TAB,'Step Rate = ' + DEFB 0 + POP HL ; restore ptr (to Step Rate) + LD A,(HL) ; get value + CALL PAFDC ; ..and display + CALL VPRINT + DEFB ' mS, Head Load = ' + DEFB 0 + INC HL ; move ptr fwd to Head Load Time + LD A,(HL) + CALL PAFDC ; ..and display + CALL VPRINT + DEFB ' mS, Unload = ' + DEFB 0 + INC HL ; move ptr fwd to Head Unload Time + LD A,(HL) + CALL PAFDC ; ..and display + CALL VPRINT + DEFB ' mS',CR,LF + DEFB 0 + RET + + ; Floppy Disk sizes + ; nul-terminated strings prefixed by a table of vectors +FDS$TBL: DEFW FDSZ$1 + DEFW FDSZ$4 + DEFW FDSZ$3 + DEFW FDSZ$2 +FDSZ$1: DEFB 'Fixed',0 +FDSZ$2: DEFB '3.5"',0 +FDSZ$3: DEFB '5.25"',0 +FDSZ$4: DEFB '8"',0 +FDSZ$5: DEFB 'Unknown',0 + + + ; ###### CHECK: unreferenced code (not used) +UNUSED1: LD A,']' + CALL COUT + CALL VPRINT + DEFB TAB,': ' + DEFB 0 + RET + ; ###### + + + ; display value at given offset in Config area, and ask user for new value + ; in: A= offset (base is B/P Bios page addr) + ; out: DE= evaluated number (user input) + ; HL= ptr in config area +PVALASK: CALL WSPCPTR ; set ptr + LD E,(HL) ; get value + LD D,0 + PUSH HL ; save regs + EX DE,HL ; swap + CALL PHLDCNV ; display current value and ask for user input + POP HL ; restore regs (ptr) + RET + + +;::::: MENU 4 - HARD DISK (config) + +M4HD: LD A,1 + LD (CFMENU),A ; store flag (sub-)menu entered + CALL CLS + CALL VPRINT + DEFB CR,LF,'Menu4 - Hard Disk Options' + DEFB CR,LF,LF,' ',1,' 1 ',2,' Hard Drive Controller = ' + DEFB 0 + LD A,0BAH ; offset to CNTRLR in Config area + CALL WSPCPTR ; set ptr + LD A,(HL) ; get controller type + LD (HDCTRLR),A ; ..and store it + LD (HDCTRL2),A + LD HL,HDCTR$A ; prepare ptr for "GIDE" + CP 80H ; is it GIDE ? + JR Z,M4HD1 ; ..if so, jump to contiinue + LD HL,HDCTRL2 ; else, clear copy + LD (HL),0 + CP 10 ; check for unknown controller type + LD HL,HDCTR$B+1 ; prepare for type "Unknown" + JR NC,M4HD1 ; ..if so, jump + LD HL,HDC$TBL ; else, ptr to vector table for strings + ADD A,A ; calculate offset + CALL GWRDHLA ; read addr and let HL point to string +M4HD1: CALL VPSTR ; display string (HL= ptr) + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 2 ',2,' First Drive :' + DEFB 0 + LD A,0BBH ; offset to HDRV0 in Config area + CALL PHDPARM ; set ptr + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 3 ',2,' Second Drive :' + DEFB 0 + LD A,0C4H ; offset to HDRV1 in Config area + CALL PHDPARM ; set ptr + CALL VPRINT + DEFB CR,LF,LF,' ',1,' 4 ',2,' Third Drive :' + DEFB 0 + LD A,0CDH ; offset to HDRV2 in Config area + CALL PHDPARM ; set ptr + LD A,'4' ; max. possible option in this menu as ascii number + CALL MSELECT ; get input + OR A + JP Z,M0MAIN ; if none, jump display main menu + + +;::::: MENU 4 - HARD DISK (configure) + + ; subsequent labels start with "HD_" +M4CFG: CP '2' ; option '2' selected ? + JR Z,HD_DRV1 ; ..if so, jump + CP '3' ; option '3' ? + JR Z,HD_DRV2 + CP '4' ; option '4' ? + JR Z,HD_DRV3 + CALL VPRINT + DEFB CR,LF,TAB,' Select Controller Type as:',CR,LF + DEFB 0 + XOR A ; clear A + LD C,A ; ..and C +M4CFG1: LD HL,HDC$TBL ; ptr to vector tables of strings + ADD A,A ; calc offset (2 bytes per entry) + CALL ADDHLA ; move ptr fwd + CALL PHDCNAM ; display option number and name of controller + INC C ; counter +1 + LD A,C + CP 10 ; check if max. number not exceeded + JR C,M4CFG1 ; ..show next controller type + LD A,0BAH ; offset to CNTRLR in Config area + CALL WSPCPTR ; set ptr + PUSH HL ; ..in IX + POP IX + LD A,'9'+1 ; max. possible option in this menu as ascii number + CALL MSELECT ; get input + JR Z,M4CFG3 ; if none, jump exit + SUB '0' ; convert ascii to number + CP 9 ; below 9 ? + JR C,M4CFG2 ; ..if so, skip over + LD A,80H ; else, must be GIDE (type 0x80) +M4CFG2: LD (IX+0),A ; set controller type +M4CFG3: JP M4HD ; ..and display hard disk menu again + + + ; configure HD drive + ; in: A= offset to HDRV0/1/2 + ; use injected opcode to skip over another offset being loaded +HD_DRV1: LD A,0BBH ; offset to HDRV0 in Config area + DEFB 21h ; injected opcode 0x21 (= LD HL,nnnn), and fall through +HD_DRV2: LD A,0C4H ; offset to HDRV1 in Config area + DEFB 21h +HD_DRV3: LD A,0CDH ; offset to HDRV2 in Config area + CALL WSPCPTR ; set ptr + CALL VPRINT + DEFB CR,LF,TAB,TAB,'Activate Drive ([Y]/N) ? ' + DEFB 0 + CALL CAPIN + RES 4,(HL) ; byte = combined Phys. Unit # and Log. Unit # + ; bit 4 indicates if active (0= inactive, 1= active) + CP 'N' ; 'N' entered ? + JP Z,HD_STP4 ; ..if so, jump exit + SET 4,(HL) ; else, set bit 4 to activate drive + CALL CRLF + + ; physical unit +HD_PUN: CALL VPRINT + DEFB CR,TAB,TAB,'Physical Unit (0..7)',TAB,TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + PUSH HL ; save HL (ptr to HDRV0/1/2) + LD A,(HL) ; get config. byte + AND 00000111B ; mask lower bits (physical device) + LD L,A ; ..and move to HL for display/input + LD H,0 + CALL PHLDCNV ; display current value and ask for user input + POP HL ; restore regs + LD A,D ; evaluated number in DE + OR A ; high-byte must not be zero + JR NZ,HD_PUN1 ; ..if so, jump + LD A,E ; else, get low-byte + CP 8 ; ..and check if above limit + JR C,HD_PUN2 ; ..if not, jump to continue +HD_PUN1: CALL CFEVAL ; eval script file input + JR HD_PUN ; loop +HD_PUN2: LD A,(HL) ; get Config. Byte + AND 11111000B ; mask off lower 3 bits + OR E ; ..combine with new value (input) + LD (HL),A ; ..and write back + LD C,A ; store Config. Byte in C + LD A,(HDCTRLR) ; get controller type + CP 80H ; is it GIDE ? + JR Z,HD_CYL ; ..if so, skip following options + CALL CRLF + + ; configure logical unit +HD_LUN: CALL VPRINT + DEFB CR,TAB,TAB,'Logical Unit Number (0..7)',TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD A,(HL) ; get Config. Byte + RLCA ; shift upper bits 7-5 to position 2-0 + RLCA + RLCA + AND 00000111B ; mask lower bits (= log. unit) + PUSH HL ; save regs + LD L,A ; copy to HL for display + LD H,0 + CALL PHLDCNV ; display current value and ask for user input + POP HL ; restore regs + LD A,D ; evaluated number in DE + OR A ; check if high-byte is zero + JR NZ,HD_LUN1 ; ..if not, jump + LD A,E ; else, get low-byte + CP 8 ; ..and check if above limit + JR C,HD_LUN2 ; ..if not, jump to continue +HD_LUN1: CALL CFEVAL ; else, eval script file input + JR HD_LUN ; loop (ask for new input) +HD_LUN2: RRCA ; shift bits back to position 7-5 + RRCA + RRCA + LD B,A ; save logical unit number in B + LD A,(HL) ; get Config. Byte + AND 00011111B ; mask off upper 3 bits + OR B ; ..combine with new value (input) + LD (HL),A ; write back + + ; configure cylinders +HD_CYL: INC HL ; move ptr to # of Cylinders in HDRV0/1/2 + PUSH HL ; ..copy to IX + POP IX + CALL VPRINT + DEFB CR,LF,TAB,TAB,'Number of Cylinders',TAB,TAB,'[' + DEFB 0 + LD L,(IX+0) ; current # of Cyl's in HL for output + LD H,(IX+1) + CALL PHLDCNV ; display current value and ask for user input + LD (IX+0),E ; evaluated number in DE + LD (IX+1),D ; ..write back + LD (HDCYLNO),DE ; ..and also store locally + CALL CRLF + + ; configure heads +HD_HEAD: CALL VPRINT + DEFB CR,TAB,TAB,'Number of Heads',TAB,TAB,TAB,'[' + DEFB 0 + CALL EREOL ; clear CON: to end of line + LD L,(IX+2) ; current # of Heads in HL for output + LD H,0 + CALL PHLDCNV ; display current value and ask for user input + LD A,D ; evaluated number in DE + OR A ; check if high-byte is zero + JR Z,HD_HED1 ; ..if so, jump to continue + CALL CFEVAL ; else, eval script file input + JR HD_HEAD ; loop (ask for new input) +HD_HED1: LD (IX+2),E ; write back new value (input) + LD A,(HDCTRLR) ; get controller type + CP 80H ; is it GIDE ? + JR NZ,HD_HED2 ; ..if not, continue w/ reduced write + CALL VPRINT ; else, continue w/ sectors per track + DEFB CR,LF,TAB,TAB,'Sectors Per Track',TAB,TAB,'[' + DEFB 0 + JR HD_RWRT +HD_HED2: CALL VPRINT + DEFB CR,LF,TAB,TAB,'Reduced Write Starting Cylinder',TAB,'[' + DEFB 0 + + ; configure Sectors per Track (GIDE) or Reduced Write Starting Cyl (SCSI) +HD_RWRT: LD L,(IX+3) ; current value in HL for output + LD H,(IX+4) + CALL PHLDCNV ; display current value and ask for user input + LD (IX+3),E ; write back evaluated number in DE + LD (IX+4),D + LD A,(HDCTRLR) ; get controller type + SUB 80H ; is it GIDE ? + ; Note: SUB 0x80 is used here, instead of CP + ; so A= 0 which is written as Step Rate value below + ; GIDE does not use a Step Rate + JP Z,HD_STP3 ; ..if so, skip following options + CALL VPRINT + DEFB CR,LF,TAB,TAB,'Write Precomp. Start Cylinder',TAB,'[' + DEFB 0 + LD L,(IX+5) ; get current Cyl # to start precompensation + LD H,(IX+6) ; ..to HL for output + CALL PHLDCNV ; display current value and ask for user input + LD (IX+5),E ; write back evaluated number in DE + LD (IX+6),D + LD A,(HDCTRLR) ; get controller type + CP 3 ; is it Owl/Adaptec/Xebec (first 3 options) ? + LD A,0 + JR NC,HD_STP3 ; ..if so, set Step Rate = 0 + + ; configure Step Rate (predefined values for specific SCSI controllers) +HD_STEP: LD A,(HDCTRLR) ; get controller type + LD HL,HDSTP$1 ; prepare ptr to Step Rate options #1 + LD C,3 ; number of options + DEC A ; is it Adaptec (#1) ? + JR Z,HD_STP1 ; ..if so, jump continue + LD HL,HDSTP$2 ; ptr Step Rate options #2 + LD C,4 ; number of options + DEC A ; is it Xebec ? + JR NZ,HD_STP4 ; ..if not, jump exit +HD_STP1: CALL VPSTR ; print string (HL= ptr) + CALL EREOL + LD L,(IX+7) ; get current value + INC L ; make it 1-based + LD H,0 + CALL PHLDCNV ; display current value and ask for user input + JR C,HD_STP2 ; ..if error, jump + LD A,D ; evaluated number in DE + OR A ; check if high-byte is zero + JR NZ,HD_STP2 ; ..if not, jump + LD A,E ; else, get low byte + DEC A ; ..make it 0-based + CP C ; and compare to possible # of options + JR C,HD_STP3 ; ..if within boundaries, continue +HD_STP2: CALL CFEVAL ; eval script file input + JR HD_STEP ; loop (ask for new input) +HD_STP3: LD (IX+7),A ; write Step Rate +HD_STP4: JP M4HD ; jump display HD menu + + ; Step Rate options + ; nul-terminated strings +HDSTP$1: DEFB CR,LF,TAB,TAB,'Step Rate:' + DEFB CR,LF,' 3mS(1), 28uS(2), 12uS(3)',TAB,TAB,'[' + DEFB 0 +HDSTP$2: DEFB CR,LF,TAB,TAB,'Step Rate: 3mS(1), ' + DEFB '200uS(2), 70uS(3), 40uS(4)',TAB,'[' + DEFB 0 + + +;::::: SUPPORT FUNCTIONS - Hard Disk (config) + + ; display option number and name of controller + ; in: C= current number (counter) + ; HL= entry in vector table of strings (names) +PHDCNAM: CALL VPRINT + DEFB CR,LF,TAB,TAB,'(' + DEFB 0 + LD A,C ; get number + ADD A,'0' ; make it ascii + CALL COUT ; ..and display + CALL VPRINT + DEFB ') ' + DEFB 0 + LD E,(HL) ; addr of string, low byte + INC HL ; ptr fwd + LD D,(HL) ; addr of string, high byte + EX DE,HL ; swap regs + JP VPSTR ; display string (HL= ptr), and return from there + + ; strings Hard Disk controllers + ; nul-terminated strings prefixed by a table of vectors +HDC$TBL: DEFW HDCTR$1 + DEFW HDCTR$2 + DEFW HDCTR$3 + DEFW HDCTR$4 + DEFW HDCTR$5 + DEFW HDCTR$6 + DEFW HDCTR$7 + DEFW HDCTR$8 + DEFW HDCTR$9 + DEFW HDCTR$A + DEFW HDCTR$B + +HDCTR$1: DEFB 'Owl',0 +HDCTR$2: DEFB 'Adaptec ACB-4000A',0 +HDCTR$3: DEFB 'Xebec 1410a/Shugart 1610-3',0 +HDCTR$4: DEFB 'Seagate SCSI',0 +HDCTR$5: DEFB 'Shugart 1610-4/Minimal SCSI',0 +HDCTR$6: DEFB 'Conner SCSI',0 +HDCTR$7: DEFB 'Quantum SCSI',0 +HDCTR$8: DEFB 'Maxtor SCSI',0 +HDCTR$9: DEFB 'Syquest SCSI',0 +HDCTR$A: DEFB 'GIDE (IDE/ATA)',0 +HDCTR$B: DEFB '--Unknown--',0 + + + ; display Hard Disk parameters + ; in: A= offset to HDRV0/1/2 +PHDPARM: CALL WSPCPTR ; set ptr + LD A,(HL) ; get Config. Byte + BIT 4,A ; is drive active ? (bit 4, 0= inactive, 1= active) + JR NZ,PHDPAR1 ; ..if active, continue + CALL VPRINT ; else, display msg and return + DEFB ' - inactive -' + DEFB 0 + RET +PHDPAR1: LD A,(HDCTRLR) ; get controller type + CP 80H ; is it GIDE ? + JR NZ,PHDPAR2 ; ..if not, jump + CALL VPRINT ; else, display msg + DEFB ' Unit ' + DEFB 0 + LD A,(HL) ; get Config. Byte + JR PHDPAR3 ; ..and skip several options + + ; for SCSI drives, show physical and locgical unit +PHDPAR2: CALL VPRINT + DEFB ' Physical Unit ' + DEFB 0 + LD A,(HL) ; get Config. Byte + AND 00000111B ; mask off bits 4-7 + CALL PAFDC ; ..display value (Phys. Unit) + CALL VPRINT + DEFB ', Logical Unit ' + DEFB 0 + LD A,(HL) ; get Config. Byte + RLCA ; rotate bits 7-5 to position 2-0 + RLCA + RLCA +PHDPAR3: AND 00000111B ; mask off bits 4-7 + CALL PAFDC ; ..display value (Log. Unit) + INC HL ; move ptr fwd (# Cyl) + PUSH HL ; ..into IX + POP IX + LD A,(HL) ; get # Cylinders + INC HL ; ..in HL + LD H,(HL) + LD L,A + OR H ; is value = zero ? + JP Z,PHDPARB ; ..if so, exit + LD (HDCYLNO),HL ; store # Cylinders + CALL VPRINT + DEFB CR,LF,TAB,' No. of Cylinders = ' + DEFB 0 + CALL PHLFDC ; display value (# Cyl) + CALL VPRINT + DEFB ',',TAB,'No. of Heads = ' + DEFB 0 + LD A,(IX+2) ; get # Heads + CALL PAFDC ; ..and display + LD A,(HDCTRLR) ; get controller type + CP 80H ; is it GIDE ? + JR NZ,PHDPAR4 ; ..if not, jump + CALL VPRINT ; else, display Sect. per Track + DEFB CR,LF,TAB,' Sectors-Per-Track= ' + DEFB 0 + LD L,(IX+3) ; get word - for GIDE Sect./Track are stored here + LD H,(IX+4) ; (instead of Cyl. to start Reduced Write) + JP PHLFDC ; ..diplay, and let return from there + + ; more parameters shown for certain SCSI controllers +PHDPAR4: CP 3 ; is controller type # less than 3 ? + RET NC ; ..if not, return (type <> Owl, Adaptec, Xebec) + CALL VPRINT ; else, display more parameters + DEFB CR,LF,TAB,' Red. Write Cyl = ' + DEFB 0 + LD E,(IX+3) ; get word, Cyl. # to start Reduced Write + LD D,(IX+4) + LD HL,(HDCYLNO) ; get total # of Cylinders + OR A ; clear C-Flag + SBC HL,DE ; subtract + EX DE,HL ; swap regs + JR NZ,PHDPAR5 ; ..if not zero, jump + CALL VPRINT ; else, no Reduced Write + DEFB 'None' + DEFB 0 + JR PHDPAR6 ; skip over +PHDPAR5: CALL PHLFDC ; display value (Cyl. to start Reduced Write) +PHDPAR6: CALL VPRINT + DEFB ',',TAB,'Precomp. @ Cyl = ' + DEFB 0 + LD E,(IX+5) ; get word, Cyl. # to start Precompensation + LD D,(IX+6) + LD HL,(HDCYLNO) ; get total # of Cylinders + OR A ; clear C-Flag + SBC HL,DE ; subtract + EX DE,HL ; swap regs + JR NZ,PHDPAR7 ; ..if not zero, jump + CALL VPRINT ; else, no Precompensation + DEFB 'None' + DEFB 0 + JR PHDPAR8 ; skip over +PHDPAR7: CALL PHLFDC ; display value (Cyl. to start Precompensation) +PHDPAR8: LD A,(HDCTRLR) ; get controller type + OR A ; is it zero ? (= Owl) + RET Z ; ..if so, return + CP 3 ; else, check if type # is less than 3 ? + RET NC ; ..if not, return + + ; Step Rate parameters only for Adaptec and Xebec SCSI controllers + CALL VPRINT + DEFB CR,LF,TAB,' Drive Step Rate = ' + DEFB 0 + LD HL,HDSTP$A ; prepare ptr + DEC A ; is it Adaptec controller ? + JR Z,PHDPAR9 ; ..if so, skip over + LD HL,HDSTP$X ; else, ptr to Xebec controller strings +PHDPAR9: LD A,(IX+7) ; get Step Rate + AND 00000011B ; mask off bits 2-7 (max. 4 values possible) + LD B,A + ADD A,A ; *2 + ADD A,A ; *4 + ADD A,B ; *5 (each entry is 5 bytes long) + CALL ADDHLA ; set ptr to string + LD B,5 ; 5 chars to display +PHDPARA: LD A,(HL) ; get char + INC HL ; move ptr fwd + CALL COUT ; ..and display char in A + DJNZ PHDPARA ; loop till done + RET + + ; parameter not defined, exit +PHDPARB: CALL VPRINT + DEFB CR,LF,TAB,'-- Not Defined --' + DEFB 0 + RET + +; Step Rate options - Adaptec controller +; 5 bytes per entry +HDSTP$A: DEFB '3mS ' + DEFB '28uS ' + DEFB '12uS ' + DEFB '??? ' +; Step Rate options - Xebec controller +; 5 bytes each entry +HDSTP$X: DEFB '3mS ' + DEFB '200uS' + DEFB '70uS ' + DEFB '40uS ' + + ; * + + +;::::: MENU 5 - DRIVE LAYOUT (display) + +M5DL: LD A,1 + LD (CFMENU),A ; store flag (sub-)menu entered + LD HL,(WSPCBEG) ; addr start WSPC area + LD DE,22*3+1 ; offset to Bios fn #22 DRVTBL (addr drive table) + ADD HL,DE + LD E,(HL) ; get low byte + INC HL + LD D,(HL) ; get high byte + EX DE,HL ; ..and swap + CALL CNVADDR ; convert to addr in WSPC area + INC HL ; move ptr past 0x21 LD HL,.... + LD E,(HL) ; get low byte + INC HL + LD D,(HL) ; get high byte + EX DE,HL ; ..and swap + CALL CNVADDR ; convert to addr in WSPC area + LD (DRTBL),HL ; store addr (in WSPC) of drive table +M5DL1: CALL CLS + CALL VPRINT + DEFB CR,LF,'Menu 5 - Logical Drive Layout',CR,LF,LF + DEFB 0 + XOR A ; clear A + LD B,16 ; max. number of drives +M5DL2: PUSH BC + PUSH AF + ADD A,'A' ; convert to ascii letter (0 -> 'A') + CALL COUT ; ..and display + CALL VPRINT + DEFB ': = ' + DEFB 0 + POP AF ; restore drive number + PUSH AF + CALL PDLPARM ; display drive parameters + CALL CRLF + POP AF + POP BC + INC A ; next drive number + DJNZ M5DL2 ; loop + CALL VPRINT + DEFB CR,LF,' ' + DEFB 1,' 1 ',2,' Swap Drives, ' + DEFB 1,' 2 ',2,' Configure Partition' + DEFB 1,' 3 ',2,' Show Drive Allocations' + DEFB 0 + LD A,'3' ; max. possible option in this menu as ascii number + CALL MSELECT ; get input + OR A + JP Z,M0MAIN ; ..if none, display Main menu + + +;::::: MENU 5 - DRIVE LAYOUT (configure) + + ; subsequent labels start with "DL_" +M5CFG: CP '1' ; option 1 selected ? + JP NZ,DL_PRTT ; ..if not, jump to next + + ; --- Swap Drives (option 1) + CALL VPRINT + DEFB CR,LF,' Swap drive [A..P] : ' + DEFB 0 +DL_SWP: CALL GETINP ; get input + CP ' '+1 ; is it a Control char or ? + JP C,M5DL1 ; ..if so, go back and display options again + CALL CKDLTR ; is it a valid drive letter ? + JR C,DL_SWP ; ..if not, loop + LD (DR1SWP),A ; else, store number of 1st drive + CALL VPRINT + DEFB ' with drive [A..P] : ' + DEFB 0 +DL_SWP1: CALL GETINP ; get input + CP ' '+1 ; is it a Control char or ? + JP C,M5DL1 ; ..if so, go back and display options again + CALL CKDLTR ; is it a valid drive letter ? + JR C,DL_SWP1 ; ..if not, loop + ADD A,A ; double the number (drive table entries are 16-bit) + LD HL,(DRTBL) ; addr of DRVTBL + LD E,L ; ..into DE + LD D,H + CALL ADDHLA ; add offset + EX DE,HL ; ..swap + LD A,(DR1SWP) ; # of 1st drive + ADD A,A ; *2 + CALL ADDHLA ; add offset + LD A,(DE) ; byte of table entry 1st drive (HL= ptr) + LD B,(HL) ; byte of table entry 2nd drive (DE= ptr) + EX DE,HL ; swap pointers + LD (HL),B ; ..and write bytes to swapped locations + LD (DE),A + INC DE ; both pointers fwd + INC HL + LD A,(DE) ; ..and repeat read/write + LD B,(HL) + EX DE,HL + LD (HL),B + LD (DE),A + LD HL,(DRTBL) ; get addr of DRVTBL + LD B,16 ; number of drives + LD DE,0 + DEC HL ; move ptr back + ; ..and fall through + + ; build drive vector (bitmap of available drives) in DE +DL_VECT: INC HL ; move ptr fwd + LD A,(HL) ; get byte + INC HL ; ptr fwd + OR (HL) ; is it zero ? (no drive) + JR Z,DL_VEC1 ; ..if so, skip + SCF ; else, set C-Flag +DL_VEC1: RR D ; rotate bits through DE + RR E ; ..existing drives are marked with a 1-bit + DJNZ DL_VECT ; loop till done + LD A,(RUNMODE) ; get program running mode + LD BC,34H ; offset drive vector in Z3ENV Descriptor + LD HL,(WRKEND) ; addr of WSPC end + CP 'I' ; config mode 'I'mage ? + JR Z,DL_VEC2 ; ..if so, jump + LD HL,(ENVADR) ; else, get addr of Environment + CP 'M' ; config mode 'M'emory ? + JR Z,DL_VEC2 ; ..if so, jump + LD HL,(WRKZ3E) ; else, Disk mode, get addr of Environment + LD A,H ; is it valid ? + OR L + JR Z,DL_VEC3 ; ..if not, jump exit +DL_VEC2: ADD HL,BC ; add offset + LD (HL),E ; ..and store new drive vector + INC HL + LD (HL),D +DL_VEC3: JP M5DL1 + + ; --- Configure Partition (option 2) +DL_PRTT: CP '2' ; option 2 selected ? + JP NZ,DL_ALOC ; ..if not, jump to next + LD A,(RUNMODE) ; get program running mode + CP 'M' ; config mode 'M'emory ? + JR NZ,DL_PRT1 ; ..if not, jump to coninue + CALL VPRINT ; else, show message + DEFB CR,LF,TAB,"--- Can't Configure Running System ! ---" + DEFB 0 + CALL CFEVAL ; eval script file input + JP DL_ALO7 ; ..and jump exit +DL_PRT1: CALL VPRINT + DEFB CR,LF,TAB,'Configure which Drive [A..P] : ' + DEFB 0 +DL_PRT2: CALL GETINP ; get input + CP CR ; is it ? + JP Z,M5DL1 ; ..if so, jump display DL menu again + CALL CKDLTR ; else, convert to drive number + JR C,DL_PRT2 ; ..if not valid, get new input + LD (DRNO),A ; store drive number + CALL GDPHDPB ; addr of DPH and DPB in WSPC area + LD A,D ; is DPH addr valid ? + OR E + JP Z,M5DL1 ; ..if not, jump to display menu + DEC DE ; move ptr back (in XPDH, located before standard DPH) + DEC DE + LD A,(DE) ; get driver ID + LD (DRVRID),A ; ..store it + CP 2 ; is it a Hard Disk ? + JR Z,DL_PRT3 ; ..if so, continue + CP 3 ; or is it RAM Disk ? + JR Z,DL_PRT3 ; ..then continue + LD A,BS ; else, clear char (send ) + CALL COUT + CALL CFEVAL ; eval script file input + JR NZ,DL_PRT2 ; loop (ask for new input) +DL_PRT3: CALL CRLF + + ; partition allocation size +DL_ALSZ: CALL VPRINT + DEFB TAB,'Allocation Size (1, 2, 4, 8, 16, 32k)',TAB,'[' + DEFB 0 + LD A,(DRNO) ; get drive number + CALL GDPHDPB ; HL= addr of DPB + LD E,(HL) ; Sect/Trk into DE + INC HL + LD D,(HL) + INC HL + SRL D ; divide DE by 2 + RR E + SRL D ; /4 + RR E + SRL D ; /8 + RR E + LD (ALSIZKB),DE ; store allocation size (kB) + LD A,(HL) ; get block shift factor (BSH) + LD (DRBSH),A ; ..and store + CALL GBLS ; get Block Size (BLS) + LD L,A ; ..in HL for output + LD H,0 + CALL PHLDCNV ; display value and ask for input + LD A,1 ; start with 1 + LD B,6 ; max. 6 valid allocation sizes +DL_ALS1: CP E ; evaluated number in DE (single digit range - check E) + JR Z,DL_ALS2 ; ..if match, jump + ADD A,A ; else, double value + DJNZ DL_ALS1 ; ..and loop + LD A,7 ; entered value is invalid + CALL COUT + CALL CFEVAL ; eval script file input + JR DL_ALSZ ; loop (ask for new input) +DL_ALS2: CALL GBSHP ; get ptr to BSH that corresponds with block size + LD (DRBSTBL),HL ; ..and store it + + ; partition number of dir entries +DL_DIRE: CALL VPRINT + DEFB TAB,TAB,'Number of Dir Entries',TAB,'[' + DEFB 0 + LD A,(DRNO) ; get drive number + CALL GDPHDPB ; HL= addr of DPB + LD DE,7 ; offset to 'Dir Max -1' + ADD HL,DE + LD A,(HL) ; get DirMax value + INC HL ; ..into HL + LD H,(HL) + LD L,A + INC HL ; +1 + CALL PHLDCNV ; display value and ask for input + LD HL,(DRBSTBL) ; ptr to BSH lookup table + INC HL ; move fwd to BLM + LD A,(HL) ; get Block Mask (BLM) + SCF + RLA ; A= A*2+1 + SCF + RLA ; A= A*2+1 + AND E ; compare input with max. possible number + JR Z,DL_TROF ; ..if ok, jump to continue + CALL VPRINT ; else, display error and ask for new input + DEFB BEL,' +++ Illegal Number of Entries +++',CR,LF + DEFB 0 + CALL CFEVAL ; eval script file input + JR DL_DIRE ; loop (ask for new input) + + ; partition track offset (start of directory) +DL_TROF: LD (DRDIRMX),DE ; store new Max Dir value + CALL VPRINT + DEFB TAB,TAB,'Starting Track Number',TAB,'[' + DEFB 0 + LD A,(DRNO) ; get drive number + CALL GDPHDPB ; HL= addr of DPB + LD DE,13 ; offset to 'Trk Offset' + ADD HL,DE + LD A,(HL) ; get 'Trk Offset' + INC HL ; ..into HL + LD H,(HL) + LD L,A + CALL PHLDCNV ; display value and ask for input + LD (DROFFS),DE ; store entered value + CALL VPRINT + DEFB TAB,TAB,'# Tracks in Logical Drv',TAB,'[' + DEFB 0 + LD A,(DRNO) ; get drive number + CALL GDPHDPB ; HL= addr of DPB + LD DE,5 ; offset to 'Disk Size -1' + ADD HL,DE + LD E,(HL) ; get Disk Size + INC HL ; ..into DE + LD D,(HL) + INC DE ; +1 + LD A,(DRBSH) ; get current Block Shift Factor (BSH) + EX DE,HL ; swap regs (HL= Disk Size) + SUB 3 ; reduce BSH + LD B,A ; ..for use as counter + LD DE,(ALSIZKB) ; get allocation size (kB) + LD A,0 + JR Z,DL_TRN1 ; ..if A already zero (BSH= 3), don't loop + + ; partition number of tracks (total) +DL_TRNO: ADD HL,HL ; 'Disk Size' is measured in BLS units (allocation blocks) + ADC A,0 ; ..so double it [BSH-3] times + DJNZ DL_TRNO +DL_TRN1: CALL DIVHLDE ; calculate disk capacity in tracks + LD L,C ; copy result in HL + LD H,B + CALL PHLDCNV ; display value and ask for input + LD (DRTRKS),DE ; store entered value (# tracks) + LD A,(DRNO) ; get drive number + CALL GDPHDPB ; DE= addr DPH, HL= addr DPB + PUSH HL ; save HL (DPB) + EX DE,HL ; swap regs + DEC HL ; move ptr backwards + PUSH HL ; save HL (ptr DPH-1, Phys. Unit #) + LD L,(HL) ; get Phys. Unit number + LD H,0 + CALL VPRINT + DEFB TAB,TAB,'Physical Unit Number',TAB,'[' + DEFB 0 + CALL PHLDCNV ; display value and ask for input + POP HL ; restore ptr (DPH-1, Phys. Drive #) + LD (HL),E ; ..and store entered value + EX DE,HL ; swap regs + INC DE ; move ptr fwd to DPH + POP HL ; restore HL (DPB) + LD A,(DRVRID) ; get driver ID + CP 2 ; is it Hard Disk ? + JR Z,DL_UNIT ; ..if so, jump to continue + INC HL ; else, move ptr fwd to DPB+2 (BSH) + INC HL + JR DL_UN1 ; ..and skip over + + ; partition physical unit + ; for Hard Disk, set fixed Sect/Trk (DEFW 64) and Alloc. Size (8k) +DL_UNIT: LD (HL),64 ; set number of sectors per track + INC HL ; ptr fwd + LD (HL),0 + INC HL + LD DE,8 ; allocation size + LD (ALSIZKB),DE ; ..store it +DL_UN1: LD DE,(DRBSTBL) ; ptr to BSH in internal lookup table + EX DE,HL ; swap regs + LDI ; copy BSH and BLM over + LDI + EX DE,HL ; swap regs back + PUSH HL ; save HL (ptr to DPB+4, extent mask) + LD A,(DE) ; get BLS from internal lookup table + LD E,A ; ..into DE + LD D,0 + LD HL,(DRTRKS) ; # of tracks (disk capacity) + LD A,(ALSIZKB) ; allocation size in kB (Sect/Trk) + SRL A ; shift right through C-Flag + LD B,A ; after initial SRL, reg B will be used + XOR A ; clear A and C-Flag + + ; multiply # of tracks according to Allocation Size + ; 1k= *2, 2k= *4, 4k= *8 and so forth +DL_UN2: ADD HL,HL ; double value + ADC A,0 ; test C-Flag + SRL B ; shift right through C-Flag + JR NC,DL_UN2 ; ..loop if more to do + CALL DIVHLDE ; then divide by BLS (from internal lookup table) + LD A,E ; BLS into A (value: 1, 2, 4, 8, 16, or 32) + LD L,0 + SRL A ; shift LSB out + JR Z,DL_UN4 ; ..if A= 0, jump +DL_UN3: SCF ; else, set Carry + RL L ; ..and set as LSB in L + SRL A ; shift next LSB out + JR NZ,DL_UN3 ; ..and continue until A= 0 + ; reg L contains a mask with lower bits set + ; representing BLS value (1= 00000000, 2= 00000001, 4= 00000011 ...) + LD A,B ; get high-byte of quotient (disk capacity / BLS) + OR A ; is it zero ? + JR Z,DL_UN4 ; ..if so, skip over + SRL L ; else, extent bit mask once more +DL_UN4: LD A,L ; bit mask into A + POP HL ; restore HL (ptr DPB+4, extent mask) + LD (HL),A ; ..store EXM + INC HL ; ptr fwd + DEC BC ; disk size -1 + LD (HL),C ; ..store value + INC HL + LD (HL),B + INC HL ; ptr to DPB+7 'Dir Max -1' + LD BC,(DRDIRMX) ; get Dir Max value + DEC BC ; -1 + LD (HL),C ; ..and store + INC HL + LD (HL),B + INC HL + PUSH HL ; save HL (ptr DPB+9, Alloc0) + LD L,C ; copy 'Dir Max -1' to HL + LD H,B + INC HL + LD B,5 ; set counter +DL_UN5: SRL H ; divide HL by 32 (5 times /2) + RR L + DJNZ DL_UN5 ; loop + XOR A + CALL DIVHLDE ; divide by BLS + LD B,C ; ..use result as counter + LD HL,0 +DL_UN6: SCF ; set Carry + RR H ; ..and build bit mask + RR L ; starting from MSB this time + ; (see B/P Bios manual, p. 57) + DJNZ DL_UN6 ; loop + EX DE,HL ; swap regs, bit mask in DE + POP HL ; restore HL (ptr DPB+9, Alloc0) + LD (HL),D ; ..store value + INC HL + LD (HL),E + INC HL + LD (HL),0 ; set 'Check Size' (DPB+11) to zero + INC HL + LD (HL),0 + INC HL ; move ptr to 'Trk Offset' + LD DE,(DROFFS) ; get start of Dir + LD (HL),E ; ..and store + INC HL + LD (HL),D + JP M5DL1 ; jump back to display menu + + ; display allocation (option 3) +DL_ALOC: CALL VPRINT + DEFB CR,LF,' Display Allocations for which Hard Drive [0..2] : ' + DEFB 0 +DL_ALO1: CALL GETINP ; get input + CP CR ; is it ? + JP Z,M5DL1 ; ..if so, jump to display DL menu + SUB '0' ; else, convert to number + JR C,DL_ALO1 ; ..if less than ascii '0', ask for new input + CP 3 + JR NC,DL_ALO1 ; ..if greater than '3', ask for new input + LD C,A ; remember user input (number) + LD HL,(WRKEND) ; addr of WSPC end + INC H ; +100h + LD B,16 ; set initial value to avoid underflow +DL_ALO2: LD A,16 + SUB B + PUSH HL + PUSH BC + CALL GDPHDPB ; DE= addr DPH, HL= addr DPB + POP BC + LD A,D ; check if DPH is valid (<> zero) + OR E + JR Z,DL_ALO5 ; ..if not valid, jump + DEC DE ; move ptr to XDPH (DPH-2= Driver ID) + DEC DE + LD A,(DE) + CP 2 ; is Hard Drive ? (ID= 2) + JR NZ,DL_ALO5 ; ..if not, jump + INC DE ; ptr fwd + LD A,(DE) ; get Phys. Drive # + CP C ; matches user input ? + JR NZ,DL_ALO5 ; ..if not, jump + EX DE,HL ; else, swap regs (DE= DPB) + POP HL ; restore addr WSPC end + LD A,16 + SUB B ; calc drive # + ADD A,'A' ; convert to ascii letter + LD (HL),A ; store it (WSPC end) + INC HL ; ptr fwd + PUSH BC ; save regs + PUSH DE + PUSH HL + LD HL,13 ; offset to 'Track Offset' (DPB+13) + ADD HL,DE ; adjust ptr + LD C,(HL) ; get track offset (16-bit) + INC HL + LD B,(HL) + POP HL ; restore ptr (WSPC end) + LD (HL),C ; ..and store TrkOffs value + INC HL + LD (HL),B + INC HL ; ptr fwd + PUSH HL ; save regs + PUSH BC + INC DE ; move ptr to DPB+2 + INC DE + LD A,(DE) ; get block shift factor (BSH) + INC DE ; move ptr to 'Disk Size -1' + INC DE + INC DE + EX DE,HL ; swap regs + LD E,(HL) ; 'Disk Size -1' into DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs back + INC HL ; Disk Size (measured in BLS units) + SUB 3 ; reduce BSH + JR Z,DL_ALO4 ; ..if zero, don't loop + LD B,A ; else, use as counter + XOR A ; clear A +DL_ALO3: ADD HL,HL ; 'Disk Size' is measured in BLS units (allocation blocks) + ADC A,0 ; ..so double it [BSH-3] times + DJNZ DL_ALO3 +DL_ALO4: LD DE,8 ; 8 sectors (of 128 bytes) = 1kB + CALL DIVHLDE ; divide (result in BC) + POP HL ; restore HL= 'Track Offset' + POP DE ; DE= ptr WSPC end + DEC BC ; [Disk Size in kB]-1 + ADD HL,BC ; calc in HL + EX DE,HL ; swap regs + LD (HL),E ; ..and store value in WSPC area + INC HL + LD (HL),D + INC HL ; move ptr fwd + POP DE ; clear stack + POP BC + PUSH HL ; save ptr WSPC +DL_ALO5: POP HL + LD (HL),0 ; (zero) marks end of string + DJNZ DL_ALO2 ; loop, collect data of all partitions of that drive + CALL CLS + CALL VPRINT + DEFB 'Partition Data Hard Drive Unit : ' + DEFB 0 + LD A,C + ADD A,'0' + CALL COUT + CALL VPRINT + DEFB CR,LF,LF,' Drv',TAB,'Start Trk',TAB,'End Trk',CR,LF + DEFB 0 + LD HL,(WRKEND) ; addr of WSPC end + INC H ; +100h (scratch area w/ collected data) + LD A,(HL) ; check first byte, zero = nothing to display + OR A + JR NZ,DL_ALO6 ; ..if not zero, jump to continue + CALL VPRINT + DEFB CR,LF,TAB,'-- No Assignments --' + DEFB 0 + JR DL_ALO7 ; jump to exit + + ; loop through collected data and display it +DL_ALO6: CALL VPRINT + DEFB CR,LF,TAB + DEFB 0 + LD A,(HL) ; ascii letter of drive + INC HL + CALL COUT + LD A,TAB + CALL COUT + LD E,(HL) ; get start track + INC HL + LD D,(HL) + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; ..display value + EX DE,HL ; and swap back + CALL VPRINT + DEFB TAB,TAB + DEFB 0 + LD E,(HL) ; get end track + INC HL + LD D,(HL) + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; ..display value + EX DE,HL ; and swap back + LD A,(HL) ; end of data (= zero) ? + OR A + JR NZ,DL_ALO6 ; ..if not, loop + CALL CRLF ; else, fall through + +DL_ALO7: CALL VPRINT + DEFB TAB,'[any key to continue]' + DEFB 0 + CALL GETINP ; get input + JP M5DL1 ; display DL menu again + + +;::::: SUPPORT FUNCTIONS - Drive Layout + + ; check if input is a valid drive letter, and convert to number + ; in: A= ascii letter (user input) + ; out: A= number ('A' = 0 .. 'P' = 15) + ; ##### another version of this routine is implemented as CHKDLTR + ; with slightly different functionality + ; THIS routine is only used by "DL_" (Drive Layout) +CKDLTR: CP 'A' ; min. 'A' + JP C,CFEVAL ; ..if not, jump + CP 'P'+1 ; max. 'P' + CCF + JP C,CFEVAL ; ..if not, jump + SUB 'A' ; convert ascii letter to number ('A' -> 0) + RET + + + ; display drive layout parameters on CON: + ; (for drives other than HD, only a short msg is displayed) + ; in: A= drive number (0 = 'A:') +PDLPARM: CALL GDPHDPB ; DE= addr DPH, HL= addr DPB + LD A,E ; check if valid (<> zero) + OR D + JP Z,M$NODRV ; ..if not valid, display message and let return from there + DEC DE ; else, move ptr to XDPH area (DPH-2) + DEC DE + LD A,(DE) ; get Driver ID + CP 2 ; is it Hard Disk ? + JP NZ,M$FLPPY ; ..if not, jump to display type and let return from there + INC DE ; else, move ptr to Phys. Drive # + CALL VPRINT + DEFB 'Unit ' + DEFB 0 + LD A,(DE) ; get Unit (Phys. Drive #) + CALL PAFDC ; ..and display + CALL VPRINT + DEFB ', ' + DEFB 0 + LD E,(HL) ; Sectors per Track in DE + INC HL + LD D,(HL) + LD (DRSECTT),DE ; store value + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; ..display value + EX DE,HL ; and swap back + LD A,(HL) ; get Block Shift Factor (BSH) + PUSH AF ; ..save + CALL VPRINT + DEFB ' Sctrs/Trk, ' + DEFB 0 + CALL GBLS ; get Block Size (BLS) for that BSH + CALL PAFDC ; ..display as decimal + CALL VPRINT + DEFB 'k/Blk, ' + DEFB 0 + LD E,(HL) ; 'Disk Size -1' in DE + INC HL + LD D,(HL) + INC HL + EX DE,HL ; swap regs + INC HL ; +1 (HL= Disk Size in BLS units) + POP AF ; restore AF + SUB 3 ; reduce BSH for use as counter + LD B,A + JR Z,PDLPAR2 ; ..if already zero, don't loop + XOR A ; else, clear A +PDLPAR1: ADD HL,HL ; 'Disk Size' is measured in BLS units (allocation blocks) + ADC A,A ; ..so double it [BSH-3] times + JP C,M$BIG ; overflow ? then exit loop + DJNZ PDLPAR1 ; else, continue loop +PDLPAR2: PUSH DE + PUSH AF + PUSH HL + CALL PDISKSZ ; display capacity + CALL VPRINT + DEFB 'k (' + DEFB 0 + LD DE,(DRSECTT) ; get Sectors/Track + LD B,3 +PDLPAR3: SRL D ; divide by 8 (sectors to kB) + RR E + DJNZ PDLPAR3 ; loop + POP HL ; restore regs (HL= Disk Size in kB) + POP AF + CALL DIVHLDE ; Disk Size / Sectors-per-Tracks (both in kB) + LD L,C ; result into HL + LD H,B + CALL PHLFDC ; ..and display value + CALL VPRINT + DEFB ' Trks), ' + DEFB 0 + POP HL ; restore DPB+8 'Dir Max -1' + LD E,(HL) ; get value + INC HL + LD D,(HL) + EX DE,HL ; swap regs + INC HL ; +1 for display + CALL PHLFDC + CALL VPRINT + DEFB ' Dirs' + DEFB 0 + RET + + ; msg "No Drive" +M$NODRV: CALL VPRINT + DEFB ' -- No Drive --' + DEFB 0 + RET + + ; for drives other than Hard Disks, only the type is displayed +M$FLPPY: CP 1 ; check Driver ID + JR NZ,M$RAM ; ..if not Floppy (1), jump next + CALL VPRINT + DEFB 'Floppy ' + DEFB 0 + INC DE ; move DPH ptr fwd + LD A,(DE) ; get Unit (Phys. Drive #) + ADD A,'0' ; convert to ascii + JP COUT ; ..display, and let return from there + +M$RAM: CP 3 ; check Driver ID + JR NZ,M$UKNWN ; ..if not RAM (3), jump to next + CALL VPRINT ; else, just display and return + DEFB 'RAM' + DEFB 0 + RET + +M$UKNWN: CALL VPRINT ; unknown type + DEFB '??? (' + DEFB 0 + INC DE ; move DPH ptr fwd + ; ##### BUG: LD A,(DE) missing ? value not retrieved before output + CALL PAFDC ; display byte in A as 1-3 decimal chars + LD A,')' + JP COUT + + ; msg "Too Big" +M$BIG: CALL VPRINT + DEFB '+++ Too Big +++' + DEFB 0 + RET + + + ; 16-bit division + ; in: HL= dividend + ; DE= divisor + ; out: BC= result +DIVHLDE: OR A ; clear C-Flag + LD BC,-1 ; set initial value for counter +DIVHLD1: INC BC ; increase counter + SBC HL,DE ; divide by subtraction + SBC A,0 ; test C-Flag + JR NC,DIVHLD1 ; ..and loop while more to go + RET + + + ; get ptr to BSH (Block Shift Factor) in internal lookup table + ; in: A= BLS + ; out: HL= points to BSH value +GBSHP: PUSH BC ; save BC + LD B,6 ; # entries in lookup table + LD HL,BSTBL+2 ; ptr to first BLS +GBSHP1: CP (HL) ; BLS found ? + JR Z,GBSHP2 ; ..if so, exit loop + INC HL ; else, ptr to next BLS + INC HL + INC HL + DJNZ GBSHP1 ; ..and loop +GBSHP2: DEC HL ; move ptr back (= BLM) + DEC HL ; ..and once more (= BSH) + POP BC ; restore BC + RET + + + ; get BLS (Block Size) for given BSH (Block Shift Factor) + ; in: HL= ptr to BSH (in DPB) + ; out: A= BLS, or 0x00 if no valid BSH was found +GBLS: LD B,6 ; # entries in lookup table + LD DE,BSTBL ; ptr to lookup table +GBLS1: PUSH HL ; save HL + LD A,(DE) ; get BSH from table + CP (HL) ; ..and compare + INC HL ; move pointers fwd + INC DE + JR NZ,GBLS2 ; ..if no match, jump + LD A,(DE) ; else, get BLM + CP (HL) ; ..and compare to value in DPB +GBLS2: POP HL ; restore HL + INC DE ; move table ptr fwd + JR Z,GBLS3 ; ..if match, jump + INC DE ; else move table ptr fwd + DJNZ GBLS1 ; loop till done + XOR A ; clear A (not found) + JR GBLS4 ; ..and exit +GBLS3: LD A,(DE) +GBLS4: INC HL + INC HL + INC HL + RET + + ; lookup table for related values of + ; BSH (block shift factor) / BLM (block mask) / BLS (block size) + ; 3 bytes per entry +BSTBL: DEFB 3 ; BSH= 3 + DEFB 7 ; BLM= 7 + DEFB 1 ; BLS= 1 (1 kB) + DEFB 4 ; BSH= 4 / BLM= 15 / BLS= 2 kB + DEFB 15 + DEFB 2 + DEFB 5 ; BSH= 5 / BLM= 31 / BLS= 4 kB + DEFB 31 + DEFB 4 + DEFB 6 ; BSH= 6 / BLM= 63 / BLS= 8 kB + DEFB 63 + DEFB 8 + DEFB 7 ; BSH= 7 / BLM= 127 / BLS= 16 kB + DEFB 127 + DEFB 16 + DEFB 8 ; BSH= 8 / BLM= 255 / BLS= 32 kB + DEFB 255 + DEFB 32 + + + ; get addr's of DPH and DPB for given drive number + ; in: A= drive number + ; out: DE= addr of DPH, HL= addr of DPB + ; or Z-Flag set if no drive +GDPHDPB: LD HL,(DRTBL) ; addr of DRVTBL in WSPC area + ADD A,A ; offset is 2* drive # + CALL GWRDHLA ; get 16-bit value from offset addr + LD D,H ; ..into DE + LD E,L + OR H ; addr invalid (= zero) ? + RET Z ; ..if so, exit with Z-Flag set + CALL CNVADDR ; convert to addr in WSPC + EX DE,HL ; swap regs + LD HL,10 ; offset from to addr DPB in DPH + ADD HL,DE + LD A,(HL) ; get addr + INC HL + LD H,(HL) + LD L,A ; ..and fall through, convert addr to WSPC + + + ; convert addr in B/P Bios to addr in WSPC area + ; in/out: HL= addr +CNVADDR: LD BC,(BIOSADR) ; B/P Bios page addr + OR A ; clear flags + SBC HL,BC ; calculate offset + LD BC,(WSPCBEG) ; ..and add to addr of start WSPC + ADD HL,BC + RET + + + ; print disk size to CON: (capacity in kB) + ; output as decimal with provision for 3-byte values - see ZXD21.Z80 PRBIG + ; in: A,H,L= 24-bit value + ; (Stack)= DE, AF, HL in that order +PDISKSZ: PUSH DE ; save regs + PUSH BC + EX AF,AF' ; swap AF + PUSH AF ; save + EX AF,AF' ; ..and swap back + LD B,0 + LD C,-1 ; set initial result + LD DE,86A0H ; 100,000 = 0x0186A0, set lower 2 bytes + OR A ; clear C-Flag +PDISKS1: INC C ; accumulate count + SBC HL,DE ; subtract lower 2 bytes + SBC A,1 ; ..and upper byte + JR NC,PDISKS1 ; loop till done + ADD HL,DE ; adjust underflow + ADC A,1 + CALL PHLD2 + LD DE,10000 ; print 10000's + CALL PHLD + LD DE,1000 ; print 1000's + CALL PHLD + LD DE,100 ; print 100's + CALL PHLD + LD DE,10 ; print 10's + CALL PHLD + LD A,L ; print 1's + CALL PHLD3 + POP AF ; restore AF + EX AF,AF' ; ..and swap + POP BC ; restore regs + POP DE + RET + + + ; print content of HL to CON: as decimal + ; divide HL by DE, convert remainder to ascii digit and print it + ; (similar to SYSLIB's PHLFDC/PHDC1 - see ZXD21.Z80 DECDSP) + ; in: HL= value, DE= divisor +PHLD: LD C,-1 ; set initial count + OR A ; clear C-Flag +PHLD1: INC C ; accumulate count + SBC HL,DE ; divide by subtraction + SBC A,0 + JR NC,PHLD1 ; ..and loop while more to go + ADD HL,DE ; compensate for underflow + ADC A,0 +PHLD2: EX AF,AF' ; swap AF regs (retain flags) + LD A,C ; get result (quotient) + OR A ; is it zero ? + JR NZ,PHLD3 ; ..if not, skip over + OR B ; get prior digit print flag + JR Z,PHLD4 ; ..if anything printed yet, jump + XOR A ; else, print a zero +PHLD3: ADD A,'0' ; convert to ascii + LD B,A ; remember for next loop + CALL COUT ; ..and display it +PHLD4: EX AF,AF' ; swap AF regs back + RET + + ; * + + +;::::: IMAGE FILE + + ; --- Read IMG file +RDIMG: LD DE,CPMFCB+9 ; filetype in CP/M standard FCB #1 + LD A,(DE) ; get byte + CP ' ' ; is it ? + JR NZ,RDIMG1 ; ..if not, skip over + LD HL,FTYPE ; else, point to standard filetype 'IMG' + LD BC,3 ; copy 3 bytes + LDIR +RDIMG1: LD HL,(WRKSTRT) ; start of workspace area + LD (WRKDMA),HL ; ..set as DMA buffer addr + CALL SETDMA + LD DE,CPMFCB + CALL Z3LOG ; log into given DU (eval as ZCPR3 XFCB) + CALL F$EXIST ; check file exists (Z= not found) + JR NZ,RDIMG2 ; ..if so, jump to continue + CALL E$MSG ; else, display error and exit + CALL VPRINT + DEFB 'File Not Found!' + DEFB 0 + JP EXIT + +RDIMG2: CALL F$OPEN ; open image file + JR Z,RDIMG3 ; ..if no error, jump to continue + CALL E$MSG ; else, dipslay error and exit + CALL VPRINT + DEFB "Can't Open!" + DEFB 0 + JP EXIT + + ; image file found and opened, read into memory +RDIMG3: LD HL,0 ; read record #0 + CALL R$READ ; random read from file (DE=FCB, HL=record) + JP NZ,RDIMERR + LD HL,(WRKSTRT) ; ptr workspace area (= current DMA) + LD DE,29 ; offset ZCPR Non-banked Size (at offset 29d) + ADD HL,DE ; adjust ptr + LD DE,0100H ; length of img file header + CALL ADDDHPT ; add values, DE = DE + (HL) + INC HL ; ptr fwd + INC HL + INC HL ; ZCPR Banked Size (at offset 33d) + CALL ADDDHPT ; add values + LD BC,27 ; move ptr fwd + ADD HL,BC ; ZSDOS Non-banked Size (at offset 61d) + CALL ADDDHPT ; add values + INC HL ; move ptr fwd + INC HL + INC HL ; ZSDOS Banked Size (at offset 66d) + CALL ADDDHPT ; add values + LD BC,25 ; move ptr fwd + ADD HL,BC ; B/P Bios base addr (at offset 91d) + LD C,(HL) ; get low byte + INC HL + LD B,(HL) ; ..and high byte + LD (BIOSADR),BC ; store B/P Bios page addr + EX DE,HL ; swap regs, HL= offset to Bios start in img file + ADD HL,HL ; *2 + LD A,H ; high byte in A + LD (BPOFFS),A ; store offset sector # + LD L,H ; ..and set as start value + LD H,0 + LD DE,CPMFCB + + ; read 20 sectors (20 * 128 = 2560 bytes) + LD B,20 +RDIMSEC: CALL R$READ ; read file sector (randomly, DE= FCB, HL= sector #) + JR NZ,RDIMERR ; ..if error, jump + PUSH HL ; save regs + PUSH BC + LD HL,(WRKDMA) ; get current DMA addr + LD BC,128 ; ..and increase by 128 bytes + ADD HL,BC + LD (WRKDMA),HL ; store new addr + CALL SETDMA ; ..and set as DMA buffer addr + POP BC ; restore regs + POP HL + INC HL ; next sector + DJNZ RDIMSEC ; ..loop til done + LD HL,(WRKDMA) ; get end of workspace area + LD (WRKEND),HL ; ..save + CALL CHKBP ; check for "B/P" signature string + JP C,EXIT ; ..if not found, exit + + PUSH DE + LD HL,(WRKSTRT) ; get addr start WSPC + PUSH HL + LD DE,91 ; offset to B/P Bios page addr + ADD HL,DE ; ..adjust ptr + LD E,(HL) ; get low byte + INC HL + LD D,(HL) ; ..and high byte of Bios page addr + LD HL,(BIOSADR) ; offset from file start + EX DE,HL ; swap regs + OR A ; clear flags + SBC HL,DE ; calc difference + POP DE ; addr WSPC (now in DE) + ADD HL,DE ; ..add to ptr + LD DE,10 ; ..and move another 10 bytes fwd + ADD HL,DE + LD A,(HL) ; get byte + LD (BPVERS),A ; ..and save it (Bios version #) + CALL RETUD ; currently logged drive in B, and user in C + LD (IMGDU),BC ; ..store DU: of IMG file + POP DE + LD HL,(WRKEND) ; addr of workspace end + CALL SETDMA ; set DMA transfer address (in HL) + LD HL,1 ; read sector #1 + CALL R$READ ; read file sector (DE= FCB, HL= sector #) + RET Z + + ; error while reading image file +RDIMERR: CALL E$MSG + CALL VPRINT + DEFB 'Error Reading : ' + DEFB 0 + JR PIMGFN ; display filename and close file + ; ..let return from there + + + ; ADD DE,(HL), add 16-bit value addressed by HL to DE + ; in: DE= 16-bit value + ; HL= ptr to 2nd 16-bit value + ; uses: BC, DE, HL +ADDDHPT: LD C,(HL) ; get low byte in C + INC HL ; move ptr to next byte + LD B,(HL) ; get high byte in B + EX DE,HL ; swap regs + ADD HL,BC ; add values + EX DE,HL ; ..and swap back + RET + + ; --- Write IMG file +WRIMG: LD HL,(WRKSTRT) ; addr start of WSPC + LD (WRKDMA),HL ; ..set as DMA buffer addr + CALL SETDMA + LD BC,(IMGDU) ; drive and user of IMG file + CALL LOGUD ; set DU: for following operations + LD DE,CPMFCB + CALL Z3LOG ; log DU (eval as ZCPR3 XFCB) + LD A,(BPOFFS) ; get offset sector # to start writing + LD L,A + LD H,0 + + ; write 20 records (20 * 128 = 2560 bytes) + LD B,20 +WRIMSEC: CALL F$WRITE ; write file sector (randomly, DE= FCB, HL= sector #) + JR NZ,WRIMERR ; ..if not successful, jump + PUSH HL ; save regs + PUSH BC + LD HL,(WRKDMA) ; get current DMA addr + LD BC,128 ; ..and increase by 128 bytes + ADD HL,BC + LD (WRKDMA),HL ; store new addr + CALL SETDMA ; ..and set as DMA addr + POP BC + POP HL + INC HL ; next sector + DJNZ WRIMSEC ; ..loop til done + LD HL,(WRKEND) ; addr end of workspace + CALL SETDMA ; set as DMA buffer addr + LD HL,1 ; sector #1 + CALL F$WRITE ; write to file + JR Z,CLSIMG ; ..if successful, jump to close file + + +; error while writing image file +WRIMERR: CALL F$CLOSE ; close file (DE= ptr FCB) + CALL E$MSG ; ..and display error msg + CALL VPRINT + DEFB 'Error Writing : ' + DEFB 0 + +; Display IMG filename +PIMGFN: LD DE,CPMFCB+1 ; fn in CP/M standard FCB #1 + CALL PFN3 ; display fn.ft + JP CRLF + +; --- Close IMG file +CLSIMG: CALL F$CLOSE ; close file (DE= ptr FCB) + CALL VPRINT ; ..and inform user + DEFB CR,LF,TAB,'...File Closed.' + DEFB 0 + RET + + ; * + + +;::::: MEMORY + + ; --- Read running B/P Bios from memory (using BIOS fn #30) +RDMEM: LD HL,(CPMBIOS+1) ; addr warm boot (BION fn #1) + LD L,30*3 ; adjust ptr to fn #30 + LD A,(HL) ; check byte at ptr location + CP 0C3H ; is it opcode 0xC3 (JP) ? + JP NZ,E$BPBIO ; ..if not, jump error and let return from there + CALL JUMPHL ; else "call" B/P Bios fn #30 (RETBIO) + LD (BPVERS),A ; store version of B/P Bios + LD (BIOSADR),BC ; " base addr + LD (CNFGADR),DE ; " config area addr + EX DE,HL ; swap regs (HL= ptr Config area) + CALL CHKSYS ; check for signature string + JP NZ,E$BPBIO ; ..if not found, jump error and let return from there + LD DE,(WSPCBEG) ; addr WSPC + LD L,C ; Bios page addr in HL + LD H,B + LD BC,2560 ; number of bytes + LDIR ; ..and copy + LD (WRKEND),DE ; store end of WSPC area + RET + + ; --- Write new configuration to memory, replace running system +WRMEM: LD HL,(WSPCBEG) ; addr WSPC start + LD DE,(BIOSADR) ; B/P Bios page addr + LD BC,2560 ; bytes to copy + LDIR + LD HL,(BIOSADR) ; B/P Bios page addr + LD L,21*3 ; offset to BIOS fn #21 (DEVINI, init IO devices) + CALL JUMPHL ; ..and "call" BIOS directly + CALL VPRINT + DEFB CR,LF,LF,TAB,'..New Configuration Installed..',CR,LF + DEFB 0 + RET + + ; * + + +;::::: DISK (System Tracks) + + ; --- Read System Tracks + ; and find addr's of system segments + ; in: A= drive letter (already checked it is A..P) +RDDSK: SUB 40H ; convert ascii to number + LD (DISKNO),A ; ..and store it + CALL DSKINDR ; ask user to place disk in drive + LD A,(DISKNO) ; get disk number + LD HL,(WSPCBEG) ; addr start WSPC + CALL RDSTRK ; read sys tracks into WSPC + JP C,ERREXIT ; ..if error, jump exit + LD A,(OLDDU+1) ; get previously logged drive + JP SELDSK ; ..select and let return from there + + ; --- Write System Tracks +WRDSK: LD A,(DISKNO) ; get disk number + CALL SELDSK1 ; ..select + LD BC,(SECTNO) ; counter outer loop + LD DE,(SYSSECT) ; # sectors w/ system tracks + PUSH BC ; save regs + PUSH DE + CALL BIOSTTR ; set track for subsequent write + POP BC ; restore regs + POP DE + LD A,(SCTBOOT) ; # of sectors w/ system (after boot code) + LD B,A + LD HL,(WRKSTRT) ; addr start WSPC +WRDSK1: PUSH DE ; save regs + PUSH BC + PUSH HL + LD DE,(XLTADR) ; addr XLT (sector translation table) + CALL BIOSTRN ; translate logical to physical sector + LD B,H ; ..in BC + LD C,L + CALL BIOSTSE ; set sector for subsequent write + POP BC ; addr WSPC + PUSH BC + CALL BIOSTDM ; set DMA buffer + LD C,0 + CALL BIOWRIT ; ..write one sector + OR A + JP NZ,E$WRITE ; if not successful, jump error and exit + POP HL ; addr WSPC + LD DE,128 ; ..move forward by 128 bytes (1 sector) + ADD HL,DE + POP BC ; restore regs / clear stack + POP DE + DEC B ; reduce counter + JR NZ,WRDSK2 ; ..if not finished, skip over + LD C,1 ; else, force writing + JP BIOWRIT ; ..and write final sector (returning from there) + +WRDSK2: INC C ; counter +1 + LD A,(SECTTRK) ; check if sectors/track (DPB) limit reached + CP C + JR NZ,WRDSK1 ; ..if not, write sector + INC DE ; else, increase track # + LD C,0 ; ..clear counter + PUSH DE + PUSH BC + PUSH HL + LD B,D ; track # in BC + LD C,E + CALL BIOSTTR ; ..and set track + POP HL + POP BC + POP DE + JR WRDSK1 ; loop + + + ; read system tracks + ; in: A= drive number + ; HL= addr of WSPC start + ; out: Z-Flag set if error, NZ if ok +RDSTRK: LD (WRKSTRT),HL ; store copy of WSPC addr (to work with) + CALL SELDSK1 ; select disk (A= #) + JP Z,E$SRC ; ..if error, jump error and exit + LD E,(HL) ; HL= addr of DPH + INC HL ; get addr of XLT (sector translation table) + LD D,(HL) ; in DE + LD (XLTADR),DE ; ..and store it + LD A,9 ; move ptr to DPB addr + CALL ADDHLA + LD E,(HL) ; addr of DPB in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD E,(HL) ; get Sectors/Track from DPB + INC HL + LD D,(HL) + LD (SECTTRK),DE ; ..and save + LD A,12 ; move ptr to Trk Offset + CALL ADDHLA + LD E,(HL) ; get # of system tracks + INC HL + LD A,(HL) + AND A ; high byte must be zero + JP NZ,E$NOSYS ; ..if not, jump error and exit + OR E ; check if # of system tracks is zero + JP Z,E$NOSYS ; ..if so, jump error and exit + LD (SYSTRK),A ; store # of system tracks + LD HL,(SECTTRK) ; get Sectors/Track + LD DE,46 ; # of sectors (= 0x1700) + ; ##### CHECK: bpboot codes approx. 0x1700 -- 46d/0x2E sectors + LD C,0 + XOR A ; clear flags + SBC HL,DE ; enough space in one track ? + JR NC,RDSTRK2 ; ..if so, jump to continue + ADD HL,DE ; else, restore initial value + EX DE,HL ; swap regs + XOR A ; clear flags +RDSTRK1: SBC HL,DE ; divide by subtraction + INC C ; increase counter (quotient) + JR NC,RDSTRK1 ; ..more to go + ADD HL,DE ; compensate underflow + DEC C ; and correct quotient + EX DE,HL ; swap back +RDSTRK2: LD B,0 + LD A,E ; check if DE= 0 + OR D + JR Z,RDSTRK3 ; ..if so, skip + DEC DE ; else, decrease DE +RDSTRK3: LD (SECTNO),BC ; store loop counter + LD (SYSSECT),DE ; store # of sys sectors + PUSH BC ; save regs + PUSH DE + LD A,(SYSTRK) ; # of system tracks + LD DE,(SECTTRK) ; sectors/track + LD HL,0 +RDSTRK4: ADD HL,DE ; accumulate count + DEC A ; decrease counter + JR NZ,RDSTRK4 ; ..loop till done + LD DE,-45 ; adjust for boot code + ADD HL,DE + LD A,L + LD (SCTBOOT),A ; save # of sectors after boot code + CALL BIOSTTR ; set track for subsequent read + POP BC + POP DE + LD A,(SCTBOOT) ; get # of sectors + LD B,A + LD HL,(WRKSTRT) ; addr start WSPC +RDSTRK5: PUSH DE ; save regs + PUSH BC + PUSH HL + LD DE,(XLTADR) ; addr of XLT + CALL BIOSTRN ; translate sector # (log. to phys.) + LD B,H + LD C,L + CALL BIOSTSE ; set sector for subsequent read + POP BC ; restore addr in WSPC + PUSH BC + CALL BIOSTDM ; set as DMA buffer + CALL BIOREAD ; ..and read one sector + OR A + JP NZ,E$READ ; ..if error, jump error and exit + POP HL ; restore addr in WSPC + LD DE,128 ; move fwd by 128 bytes (1 sector) + ADD HL,DE + LD (WRKEND),HL ; store as WSPC end addr + POP BC ; restore regs + POP DE + DEC B ; decrease counter (# of sectors) + JR Z,RDSTRK6 ; ..if done, exit loop + INC C ; counter +1 + LD A,(SECTTRK) ; check if sectors/track (DPB) limit reached + CP C + JR NZ,RDSTRK5 ; ..if not, loop + INC DE ; else, increase track # + LD C,0 ; ..clear counter + PUSH DE + PUSH BC + PUSH HL + LD B,D ; track # in BC + LD C,E + CALL BIOSTTR ; ..and set it + POP HL + POP BC + POP DE + JR RDSTRK5 ; then start all over again +RDSTRK6: CALL CHKBP ; search for B/P signature string in WSPC + JP C,EXIT ; ..if not found, exit program + ; else, fall through + + ; --- Find System Segments + ; search for B/P Bios fn #30 RETBIO in the just loaded system + ; start addr is at known offset in WSPC + ; byte pattern: 0x01 0x00 ... 0x11 ... ... 0x21 ... ... 0x3E ... + ; LD BC,..00 LD DE,.... LD HL,.... LD A,.. + ; page addr config area dev table version + LD HL,0 +FNDSYS: LD (WRKZ3E),HL ; clear variable + LD HL,(WSPCBEG) ; addr start WSPC area + LD DE,30*3+1 ; offset to B/P Bios fn #30 RETBIO + ADD HL,DE + LD C,(HL) ; get addr of function + INC HL + LD B,(HL) + LD E,C ; ..low byte only + LD D,0 + LD HL,(WSPCBEG) ; reset ptr to start WSPC again + ADD HL,DE ; move ptr to first byte of fn +FNDSYS1: PUSH HL ; ..and save ptr + LD A,(HL) ; get byte at ptr location + CP 01H ; is it 0x01 ? (LD BC,...) + JR NZ,FNDSYS2 ; ..if not, move to next memory page + INC HL ; else, move ptr fwd + LD A,(HL) ; get byte + OR A ; is it 0x00 ? + JR NZ,FNDSYS2 ; ..if not, move to next mem page + INC HL ; else, move ptr fwd + LD A,(HL) ; get byte (high byte of possible B/P Bios page addr) + ADD A,D ; add to current offset in WSPC area + CP B ; match w/ addr of fn #30 ? + JR Z,FNDSYS3 ; ..if so, code found, jump to continue +FNDSYS2: POP HL ; else, restore ptr in WSPC + INC D ; move both ptr's fws by 0x100 bytes + INC H + LD A,D ; fn must be within first 0x600 bytes + CP 6 ; so check + JR C,FNDSYS1 ; ..if within limit, continue searching + LD HL,0 ; else, clear addr and exit + JR FNDSYS8 + + ; code signature of fn #30 found, extract data +FNDSYS3: PUSH HL ; save regs + PUSH DE + LD DE,8 ; offset to version # (LD A,..) + ADD HL,DE ; adjust ptr + LD A,(HL) ; get byte + LD (BPVERS),A ; ..and store it + POP DE + POP HL ; HL= ptr to high byte of B/P Bios page addr + LD A,(HL) ; get it + POP HL ; clear stack + LD H,A ; copy Bios page addr in HL + LD L,0 + PUSH HL ; ..and save it + + ; search for Z3ENV Environment descriptor + LD DE,(WSPCBEG) ; addr start WSPC area + LD HL,(WRKEND) ; addr end WSPC area + OR A ; clear C-Flag + SBC HL,DE ; calculate size of WSPC area + LD C,L ; ..copy to BC + LD B,H + EX DE,HL ; swap regs + LD DE,Z3ENV$ ; ptr to "Z3ENV" +FNDSYS4: LD A,(DE) ; get letter from string to search for + CPIR + JP PO,FNDSYS7 ; ..if not found, exit + PUSH HL ; else, save regs + PUSH DE + PUSH BC + LD B,4 ; number of remaining letters +FNDSYS5: INC DE ; move to next letter to search + LD A,(DE) ; ..and get it + CP (HL) ; compare with found place + JR NZ,FNDSYS6 ; ..if no match, jump + INC HL ; else, move ptr fwd + DJNZ FNDSYS5 ; ..and loop for next letter + XOR A ; set Z-Flag (= found) and fall through +FNDSYS6: POP BC ; restore regs + POP DE + POP HL + JR NZ,FNDSYS4 ; Z-Flag not set, continue searching + LD DE,-4 ; correct addr, set to beginning of Z3ENV + ADD HL,DE + LD (WRKZ3E),HL ; ..and store it +FNDSYS7: POP HL ; restore regs + OR A ; clear flags +FNDSYS8: LD (BIOSADR),HL ; store B/P Bios page addr + RET +Z3ENV$: DEFB 'Z3ENV' + + + ; search for signature string "B/P" within first 3 sectors in workspace + ; in: WRKSTRT set to start addr + ; out: if found, Z-Flag is set and C-Flag is reset (NC) + ; else display error msg and C-Flag set +CHKBP: LD HL,(WRKSTRT) ; addr start of WSPC + LD (WSPCBEG),HL ; ..retain copy + LD B,2 ; set counter (# of attempts) +CHKBP0: LD HL,(WSPCBEG) ; addr start WSPC + LD A,7EH ; offset to Config area (from sector start) + CALL ADDHLA ; adjust ptr + CALL CHKSYS ; ..and check for signature + RET Z ; if found, return + LD HL,(WSPCBEG) ; else, get addr of WSPC + LD DE,128 ; ..and move fwd by 1 sector (128 bytes) + ADD HL,DE + LD (WSPCBEG),HL ; store new addr + DJNZ CHKBP0 ; ..and loop + JP E$BPBIO ; not found, display err msg and let return from there + ; ..with C-Flag set + + +;::::: HELP + +HELP: CALL VPRINT + DEFB CR,LF,1 + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB 2,' - Alter parameters in a B/P Bios Image file, Boot Tracks or Memory.' + DEFB CR,LF,' The program may be interactive with screen attributes under ZCPR3' + DEFB CR,LF,' or take input from a text Configuration file.' + DEFB CR,LF,LF,'Syntax:',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' //',TAB,TAB,'<-- Display this message',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB TAB,TAB,'<-- Run interactively',CR,LF,LF + DEFB ' The following forms may be followed by an optional Config file',CR,LF + DEFB ' from which to draw parameters to set. There must be a space',CR,LF + DEFB ' between the first argument shown and the filename.',CR,LF,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' *',TAB,TAB,'<-- Configure Memory Image',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' d:',TAB,TAB,'<-- Configure drive d: Boot Tracks',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' [du:]fn[.ft]',TAB,'<-- Configure Image File',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' [du:]fn[.ft] [du:]fn[.ft] <-- Configure Image file (1st ',CR,LF + DEFB ' filespec) using Config file (2nd filespec).',CR,LF + DEFB ' Default Type of Config File is .CNF.',CR,LF + DEFB 0 + + +;::::: EXIT PROGRAM +EXIT: LD SP,(STACK) ; restore stack pointer + JP 0 ; initiate warm boot + +EXIT1: CALL VPRINT + DEFB CR,LF,TAB,'.. aborted ..',CR,LF + DEFB 0 + JR EXIT + + + ; return quiet flag from ENV, or Z-Flag set if error + ; (shorter than SYSLIB's GETQUIET) +GETQFLG: LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + RET Z ; ..if not, return with Z-Flag set + LD A,28H ; offset to quiet flag + CALL ADDHLA ; ..adjust ptr + LD A,(HL) ; get flag + RET + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PPRGNAM: LD A,(ENVADR+1) ; get high byte of ENVPTR + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; and let return from there + CALL VPRINT ; else, display default + DEFB 'BPCNFG' + DEFB 0 + RET + + + ; #### CHECK: unreferenced code (not used) + ; print filename (?), deleting spaces + LD B,8 ; up to eight chars +UNUSED2: INC HL ; move ptr forward + LD A,(HL) ; get char + AND 7FH ; mask MSB + CP ' ' ; is it ? + CALL NZ,COUT ; ..if not, print to CON: + DJNZ UNUSED2 ; count down + RET + ; ##### + + + ; check if running under B/P Bios + ; in: HL= ptr to possible B/P Bios CONFIG area + ; out: Z-Flag set if B/P Bios, NZ= not ok +CHKSYS: PUSH HL ; save regs + DEC HL ; move ptr 6 bytes backward + DEC HL ; (signature string) + DEC HL + DEC HL + DEC HL + DEC HL + LD A,(HL) ; get byte + CP 'B' ; is it 'B' ? + JR NZ,CHKSYS1 ; ..if not, jump error + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP '/' ; is it '/' ? + JR NZ,CHKSYS1 ; ..if not, jump error + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP 'P' ; is it 'P' + ; ..if so, fall trhough w/ Z-Flag set +CHKSYS1: POP HL ; restore regs + RET + + + ; select disk using direct BIOS call + ; in: A= disk drive # (one-based) + ; out: Z-Flag set if error, NZ= ok +SELDSK1: DEC A ; A -1, and fall through + + ; in: A= disk drive # (zero-based) +SELDSK: LD C,A ; C= drive (0= A ... 15= P) + LD E,0 ; ##### CHECK: not needed under B/P Bios + CALL BIOSELD + LD A,H ; HL= 0 if no drive + OR L ; ..set Z-Flag (status indicator) + RET + + + ; #### CHECK: unreferenced code (not used) +UNUSED3: PUSH BC + PUSH DE + PUSH HL + CALL CPMBDOS + INC A + POP HL + POP DE + POP BC + RET + ; ##### + + +;::::: MENU SELECTION + + ; evaluate selected option, or exit program (on / ) + ; function combines manual input and reading script file (CNF) + ; in: A= max. possible option (as ascii number) + ; out: Z-Flag set if error, NZ= ok +MSELECT: INC A ; upper limit +1 + LD E,A ; ..store value + CALL VPRINT + DEFB CR,LF,LF,LF,TAB,'Enter Selection : ' + DEFB 0 +MSELCT1: CALL CFIN ; get input + CP ' ' ; is it ? + JR Z,MSELCT3 ; ..jump return + CP CR ; ? + JR Z,MSELCT3 ; ..jump return + CP CTRLC ; ? + JP Z,EXIT ; ..exit program + CP ESC ; ? + JP Z,EXIT ; ..exit program + CP '1' ; is it ascii number ? + JR C,MSELCT2 ; ..if not, jump error + CP E ; else, compare with limit + CCF ; reverse C-Flag + JR C,MSELCT2 ; ..if out of range, jump error + CALL COUT ; else, print char and return + RET +MSELCT2: LD A,BEL ; error, notify user + CALL COUT + CALL CFEVAL ; if running script, opt change to interactive mode + JR MSELCT1 ; ..and loop +MSELCT3: XOR A ; set Z-Flag + RET + + + ; get input - either from script file, or manual (CAPINE uses injected CIN) + ; *** A CENTRAL FUNCTION *** + ; out: A= char + ; Z-Flag set if , exit program if or +GETINP: CALL CAPIN ; get char in A and capitalize + CP ' ' ; is it a control char ? + CALL NC,COUT ; ..if not, echo on console + CP ESC ; ? + JR Z,GETINP1 ; ..if so, jump exit program + CP 3 ; ? +GETINP1: JP Z,EXIT ; ..if so, exit program + CP ' ' ; is it ? return w/ Z-Flag set + RET + + + ; check for and + ; in: A= char to check + ; out: Z-Flag set if true +CHRSPCR: CP ' ' ; is it a ? + RET Z ; ..if so, return w/ Z-Flag set + CP CR ; ? + RET ; return, Z-Flag is set accordingly + + + ; #### CHECK: unreferenced code (not used) +UNUSED4: PUSH HL + CALL PHL4HC ; display hex number + JR PHLDCN1 ; ... and get input + ; ##### + + + ; print HL as decimal + closing bracket + ; then get user input and convert to number + ; in: HL= 16-bit value + ; out: DE= converted number, or original value if no input + ; HL= ptr after string + ; Z-Flag set if no input +PHLDCNV: PUSH HL ; save regs + CALL PHLFDC ; display as dec +PHLDCN1: POP DE ; get orig. value in DE + CALL VPRINT + DEFB ']',TAB,': ' + DEFB 0 + CALL CINPUTL ; line input + RET Z ; ..if no input, return + JP EVAL ; else, parse input string as Bin/Oct/Dec/Hex + + + ; print 2 options the user can choose from as "[D]/E" or "D/[E]" + ; in: DE= ascii chars to display + ; Z-Flag set= "D" in brackets, NZ= "E" in brackets +PDEOPTN: CALL Z,PLBR ; ..if Z, print left bracket + LD A,D ; print char in D + CALL COUT + CALL Z,PRBR ; ..if Z, print right bracket + LD A,'/' ; print slash + CALL COUT + CALL NZ,PLBR ; ..if NZ, print left bracket + LD A,E ; print char in E + CALL COUT + RET Z ; ..if Z, return (no closing bracket) +PRBR: LD A,']' ; print right bracket + JP COUT ; ..and let return from there +PLBR: LD A,'[' ; print left bracket + JP COUT ; ..and let return from there + + + ; #### CHECK: unreferenced code (not used) +UNUSED5: CALL CINPUTL + JP EVAL ; HL points to string to be parsed for Bin/Oct/Dec/Hex + ; ##### + + + ; get line input + ; through SYSLIB's INLINE fn, with injected code to read script file + ; out: HL= ptr to string buffer + ; Z-Flag set if nothing entered +CINPUTL: LD HL,INLBUF ; set buffer addr + LD (HL),0 ; prepare for empty string ( terminator) + OR 0FFH ; echo ON + CALL INLINE ; single line editor for CON: + LD A,(HL) ; check for empty string + OR A + RET + + + ; get pointer in WSPC area + ; (used to return addr in Config area) + ; in: A= offset + ; out: HL= ptr to byte at WSPC + offset +WSPCPTR: LD HL,(WSPCBEG) ; addr start WSPC area + ; ..and fall through + + ; add A to HL (result in HL) +ADDHLA: ADD A,L ; add L + LD L,A ; store result in L + RET NC ; ..if no overflow, return + INC H ; else, increment H + RET + + + ; get word (16-bit value) indirectly + ; in: HL= base addr + ; A= offset + ; out: HL= 16-bit value at offset addr +GWRDHLA: CALL ADDHLA ; add offset + LD A,(HL) ; get low byte + INC HL ; ptr fwd + LD H,(HL) ; get high byte in H + LD L,A ; ..and low byte in L + RET + + + ; check drive letter is valid ('A'..'P') + ; in: A= letter to check + ; out: C-Flag set if error, NC= ok + ; ##### another version of this routine is implemented as CKDLTR + ; with slightly different functionality +CHKDLTR: CP 'A' ; below ascii letter 'A' ? + RET C ; ..return with C-Flag set + CP 'P'+1 ; greater than ascii letter 'P' ? + CCF ; ..reverse C-Flag and return + RET + + + ; ask user to place disk in drive + ; in: DISKNO contains disk # +DSKINDR: CALL VPRINT + DEFB CR,LF,'Place disk in drive ' + DEFB 0 + LD A,(DISKNO) ; get disk number + ADD A,40H ; ..convert to ascii for display + CALL COUT + CALL VPRINT + DEFB ': and press return to continue...' + DEFB 0 +DSKIND0: CALL CFIN ; get input (console or script file) + CP CTRLC ; is it ? + JP Z,EXIT1 ; ..if so, quit program + CP CR ; ? + JR NZ,DSKIND0 ; ..if not, loop + JP CRLF ; else, output newline and let return from there + + +;::::: ERROR MESSAGES + + ; entry points for various error messages + ; in most cases, the program is terminated after display +E$BPBIO: CALL E$MSG + CALL VPRINT + DEFB 'Not B/P Bios +++',CR,LF + DEFB 0 + SCF + RET + +E$READ: CALL VPRINT + DEFB BEL,'*** Read Error' + DEFB 0 + JR ERREXIT + +E$SRC: CALL VPRINT + DEFB BEL,'*** Bad source!' + DEFB 0 + JR ERREXIT + +E$WRITE: CALL VPRINT + DEFB BEL,'*** Write Error' + DEFB 0 + JR ERREXIT + +E$DEST: CALL VPRINT + DEFB BEL,'*** Bad destination!' + DEFB 0 + JR ERREXIT + +E$NOSYS: CALL VPRINT + DEFB BEL,'*** No System!' + DEFB 0 + JR ERREXIT + +E$OPEN: CALL VPRINT + DEFB BEL,"*** Can't open source file!" + DEFB 0 + +ERREXIT: CALL CRLF + LD HL,0 ; load HL= 0 (warm boot) + ; ..and fall through + + ; "called" as a pseudo-routine that returns to caller + ; in: HL= target addr +JUMPHL: JP (HL) ; jump to addr in HL regs + + + ; every output of an error message begins + ; with this sequence of and "+++ " +E$MSG: CALL VPRINT + DEFB CR,LF,BEL,'+++ ' + DEFB 0 + RET + + + ; print lower nybble in A as hex on CON: + ; in: A= number to display +PLOWAX: AND 00001111B ; mask off high nybble, keep lower + ADD A,90H ; conversion to hex + DAA ; (same as SYSLIB @B2HL) + ADC A,40H + DAA + JP COUT ; send to CON: and let return from there + + ; * + + +;::::: MENU 6 - CNF SCRIPT FILE + +M6CNF: CALL VPRINT + DEFB CR,LF,LF,' Enter Config File (default type = .CNF) : ' + DEFB 0 + CALL CINPUTL + LD HL,INLBUF ; ptr to input buffer + LD DE,CFFCB ; ptr to script file FCB + CALL ZFNAME ; parse specified token into an FCB + CALL CFINFT ; add standard filetype 'CNF', if necessary + CALL CFINOPN ; open file (check if exists) + JP M0MAIN + + + ; read config file (script) byte-wise + ; interpret special chars (comment, end-of-line etc.) + ; convert closing brackets and commas to + ; all other chars fall through and are returned as read +CIN: +CFIN: LD A,(CFBYTE) ; get current byte + OR A ; is it zero ? + JR Z,CINPUT ; ..if so, manual input mode is active + CALL CFINCHR ; else, get next byte from config file + JR C,CFIN ; if error occurred, loop and fall through to manual input + CP ';' ; is it a semi-colon ? + JR NZ,CFIN1 ; ..if not, jump to check of end of line + + ; comment, skip over chars until an error occurred or end of line is reached +CFIN0: CALL CFINCHR ; get next char + JR C,CFIN ; ..if error occured, loop and fall through to manual input + CP CR ; is it a ? + JR Z,CFIN ; ..if so, get next byte from config file + CP LF ; follows ? + JR NZ,CFIN0 ; ..if not, get next byte + LD A,(CFLNNO) ; else, get line counter + INC A ; ..increase it + LD (CFLNNO),A ; ..and save back + JR CFIN ; loop + + ; end of line ? +CFIN1: CP CR ; is it ? + JR Z,CFIN ; ..if so, get next byte + CP LF ; follows ? + JR NZ,CFIN2 ; ..if not, jump to check special chars + LD A,(CFLNNO) ; else, get line counter + INC A ; ..increase it + LD (CFLNNO),A ; ..and save back + JR CFIN ; loop + + ; check for special characters +CFIN2: CP ' ' ; is it ? + JR Z,CFIN ; ..if so, get next byte + CP TAB ; ? + JR Z,CFIN ; ..get next byte + CP '[' ; is it an opening bracket ? + JR Z,CFIN ; ..get next byte + CP ']' ; is it a closing bracket ? + JR Z,CFIN3 ; ..exit routine + CP ',' ; is it a comma ? + RET NZ ; ..if not, return with Z-Flag cleared +CFIN3: LD A,CR ; else return a in A + RET + + + ; get one char from console + ; (using direct call to BIOS CONIN) +CINPUT: PUSH HL + PUSH DE + PUSH BC + LD HL,(CPMBIOS+1) ; HL= warm boot addr of BIOS jump (fn #1) + LD L,3*3 ; adjust target addr to fn #3 (after 0xC3 JP) + CALL JUMPHL ; ..and "call" into BIOS + POP BC + POP DE + POP HL + RET + + + ; get next char from config file + ; in: - + ; out: byte stored in data segment + ; or A= 0 and C-Flag set if error +CFINCHR: PUSH HL ; save regs + LD HL,CFDMA ; addr DMA transfer buffer + LD A,(CFPOS) ; get last reading position + OR A ; reset flags + INC A ; ..move forward + CALL M,CFINRD ; if negative (high-bit set), read next sector + JR C,CFINCH0 ; ..if end reached, jump + LD (CFPOS),A ; else, remember reading position + CALL ADDHLA ; HL= ptr to byte in DMA buffer + LD A,(HL) ; ..get it + CP CTRLZ ; is it (EOF) ? + SCF + CCF ; clear C-Flag, set return status Ok (NC) + JR NZ,CFINCH0 ; ..if not EOF, return Ok + XOR A ; else, clear A + LD (CFBYTE),A ; ..and store zero byte + SCF ; set C-Flag (= error) +CFINCH0: POP HL ; restore regs + RET + + ; reads next sector from config file +CFINRD: PUSH HL + PUSH DE + LD HL,CFDMA ; addr DMA transfer buffer + CALL SETDMA ; ..set + LD DE,CFFCB ; local FCB + CALL Z3LOG ; ..log into DU: given in FCB + CALL F$READ ; read one sector of file sequentially + CALL NZ,CFINCLS ; close file again + POP DE + POP HL + RET + + ; open config file +CFINOPN: LD HL,CFDMA ; addr DMA transfer buffer + CALL SETDMA ; ..set + LD DE,CFFCB ; local FCB + CALL Z3LOG ; ..log into DU: given in FCB + CALL F$EXIST ; does the file exist ? + JR NZ,CFINOP0 ; ..if yes, try to open it + CALL E$MSG ; else, display msg and switch to interactive mode + CALL VPRINT + DEFB 'Not Found' + DEFB 0 +CFINERR: CALL VPRINT + DEFB '..using Console Input!',CR,LF,' [press any key to continue]' + DEFB 0 + CALL CINPUT + XOR A + LD (CFBYTE),A + RET +CFINOP0: CALL F$OPEN ; try to open config file + JR Z,CFINOP1 ; ..if ok, jump + CALL E$MSG ; else, display error + CALL VPRINT + DEFB "Can't Open" + DEFB 0 + JR CFINERR ; ..and switch to interactive mode + + ; set parameters for subsequent read +CFINOP1: LD A,1 ; line # + LD (CFLNNO),A + LD A,0FFH ; current byte + LD (CFBYTE),A + DEC A ; set byte pos in DMA buffer + LD (CFPOS),A ; ..to initiate reading next sector automatically + XOR A ; clear A + LD (CFFCB+32),A ; set sector count in FCB + RET + + ; close file +CFINCLS: LD DE,CFFCB ; local FCB + CALL Z3LOG ; ..log into DU: given in ZCPR3 FCB + CALL F$CLOSE ; and close file + XOR A + LD (CFBYTE),A + SCF ; set Carry + RET + + ; add standard file type 'CNF' if none was specified +CFINFT: LD A,(CFFCB+9) ; get first char of filetype + CP ' ' ; is it ? + JR NZ,CFINFT0 ; ..if not, skip over + LD DE,CFFCB+9 ; else, ptr to filetype in FCB + LD HL,FTYPE+3 ; ..ptr to default type 'CNF' + LD BC,3 ; copy 3 bytes + LDIR +CFINFT0: LD DE,CFFCB ; ptr to FCB + RET + + ; evaluate script file, checks if current byte is zero + ; if so, an error occured and user may switch to manual input +CFEVAL: PUSH AF ; save regs + LD A,(CFBYTE) ; get current byte + OR A ; is is zero ? + JP Z,CFEVL0 ; ..if so, jump exit + PUSH BC ; else, save other regs too + PUSH DE + PUSH HL + CALL CFINCLS ; close config file + CALL VPRINT + DEFB CR,LF,BEL,'+++ Error in : ' + DEFB 0 + LD DE,CFFCB+1 ; ptr to fn in FCB + CALL PFN3 ; print FCB-type fn.ft to CON: + CALL VPRINT + DEFB ', Line : ' + DEFB 0 + LD A,(CFLNNO) ; print line number + CALL PAFDC ; as decimal + CALL VPRINT + DEFB ' ..aborting to Keyboard..',CR,LF,' [press any key to continue]' + DEFB 0 + CALL CINPUT ; get pressed key + CP CTRLC ; is it ? + JP Z,0 ; ..if so, exit program w/ warm boot + CP ESC ; ? + JP Z,0 ; ..exit program w/ warm boot + CALL CRLF + POP HL ; restore regs + POP DE + POP BC +CFEVL0: POP AF ; restore AF + RET + + +;::::: BIOS JUMPS (for direct calls) + +; area is filled with actual jumps at runtime +; to call BIOS fn's directly +BIOSELD: JP 0 ; fn #9 SELDSK select disk +BIOSTTR: JP 0 ; fn #10 SETTRK set track +BIOSTSE: JP 0 ; fn #11 SETSEC set sector +BIOSTDM: JP 0 ; fn #12 SETDMA set buffer addr +BIOREAD: JP 0 ; fn #13 READ read one sector +BIOWRIT: JP 0 ; fn #14 WRITE write one sector + JP 0 ; fn #15 LISTST list status (not used) +BIOSTRN: JP 0 ; fn #16 SECTRN sector translation + + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; VLIB - 0x318C +; Z3LIB - 0x33AD +; SYSLIB - 0x3653 +; end addr 0x3A55 (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;::::: RAM STORAGE + + DSEG + + ; --- RAM (menu 1.1) + DEFB 0 ; not used + DEFB 0 ; not used +SELBNK: DEFB 0 ; selected RAM bank (offset in CONFIG area) + DEFB 0 ; not used + DEFB 0 ; not used + + ; --- Char IO Device (menu 2) +BAUDRT: DEFB 0 ; baud rate / max. capabilities +DEVASSG: DEFB 0 ; device assignment (current #, 2 bits IOBYT) +DEVTBL: DEFW 0 ; addr of Char IO device table (DEVCFG) +DEVLAST: DEFB 0 ; # of last/highest device as ascii +DEV1SWP: DEFB 0 ; # first device to swap + + ; --- Hard Disk (menu 4) +HDCYLNO: DEFW 0 ; # of cylinders +HDCTRLR: DEFB 0 ; SCSI/HD controller type +HDCTRL2: DEFB 0 ; " (copy) + + ; --- Drive Layout (menu 5) +DRBSH: DEFB 0 ; BSH block shift factor (from DPB) +DRNO: DEFB 0 ; # drive to configure +DRBSTBL: DEFW 0 ; ptr to internal lookup table (vector), +0 = BSH, +1 = BLM +DRDIRMX: DEFW 0 ; max. directory entries +DROFFS: DEFW 0 ; track offset (start of directory) +DRTRKS: DEFW 0 ; number of tracks (disk capacity) +DRSECTT: DEFW 0 ; sectors per track (tmp storage when iterating over HD's) +DRTBL: DEFW 0 ; addr of DRVTBL in workspace area +DR1SWP: DEFB 0 ; # first drive to swap +DRVRID: DEFB 0 ; driver ID (1= Floppy, 2= HD, 3= RAM) +ALSIZKB: DEFW 0 ; allocation size in kB (sect/trk divided by 8) + + ; --- CNF Script File +CFBYTE: DEFB 0 ; current byte +CFMENU: DEFB 0 ; indicator when entering a new menu (##### CHECK: not used?) + DEFB 0 ; not used +CFLNNO: DEFB 0 ; # line (counter) +CFPOS: DEFB 0 ; pos of current byte (in DMA buffer) +CFFCB: DEFS 24H ; local FCB of CNF script file +CFDMA: DEFS 80H ; transfer buffer + + ; 'other' +BPVERS: DEFB 0 ; B/P Bios version # +WSPCBEG: DEFW 0 ; addr begin of workspace (WSPC) +CNFGADR: DEFW 0 ; addr Config. area +BIOSADR: DEFW 0 ; addr Bios base + + DEFS 64H ; room for stack (100 bytes) +STACK: DEFW 0 ; stack storage location + + ; ..and more 'other' +RUNMODE: DEFB 0 ; program running mode (config Memory/Disk/Image) +OLDDU: DEFW 0 ; logged Drive/User at program start +IMGDU: DEFW 0 ; Drive/User of image file +INLBUF: DEFS 20H ; buffer for INLINE routine (SYSLIB single line editor) +DISKNO: DEFB 0 ; # of disk (in config mode Disk) +WRKSTRT: DEFW 0 ; addr begin of WSPC (copy) +WRKDMA: DEFW 0 ; addr of transfer buffer +WRKEND: DEFW 0 ; addr end of WSPC + + ; config mode Disk (system tracks) +SECTTRK: DEFW 0 ; sectors per track (from DPB) +XLTADR: DEFW 0 ; addr of XLT (from DPH) +SECTNO: DEFW 0 ; counter for sectors, if track capacity less than 0x1700 bytes +SYSSECT: DEFW 0 ; # of sectors containing system tracks +SCTBOOT: DEFB 0 ; # of sectors after boot code +SYSTRK: DEFB 0 ; # of system tracks +WRKZ3E: DEFW 0 ; addr of Z3ENV descriptor in WSPC +BPOFFS: DEFB 0 ; offset (in # of sectors) to start writing B/P Bios in IMG file + + END + + +;************************************************************************ +; Remarks jxl: +; BPCNFG.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file *almost* matches the +; original BPCNFG.COM file. Some SYSLIB routines are located at other +; absolute addresses. Apparently, a different version of SYSLIB was used +; for the original BPCNFG.COM. Reproducing an exactly matching copy was +; not possible. However, only the order of routines within SYSLIB seem +; to have changed, not their code/functionality. (see BPCNFG.SYM) +; +; The program is the most complex of tools distributed with B/P Bios. +; It supports configuration of the running system in memory, of an image +; file, and of system tracks; requiring an exhaustive tool chest (and +; code). Configuration can be done manually/interactively or using a +; script file. Programmatically, this has been intertwined, i.e. user +; input and script input are handled in the same routine. Therefore, a +; local implementation replaces SYSLIB's CIN routine, letting all calls +; go through that local routine which can read console and file input. +; +; From the structure and coding styles (let alone the size!) it can +; be concluded, that the original code was divided up into several +; files, worked on by different persons. As a byproduct of this approach +; (and the technical limitations in those days), some unreferenced code +; portions were found. Those are marked with "#####" in the comment, as +; well as some other places that could be optimised. Of course, further +; code refactoring would be possible. +; Similar patterns can be found for every menu displayed on screen: +; Display, configure, support functions, and messages/strings. The +; source code above is structured accordingly, also attemting to use +; a common naming scheme for labels. It seems very likely that first +; .REL files were produced for the different code portions before +; linking them together. Not exposing all labels as public gives more +; freedom in naming them. To provide the source code in its entirety, +; for now it was not split up. Perhaps in a later version... +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/bpswap.z80 b/Source/BPBIOS/UTIL/bpswap.z80 new file mode 100644 index 00000000..a966b9b9 --- /dev/null +++ b/Source/BPBIOS/UTIL/bpswap.z80 @@ -0,0 +1,483 @@ + TITLE "Swap drives under B/P Bios" +;************************************************************************ +;* B P S W A P * +;* Swap two drive letters in a running B/P Bios system * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Dec 2024 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB * +;* * +;* A>Z80ASM BPSWAP/RS * +;* A>SLRNK BPSWAP/N,/A:100,/D:0854,BPSWAP,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 10 +REV EQU ' ' + +DATE MACRO + DEFB '31 Aug 92' + ENDM + + +CTRLC EQU 03H ; Control-C character +BEL EQU 07H ; Bell character +TAB EQU 09H ; Tab character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) +CPMDMA EQU 80H ; CP/M standard DMA buffer + + +; From VLIB Get.. + EXTRN VPRINT, Z3VINIT + +; From Z3LIB Get.. + EXTRN GETNAME, PRTNAME, WHRENV + +; From SYSLIB Get.. + EXTRN CRLF, CAPINE, COUT + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +BPSWAP: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0 ; addr of Z3 environment + +START: LD HL,(CPMBDOS) ; ##### BUG: should be CPMBDOS+1 ? + CALL WHRENV ; find Z3 Environment Descriptor + LD (ENVADR),HL ; store addr + CALL Z3VINIT ; ..and init for Z3LIB routines + CALL GETNAME ; get actual program name + CALL GQFLAG + AND A ; running in quiet mode ? + JR NZ,START0 ; ..if so, skip over + CALL VPRINT + DEFB 1,'B/P Drive Swap',2,' V',VER/10+'0','.',VER MOD 10 + '0',', ' + DATE + DEFB CR,LF + DEFB 0 + +START0: LD (STACK),SP + LD SP,STACK + + ; get first token from command line (in FCB #1) + LD A,(CPMFCB+1) ; get char + CP '/' ; is this a help request ? + JP Z,HELP ; ..if so, show help screen + LD HL,(CPMBIOS+1) ; get warm boot addr (BIOS fn #1) + LD L,30*3 ; adjust ptr to fn #30 + LD A,(HL) ; check byte at ptr location + CP 0C3H ; is it opcode 0xC3 (JP) ? + JR NZ,E$BPBIO ; ..if not, jump error and exit + CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO) + LD (BPBASE),BC ; store B/P Bios base addr + LD HL,-6 ; move ptr 6 bytes backward + ADD HL,DE ; (signature string) + LD A,(HL) ; get byte + CP 'B' ; is it 'B' ? + JR NZ,E$BPBIO ; ..if not, error and exit + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP '/' ; is it '/' ? + JR NZ,E$BPBIO ; ..if not, error and exit + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP 'P' ; is it 'P' ? + JR Z,EVALCMD ; ..if so, jump to continue + ; else, fall through (error and exit) + +E$BPBIO: CALL VPRINT + DEFB CR,LF,BEL,'+++ Not B/P Bios ... aborting +++',CR,LF + DEFB 0 + JP EXIT + + + ; evaluate command line +EVALCMD: LD HL,CPMDMA ; ptr to standard DMA buffer (holds command line) + LD A,(HL) ; get length of first token + INC HL ; +1 + CALL ADDHLA ; move ptr fwd + LD (HL),0 ; set terminator + LD HL,CPMDMA+1 ; set ptr to start of string + CALL FINDDRV ; find letter of first drive + JR C,RUNIMOD ; ..if invalid/not found, switch to interactive mode + LD (DRV1ST),A ; else, store # of first drive + LD A,(HL) ; get following byte + CALL EVALSEP ; is it a separator char ? + JP C,M$ABORT ; ..if not, abort program + CALL FINDDRV ; find letter of second drive + JR C,RUNIM0 ; ..if invalid/not found, switch to interactive mode + LD (DRV2ND),A ; else, store # of second drive + LD A,(HL) ; get following byte + CALL EVALSEP ; is it a separator char ? + JP C,M$ABORT ; ..if not, abort program + JR SWAPDRV ; else, jump to continue + + + ; run in interactive mode +RUNIMOD: CALL VPRINT + DEFB ' First Drive to Swap [A..P] : ' + DEFB 0 + CALL CAPINE ; get input + CALL CRLF + CP CTRLC ; is it ? + JP Z,M$ABORT ; ..if so, abort program + CALL EVALDRV ; check if drive letter is valid (A..P) + JR C,RUNIMOD ; ..if not, loop ask for new input + LD (DRV1ST),A ; else, store drive # +RUNIM0: CALL VPRINT + DEFB ' Second Drive to Swap [A..P] : ' + DEFB 0 + CALL CAPINE ; get input + CALL CRLF + CP CTRLC ; is it ? + JP Z,M$ABORT ; ..if so, abort program + CALL EVALDRV ; check if drive letter is valid (A..P) + JR C,RUNIM0 ; ..if not, loop ask for new input + LD (DRV2ND),A ; else, store drive # + + +;::::: PROCESS + +SWAPDRV: LD HL,(BPBASE) ; get B/P Bios base addr + LD L,22*3 ; adjust ptr to fn #22 (DRVTBL) + CALL JUMPHL ; ..and "call" fn + PUSH HL ; save ptr to DRVTBL + LD A,(DRV1ST) ; get # of first drive + ADD A,A ; *2 for 16-bit entries + CALL ADDHLA ; ..and move ptr fwd + EX DE,HL ; swap regs + POP HL ; restore ptr to DRVTBL + LD A,(DRV2ND) ; get # of second drive + ADD A,A ; *2 + CALL ADDHLA ; ..and move ptr fwd + + ; DE= addr DPH first drive + ; HL= addr DPH second drive + LD C,(HL) ; swap addr's in DRVTBL using + LD A,(DE) ; regs DE, HL as pointers + LD (HL),A ; and regs A, C holding bytes to copy + LD A,C + LD (DE),A + INC HL + INC DE + LD C,(HL) + LD A,(DE) + LD (HL),A + LD A,C + LD (DE),A + LD HL,0 + LD (PDRVVCT),HL ; init new Drive Vector (pos) with 0x0000 + DEC HL + LD (NDRVVCT),HL ; init new Drive Vector (neg) with 0xFFFF + LD HL,(ENVADR) ; get ENV addr + LD DE,52 ; offset to Drive Vector + ADD HL,DE ; move ptr + PUSH HL ; ..and save it + LD E,(HL) ; get Drive Vector in DE + INC HL + LD D,(HL) + LD A,(DRV1ST) ; get # of first drive + CALL MKDRMSK ; get bit mask for first drive + LD C,L ; ..and move it to BC + LD B,H + LD A,(DRV2ND) ; get # of second drive + CALL MKDRMSK ; get bit mask for second drive + EX DE,HL ; ..and move it to DE + CALL MKVCMSK ; update new Drive Vector for first drive + PUSH BC ; swap BC and DE + PUSH DE + POP BC + POP DE + CALL MKVCMSK ; update new Drive Vector for second drive + + ; (Stack) = addr of Drive Vector in ENV - PUSH HL + ; HL= current Drive Vector, DE= bit mask first drive, BC= bit mask second drive + EX DE,HL ; swap regs (save current Drive Vector in DE) + ADD HL,BC ; add/merge bit masks + EX (SP),HL ; put merged mask on stack - used by SWAPDRX + ; get addr of Drive Vector in ENV + PUSH HL ; ..and save it + EX DE,HL ; swap regs back (current Drive Vector in HL) + LD BC,(PDRVVCT) ; get new Drive Vector (pos) + LD DE,(NDRVVCT) ; and (neg) + LD A,L ; low byte of current Drive Vector + AND E ; reset bit (neg) + OR C ; set bit (pos) + LD E,A ; ..and store result in E + LD A,H ; high byte of current Drive Vector + AND D ; reset bit (neg) + OR B ; set bit (pos) + LD D,A ; ..and store result in D + POP HL ; get addr of Drive Vector in ENV + LD (HL),E ; store new Drive Vector (low byte) + INC HL + LD (HL),D ; ..and high byte + CALL GQFLAG + OR A ; check quiet flag + JR NZ,SWAPDRX ; ..if quiet mode, skip over + CALL VPRINT + DEFB ' ...Drives ' + DEFB 0 + LD A,(DRV1ST) ; get # of first drive + ADD A,'A' ; make ascii letter + CALL COUT ; ..and display it + CALL VPRINT + DEFB ': and ' + DEFB 0 + LD A,(DRV2ND) ; get # of second drive + ADD A,'A' ; make ascii letter + CALL COUT ; ..and display it + CALL VPRINT + DEFB ': exchanged',CR,LF + DEFB 0 + + ; exit function +SWAPDRX: POP DE ; restore merged bit masked 1st+2nd drive + LD C,37 ; BDOS fn #37 Reset Drive(s) + CALL CPMBDOS + JP EXIT + + +M$ABORT: CALL VPRINT + DEFB ' ...aborting...',CR,LF + DEFB 0 + JP EXIT + + +;::::: HELP SCREEN + +HELP: CALL VPRINT + DEFB CR,LF,1 + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB 2,' exchanges the logical definition ' + DEFB 'of two physical disk drives',CR,LF + DEFB ' or partitions. Drive letters must be ' + DEFB 'in the range of "A"-"P".',CR,LF + DEFB ' The program is re-executable under ' + DEFB 'ZCPR with the "GO" command',CR,LF,LF + DEFB ' Syntax: ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' [:] [:]',CR,LF,LF + DEFB ' Examples:',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' A: E: - Exchange E drive with A',CR,LF + DEFB ' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' D,H - Exchange D drive with H',CR,LF + DEFB ' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' // - display this message',CR,LF + DEFB 0 + + +;::::: EXIT PROGRAM + +EXIT: LD SP,(STACK) ; restore stack + RET ; ..and return to system + + +;::::: SUPPORT FUNCTIONS + + ; "called" as a pseudo-routine that returns to caller + ; in: HL= target addr +JUMPHL: JP (HL) ; jump to addr in HL regs + + + ; parse nul-terminated string skipping separator chars + ; then fall through and check/convert drive letter + ; in: HL= ptr to string + ; out: A= drive number (or if invalid letter) + ; HL= ptr to byte after end of string + ; C-Flag set if (end of string) reached +FINDDRV: LD A,(HL) ; get byte + INC HL ; move ptr fwd + OR A ; check if (zero) = end of string + SCF ; prepare status indicator (C-Flag set) + RET Z ; ..if byte, return + CALL EVALSEP ; check if byte is a separator + JR NC,FINDDRV ; ..if so, get next char + ; else, fall through and check if letter is valid + + + ; evaluate if letter is a valid drive (A..P) and return as number + ; in: A= letter to check + ; out: A= drive number + ; C-Flag set if error, NC= ok +EVALDRV: CP 'A' ; is it lower than ascii 'A' ? + RET C ; ..return with C-Flag already set + CP 'P'+1 ; is it greater than ascii 'P' ? + CCF ; ..reverse C-Flag to set correct status + RET C ; and return + SUB 'A' ; else, convert to number + RET + + + ; evaluate char in register A whether it is a separator + ; (space, comma, colon, tab, zero) + ; in: A= char + ; out: C-Flag set if not separator, NC= char is separator +EVALSEP: CP ' ' ; is it ? + RET Z + CP ',' ; Comma ? + RET Z + CP ':' ; Colon ? + RET Z + CP TAB ; ? + RET Z + OR A ; (zero) ? + RET Z + SCF ; set C-Flag + RET + + + ; make bit mask for specified drive # + ; position of 1-bit represents drive in 16-bit word (similar to Drive Vector) + ; in: A= drive number + ; out: HL= bit mask +MKDRMSK: LD HL,1 ; set bit 0 + INC A ; ahead of loop, increase A +MKDRMS0: DEC A ; decrease A + RET Z ; ..if zero, finished + ADD HL,HL ; *2 (shift 1-bit to next position) + JR MKDRMS0 ; loop + + + ; make bit masks for new Drive Vector + ; maintaining a positive (bits set) map, and a negate version (bits reset) + ; in: HL= current Drive Vector (from ENV) + ; BC= bit mask w/ old position + ; DE= bit mask w/ new position +MKVCMSK: PUSH BC ; save regs + LD A,B + AND H ; mask high byte + LD B,A ; ..and store result back in B + LD A,C + AND L ; mask low byte + OR B ; check if invalid (= zero), ie. not mapped in Vector + POP BC ; restore regs + JR Z,MKVCMS0 ; if invalid drive, jump + + ; drive at new position exists in Drive Vector - set bit + PUSH HL + LD HL,(PDRVVCT) + LD A,H ; high byte first + OR D ; ..merge with new position + LD H,A ; and store result back in H + LD A,L ; low byte + OR E ; ..merge with new position + LD L,A ; and store result back in L + LD (PDRVVCT),HL ; save final result + POP HL + RET + + ; drive at new position does _not_ exist in Drive Vector - reset bit +MKVCMS0: PUSH HL + LD HL,(NDRVVCT) + LD A,D ; get high byte of new position + CPL ; invert it + AND H ; reset corresponding bit + LD H,A ; ..and store result in H + LD A,E ; get low byte of new position + CPL ; invert it + AND L ; reset corresponding bit + LD L,A ; ..and store result in L + LD (NDRVVCT),HL ; save final result + POP HL + RET + + + ; get Quiet Flag from Z3 Environment + ; in: - + ; out: A= Quiet Flag, defaults to A= 0 (not quiet) +GQFLAG: LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if invalid (= zero) + OR L + RET Z ; ..if so, return + LD A,40 ; else, move ptr forward + CALL ADDHLA ; to Quiet Flag + LD A,(HL) ; get value + RET ; ..and return + + + ; add A to HL (result in HL) +ADDHLA: ADD A,L ; add L + LD L,A ; store result in L + RET NC ; ..if no overflow, return + INC H ; else, increment H + RET + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PPRGNAM: LD A,(ENVADR+1) ; get high byte of ENVPTR + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; and let return from there + CALL VPRINT ; else, display default + DEFB 'BPSWAP' + DEFB 0 + RET + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; VLIB - 0x0536 +; Z3LIB - 0x0757 +; SYSLIB - 0x0805 +; end addr 0x0854 (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;::::: RAM STORAGE + + DSEG + +PDRVVCT: DEFW 0 ; new Drive Vector + ; (positive notation, bit _set_ for existing drives) +NDRVVCT: DEFW 0 ; new Drive Vector + ; (negative notation, bits _reset_ for existing drives) +BPBASE: DEFW 0 ; B/P Bios base addr +DRV1ST: DEFB 0 ; # of first drive +DRV2ND: DEFB 0 ; # of second drive + + DEFS 40H ; room for stack +STACK: DEFW 0 ; stack storage location + + END + + +;************************************************************************ +; Remarks jxl: +; BPSWAP.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file matches exactly the +; original BPSWAP.COM, i.e. no changes to the source were made. There +; seems to be one bug (marked with "##### BUG") at the beginning of the +; program. +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/bpsysgen.z80 b/Source/BPBIOS/UTIL/bpsysgen.z80 new file mode 100644 index 00000000..aebf8fe0 --- /dev/null +++ b/Source/BPBIOS/UTIL/bpsysgen.z80 @@ -0,0 +1,636 @@ + TITLE "Write B/P Bios System to system tracks of a disk" +;************************************************************************ +;* B P S Y S G E N * +;* Copy B/P Bios based Operating System to system tracks * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Dec 2024 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB * +;* * +;* A>Z80ASM BPSYSGEN/RS * +;* A>SLRNK BPSYSGEN/N,/A:100,/D:08CD,BPSYSGEN,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 10 +REV EQU ' ' + +DATE MACRO + DEFB '31 Aug 92' + ENDM + + +CTRLC EQU 03H ; Control-C character +BEL EQU 07H ; Bell character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) +CPMFCB2 EQU 6CH ; CP/M standard FCB #2 + +; From Z3LIB Get.. + EXTRN GETNAME, PRTNAME, Z3INIT, WHRENV + +; From SYSLIB Get.. + EXTRN PUTUD, GETUD, SUA, EPRINT, CRLF, CAPINE, CIN, COUT + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +BPSYSGEN: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0 ; addr of Z3 environment + +START: LD HL,(CPMBDOS+1) ; BDOS entry as starting point for Z3ENV search + CALL WHRENV ; get Z3 Environment + LD (ENVADR),HL ; ..store it + CALL Z3INIT ; init ENV ptr for Z3LIB modules + CALL GETNAME ; get actual program name + CALL GETQFLG ; check ENV quiet flag + AND A ; zero means 'verbose' i.e. not quiet + JR NZ,START1 ; ..if quiet mode, skip msg +START0: CALL EPRINT + DEFB 'B/P SYSGEN Utility V',VER/10+'0','.',VER MOD 10 + '0',REV + DATE + DEFB CR,LF,LF + DEFB 0 + +START1: CALL PUTUD ; currently logged in drive/user + LD HL,RESDISK ; prepare exit with resetting disk system + PUSH HL ; by putting addr of 'RESDISK' on stack + LD HL,(CPMBIOS+1) ; get BIOS entry addr + LD A,8*3 ; move forward to fn #9 SELDSK + CALL ADDHLA + LD DE,BIOSELD ; ptr to target addr + LD BC,8*3 ; bytes to copy (8 JP instructions, 3 bytes each) + LDIR ; ..copy + + + ; Evaluate command line (if invalid parameters, switch to interactive mode) +EVALCMD: LD HL,CPMFCB ; set ptr to standard FCB #1 + LD A,(HL) ; get drive + LD (SRCDRV),A ; ..and store it (SRC) + INC HL ; move ptr forard + LD A,(HL) ; get byte/char + CP '/' ; is this a help request ? + JP Z,HELP ; ..if so, jump display help + ; ..and quit (addr of exit routine on stack) + + ; syntax: BPSYSGEN [d:]fn[.ft] [d:] + ; drive #1 = source, drive #2 = destination + LD A,(CPMFCB2) ; get first byte of standard FCB #2 + LD (DSTDRV),A ; store drive # (DEST) + LD (DSTDR2),A ; ..and a copy (as indicator for cmdline input) + LD B,A ; remember value + LD A,(HL) ; get first char of filename in FCB #1 + CP ' ' ; is it ? + JP NZ,SRCRD0 ; ..if not, jump read sys file + LD A,B ; else, restore char (from FCB #2) + AND A ; is it ? + JP NZ,SRCREAD ; ..if not, jump read sys tracks + ; else, no source specified in command line + ; (switch to interactive mode) + LD A,(SRCDRV) ; get source drive number + LD (DSTDRV),A ; ..and overwrite destination drive number + + +;::::: SOURCE DRIVE + + ; interactive mode +SRCINP: CALL EPRINT + DEFB 'Source Drive (CR to skip)? ' + DEFB 0 + CALL CAPINE ; get user input + CALL CRLF + CP CR ; is it ? + JP Z,SRCRD1 ; ..if so, skip + SUB 40H ; else, convert ascii to number + LD (SRCDRV),A ; ..and store it + CALL EPRINT + DEFB 'Place source disk in drive ' + DEFB 0 + LD A,(SRCDRV) ; get source drive number + ADD A,40H ; convert to ascii + CALL COUT ; ..and display it + CALL EPRINT + DEFB ': and press return to continue...' + DEFB 0 +SRCINP0: CALL CIN ; get input + CP CTRLC ; is it ? + RET Z ; ..if so, return + CP CR ; ? + JR NZ,SRCINP0 ; ..if not, loop ask for new input + CALL CRLF + + + ; start reading +SRCREAD: CALL RDTRACK ; read system tracks of source disk + JR SRCRD1 ; ..and skip over +SRCRD0: CALL RDFILE ; read system file +SRCRD1: CALL CHKSYS ; check if a valid system was loaded/read + ; (fn _not_ implemented, simply returns) + JP NZ,E$NOSYS ; ..if not, jump error and exit + LD A,(DSTDRV) ; get # of destination disk + AND A + JP NZ,DSTINP0 ; ..if not empty (= zero), jump to continue + ; else, fall through and ask user + + +;::::: DESTINATION DRIVE + + ; interactive mode +DSTINP: CALL EPRINT + DEFB CR,LF,'Destination Drive (^C quits)? ' + DEFB 0 + CALL CAPINE ; get user input + CP CTRLC ; is it ? + RET Z ; ..if so, return + SUB 40H ; else, convert ascii to number + LD (DSTDRV),A ; ..and store it + CALL CRLF +DSTINP0: LD A,(DSTDR2) ; get copy of # destination disk + AND A ; check if valid + JR NZ,DSTWRIT ; ..if so, running in command line mode + ; ..continue writing to destination immediately + ; else, fall through and ask user for input + CALL EPRINT + DEFB 'Place destination disk in drive ' + DEFB 0 + LD A,(DSTDRV) ; get destination drive number + ADD A,40H ; convert to ascii + CALL COUT ; ..and display it + CALL EPRINT + DEFB ': and press return to continue...' + DEFB 0 +DSTINP1: CALL CIN ; get input + CP CTRLC ; is it ? + RET Z ; ..if so, return + CP CR ; ? + JR NZ,DSTINP1 ; ..if not, loop ask for new input + CALL CRLF + + + ; start writing + ; exit through "RET", addr of RESDISK routine is on stack +DSTWRIT: CALL WRTRACK + CALL GETQFLG + AND A ; check if quiet flag is set + RET NZ ; ..if not (= verbose), exit program + LD A,(DSTDR2) ; else, get copy of # dest. disk (indicator cmdline mode) + AND A ; check if valid + RET NZ ; ..if not, exit program + JP DSTINP ; else, loop ask for input + + + ; initiate a reset of disk system when returning to system +RESDISK: LD C,13 ; BDOS fn #13 (reset disk system) + CALL CPMBDOS + JP GETUD ; set Drive/User and let return from there + + +;::::: HELP SCREEN + +HELP: CALL PRGNAME + CALL EPRINT + DEFB ' Places a copy of the operating ' + DEFB 'system onto the system',CR,LF + DEFB ' tracks of a drive on the system.',CR,LF,LF + DEFB ' Syntax: ' + DEFB 0 + CALL PRGNAME + CALL EPRINT + DEFB ' [DIR:[Ufn.Ft]] [D:]',CR,LF,LF + DEFB ' Examples:',CR,LF,LF + DEFB ' ' + DEFB 0 + CALL PRGNAME + CALL EPRINT + DEFB ' - Execute in Interactive Mode',CR,LF + DEFB ' ' + DEFB 0 + CALL PRGNAME + CALL EPRINT + DEFB ' A: - Prompt for Source, ' + DEFB 'Place System onto A',CR,LF + DEFB ' ' + DEFB 0 + CALL PRGNAME + CALL EPRINT + DEFB ' B:ZSDOS64.COM - Get System from File, ' + DEFB 'Prompt for Drive',CR,LF + DEFB ' ' + DEFB 0 + CALL PRGNAME + CALL EPRINT + DEFB ' A: B: - Copy System from Drive A ' + DEFB 'to Drive B',CR,LF + DEFB ' ' + DEFB 0 + CALL PRGNAME + CALL EPRINT + DEFB ' // - display this help',CR,LF + DEFB 0 + RET + + +;::::: SUPPORT FUNCTIONS + + ; get Quiet Flag from Z3 Environment + ; in: - + ; out: A= Quiet Flag, defaults to A= 0 (not quiet) +GETQFLG: LD HL,(ENVADR) ; get local ENVPTR + LD A,H ; check if invalid (= zero) + OR L + RET Z ; ..if so, return + LD A,40 ; else, move ptr forward + CALL ADDHLA ; to Quiet Flag + LD A,(HL) ; get value + RET ; ..and return + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PRGNAME: LD A,(ENVADR+1) ; get high byte of ENVPTR + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; and let return from there + CALL EPRINT ; else, display default + DEFB 'BPSYSGEN' + DEFB 0 + RET + + + ; Read system tracks - source +RDTRACK: LD A,(SRCDRV) ; get source drive + CALL SELDRV ; and select it + JP Z,E$SRC ; ..if error, jump + LD (SRCDPH),HL ; store addr of DPH + LD A,10 ; move forward to DPB addr + CALL ADDHLA ; at DPH+10 + LD E,(HL) ; get DPB addr in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD (SRCDPB),HL ; ..and store DPB addr + LD E,(HL) ; get sectors per track in DE + INC HL ; at DPB+0 + LD D,(HL) + LD (SECTTRK),DE ; store value + LD A,12 ; move forward to track offset + CALL ADDHLA ; (beginning of directory) at DPB+13 + LD E,(HL) ; get track offset in DE + INC HL + LD D,(HL) + LD A,D ; check upper nybble + AND A ; is it zero ? + JP NZ,RDTRK0 ; ..if not, jump to adjust + OR E ; check lower nybble + JP Z,E$NOSYS ; ..if also zero, jump to error and exit + CP 4 ; check upper limit for # of system tracks + JR C,RDTRK1 ; ..if within boundaries, skip over +RDTRK0: LD DE,2 ; set (default) # of system tracks + +RDTRK1: LD B,E ; trk offset in B (counter) + LD DE,(SECTTRK) ; get sect/trk + LD HL,0 ; set initial value +RDTRK2: ADD HL,DE ; multiply by addition + DJNZ RDTRK2 ; loop till done + XOR A ; nullify A + OR H ; check if H is zero + JP NZ,E$NOSYS ; ..if not, jump error and exit + PUSH HL ; save regs + LD BC,0 + CALL BIOSTTR ; set track # 0 + POP HL ; restore regs + LD C,H ; move # of sectors containing system + LD B,L ; to BC (as counter) + LD DE,0 ; set intial value + LD HL,FILEBUF ; set target addr to file buffer + ; (at 0x0900, page-aligned after end of program) + +RDTRK3: PUSH DE ; save regs + PUSH BC + PUSH HL + LD HL,(SRCDPH) ; get addr of DPH + LD E,(HL) ; get skew table ptr in DE + INC HL + LD D,(HL) + CALL BIOSTRN ; translate logical sector # in BC + LD B,H ; move physical sector # to BC + LD C,L + CALL BIOSTSE ; ..and set (physical) sector + POP BC ; restore target addr + PUSH BC + CALL BIOSTDM ; set as DMA buffer addr + CALL BIOREAD ; read one sector + OR A ; check for error (A <> 0) + JP NZ,E$READ ; ..if error, jump + POP HL ; restore target addr + LD DE,128 ; increase by 128 bytes (1 sector) + ADD HL,DE + POP BC ; restore regs / clear stack + POP DE + DEC B ; decrease counter + RET Z ; ..if finished, return + INC C + LD A,C + AND 00000011b ; mask lower 2 bits + LD A,'.' + CALL Z,COUT ; display progress every 4 sectors (0.5 kB) + LD A,(SECTTRK) + CP C ; max. # sect/trk reached ? + JR NZ,RDTRK3 ; ..if not, loop + INC DE ; increase trk counter + LD C,0 ; reset sect counter + PUSH DE ; save regs + PUSH BC + PUSH HL + LD B,D ; copy trk # in BC + LD C,E + CALL BIOSTTR ; ..and set track # + POP HL ; restore regs + POP BC + POP DE + JR RDTRK3 ; loop + + + ; Read system file (img) - source +RDFILE: LD A,(ENVADR+1) ; get base addr of ENV + AND A ; check if invalid (= zero) + JR Z,RDFIL0 ; ..if no ENV, skip over + LD A,(CPMFCB+0DH) ; else, get user no from standard FCB #1 + CALL SUA ; ..and log in +RDFIL0: LD DE,CPMFCB ; set ptr to standard FCB #1 + LD C,15 ; BDOS fn #15 Open File + CALL BDOSSV + JP Z,E$SOPEN + LD HL,32 ; ptr to current record + ADD HL,DE + LD (HL),16 ; set # of current record + ; (skip 16 records = 2kB, MOVSYS boot loader code) + LD HL,FILEBUF-128 ; set addr of file buffer (-128 ahead of loop) + +RDFIL1: LD A,128 ; move forward by 128 bytes (1 sector) + CALL ADDHLA + EX DE,HL ; swap regs + LD C,26 ; BDOS fn #26 Set DMA Address + CALL BDOSSV + EX DE,HL ; swap regs back + LD C,20 ; BDOS fn #20 Read Sequentially + CALL BDOSSV + DEC A ; A= 1 returned means EOF, so decrease A + JR Z,RDFIL1 ; ..if zero, continue with next sector + LD C,16 ; BDOS fn #16 Close File + JP BDOSSV + + + ; Write system tracks - destination +WRTRACK: LD A,(DSTDRV) ; get destination drive + CALL SELDRV ; and select it + JP Z,E$DEST ; ..if error, jump and exit + LD (DSTDPH),HL ; store addr of DPH + LD A,10 ; move forward to DPB addr + CALL ADDHLA ; at DPH+10 + LD E,(HL) ; get DPB addr in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD (DSTDPB),HL ; ..and store DPB addr + LD E,(HL) ; get sectors per track in DE + INC HL ; at DPB+0 + LD D,(HL) + LD (SECTTRK),DE ; store value + LD A,12 ; move forward to track offset + CALL ADDHLA ; (beginning of directory) at DPB+13 + LD E,(HL) ; get track offset in DE + INC HL + LD D,(HL) + LD A,D ; check upper nybble + AND A ; is it zero ? + JP NZ,WRTRK0 ; ..if not, jump to adjust + OR E ; check lower nybble + JP Z,E$NOSYS ; ..if also zero, jump to error and exit + CP 4 ; check upper limit for # of system tracks + JR C,WRTRK1 ; ..if within boundaries, skip over + +WRTRK0: LD DE,2 ; set (default) # of system tracks + +WRTRK1: LD B,E ; trk offset in B (counter) + LD DE,(SECTTRK) ; get sect/trk + LD HL,0 ; set initial value +WRTRK2: ADD HL,DE ; multiply by addition + DJNZ WRTRK2 ; loop till done + XOR A ; nullify A + OR H ; check if H is zero + JP NZ,E$NOSYS ; ..if not, jump error and exit + PUSH HL ; save regs + LD BC,0 + CALL BIOSTTR ; set track # 0 + POP HL ; save regs + LD C,H ; move # of sectors containing system + LD B,L ; to BC (as counter) + LD DE,0 ; set initial value + LD HL,FILEBUF ; set origin addr (file buffer) + +WRTRK3: PUSH DE ; save regs + PUSH BC + PUSH HL + LD HL,(DSTDPH) ; get addr of DPH + LD E,(HL) ; get skew table ptr in DE + INC HL + LD D,(HL) + CALL BIOSTRN ; translate logical sector # in BC + LD B,H ; move physical sector # to BC + LD C,L + CALL BIOSTSE ; ..and set (physical) sector + POP BC ; restore origin addr + PUSH BC + CALL BIOSTDM ; set as DMA buffer addr + LD C,0 + CALL BIOWRIT ; write one sector + OR A ; check for error (A <> 0) + JP NZ,E$WRITE ; ..if error, jump + POP HL ; restore origin addr + LD DE,128 ; ..and increase by 128 bytes (1 sector) + ADD HL,DE + POP BC ; restore regs / clear stack + POP DE + DEC B ; decrease counter + JR NZ,WRTRK4 ; ..if not finished, continue + LD C,1 ; else, force write (flush to disk) + JP BIOWRIT ; ..and let return from there + +WRTRK4: INC C + LD A,C + AND 00000011b ; mask lower 2 bits + LD A,'.' + CALL Z,COUT ; display progress every 4 sectors (0.5 kB) + LD A,(SECTTRK) + CP C ; max. # sect/trk reached ? + JR NZ,WRTRK3 ; ..if not, loop + INC DE ; increase trk counter + LD C,0 ; reset sect counter + PUSH DE ; save regs + PUSH BC + PUSH HL + LD B,D ; copy trk # in BC + LD C,E + CALL BIOSTTR ; ..and set track + POP HL ; restore regs + POP BC + POP DE + JR WRTRK3 ; loop + + + ; check if a valid B/P Bios was loaded + ; *** function not implemented *** + ; in: - + ; out: Z-Flag set if ok, NZ= error +CHKSYS: XOR A ; always return Z-Flag set + RET + + + ; select disk drive + ; in: A= drive number (one-based) + ; out: Z-Flag set if error +SELDRV: DEC A ; -1 to comply with CP/M BIOS standards + LD C,A + LD E,0 + CALL BIOSELD ; call BIOS fn #9 directly + LD A,H + OR L + RET + + + ; call BDOS saving regs BC, DE, HL + ; out: A= 0 and Z-Flag set if not found +BDOSSV: PUSH BC + PUSH DE + PUSH HL + CALL CPMBDOS + INC A ; 0xFF --> 0x00 if not found + POP HL + POP DE + POP BC + RET + + + ; add A to HL (result in HL) +ADDHLA: ADD A,L ; add L + LD L,A ; store result in L + RET NC ; ..if no overflow, return + INC H ; else, increment H + RET + + +;::::: ERROR MESSAGES + + ; display msg on CON: then exit with warm boot +E$READ: CALL EPRINT + DEFB BEL,'*** Read error' + DEFB 0 + JP EXIT + +E$SRC: CALL EPRINT + DEFB BEL,'*** Bad source!' + DEFB 0 + JP EXIT + +E$WRITE: CALL EPRINT + DEFB BEL,'*** Write error' + DEFB 0 + JP EXIT + +E$DEST: CALL EPRINT + DEFB BEL,'*** Bad destination!' + DEFB 0 + JP EXIT + +E$NOSYS: CALL EPRINT + DEFB BEL,'*** No system!' + DEFB 0 + JP EXIT + +E$SOPEN: CALL EPRINT + DEFB BEL,"*** Can't open source file!" + DEFB 0 + + +;::::: EXIT PROGRAM + +EXIT: CALL CRLF + LD HL,0 ; set addr + JP (HL) ; and jump to CP/M WBOOT + + +;::::: BIOS JUMPS (for direct calls) + + ; area is filled with actual jumps at runtime + ; to call BIOS fn's directly +BIOSELD: JP 0 ; fn #9 SELDSK select disk +BIOSTTR: JP 0 ; fn #10 SETTRK set track +BIOSTSE: JP 0 ; fn #11 SETSEC set sector +BIOSTDM: JP 0 ; fn #12 SETDMA set buffer addr +BIOREAD: JP 0 ; fn #13 READ read one sector +BIOWRIT: JP 0 ; fn #14 WRITE write one sector +BIOLIST: JP 0 ; fn #15 LISTST list status (not used) +BIOSTRN: JP 0 ; fn #16 SECTRN sector translation + + + +;::::: RAM STORAGE (not in DSEG !) + +SECTTRK: DEFW 0 ; sectors per track (sect/trk), used for src+dst +SRCDPH: DEFW 0 ; source: addr of Disk Parameter Header (DPH) +SRCDPB: DEFW 0 ; source: addr of Disk Parameter Block (DPB) +DSTDPH: DEFW 0 ; destination: addr of DPH +DSTDPB: DEFW 0 ; destination: addr of DPB +SRCDRV: DEFB 0 ; source: drive # (from standard FCB #1) +DSTDRV: DEFB 0 ; destination drive # +DSTDR2: DEFB 0 ; destination drive # (copy) + ; extracted from cmdline, used as indicator for run mode + + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; Z3LIB - 0x0735 +; SYSLIB - 0x07e3 +; end addr 0x08cc (DSEG Z3+SYS = 4 bytes) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + ; buffer start addr = 0x0900 +FILEBUF: EQU $+512-($-BPSYSGEN AND 255) + + DSEG + + END + + +;************************************************************************ +; Remarks jxl: +; BPSYSGEN.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file matches exactly the +; original BPSYSGEN.COM, i.e. no changes to the source were made. +; The program is pretty straightforward. It supports a command line +; mode and an interactive mode. (Code portions for the latter are pretty +; short.) Functionality to check if the running system is valid, was +; not implemented. Since other B/P Bios tools perform such checks, this +; is rather surprising. +; An interesting approach was used to end the program and literally +; return to the system. The address of RESDISK routine is pushed on the +; stack at the very beginning. +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/confz4.z80 b/Source/BPBIOS/UTIL/confz4.z80 new file mode 100644 index 00000000..65bc670e --- /dev/null +++ b/Source/BPBIOS/UTIL/confz4.z80 @@ -0,0 +1,489 @@ + TITLE "ZCPR 4 Configuration Utility" +;************************************************************************ +;* C O N F Z 4 * +;* Configure ZCPR 4 options * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Jan 2025 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: Z3LIB, SYSLIB * +;* * +;* A>Z80ASM CONFZ4/RS * +;* A>SLRNK CONFZ4/N,/A:100,/D:080A,CONFZ4,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 10 +REV EQU ' ' + +DATE MACRO + DEFB '18 Nov 95' + ENDM + + +BEL EQU 07H ; Bell character +BS EQU 08H ; Backspace character +TAB EQU 09H ; Tab character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) +CPMDMA EQU 80H ; CP/M standard DMA buffer + + +; From Z3LIB Get.. + EXTRN GETNAME, PRTNAME, Z3INIT, WHRENV + +; From SYSLIB Get.. + EXTRN EPRINT, CRLF, CAPIN, PA2HC, COUT + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +CONFZ4: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0 ; addr of Z3 environment + DEFW CONFZ4 ; type 4 filler + + DEFB 'CONFZ41 ',0 ; configuration name + +START: LD (STACK),SP + LD SP,STACK + CALL EPRINT + DEFB 'B/P System Command Processor Configuration V' + DEFB VER/10+'0','.',VER MOD 10 + '0',REV,' ' + DATE + DEFB CR,LF + DEFB 0 + + CALL INITZ3 ; find Z3ENV and check Wheel Byte + CALL GETNAME ; get actual program name + CALL CHKHLP ; check if help was requested + SUB ' ' ; ##### convert to ... ?? + LD (UNUSED1),A ; ##### and store (not used at all) + CALL CHKSYS ; check if running B/P Bios + LD HL,(BPCNFG) ; addr CONFIG area + INC HL ; move ptr fwd + INC HL + LD A,(HL) ; get option flags (OPTF1) + AND 00000001B ; mask bit 0 (0= unbanked, 1= banked) + LD (BPBNKD),A ; store indicator + JR NZ,CHKXENV ; ..if banked, jump to continue + CALL EPRINT ; else, display msg and exit + DEFB CR,LF,'+++ Not Banked System..aborting...!',BEL + DEFB 0 + JP EXIT + + ; check for extended environment +CHKXENV: INC HL ; move ptr fwd + INC HL + INC HL + LD A,(HL) ; get first system bank (SYSBNK) + LD (SYSBNK),A ; store it + LD HL,(ENVADR) ; addr ENV + LD DE,8 ; offset to type + ADD HL,DE ; move ptr + BIT 7,(HL) ; check high bit (= 0x80+ for extended Z3ENV) + JR NZ,CHKVERS ; ..if set, jump to continue + CALL EPRINT + DEFB CR,LF,'+++ Not Extended Environment..aborting..!',BEL + DEFB 0 + JP EXIT + + ; check ZCPR version +CHKVERS + LD DE,55 ; offset addr CPR (8+55 = 63) + ADD HL,DE ; move ptr + LD E,(HL) ; get addr in DE + INC HL + LD D,(HL) + LD HL,5 ; offset to version byte in ZCPR 4.x + ; (code starts with JP.., JR.., VERSION) + ADD HL,DE ; move ptr + LD A,(HL) ; get byte + CP 41H ; is it 4.1 (or higher) ? + JR NC,PVRSION ; ..if so, jump to continue + PUSH AF ; else, display error msg and exit + CALL EPRINT + DEFB CR,LF,BEL,"+++ Can't Configure Vers : " + DEFB 0 + POP AF + CALL PA2HC + CALL EPRINT + DEFB ' of Command Processor!' + DEFB 0 + JP EXIT + + ; display version +PVRSION: PUSH AF + CALL EPRINT + DEFB CR,LF,' Configuring Options for CPR Version : ' + DEFB 0 + POP AF ; restore version # + PUSH AF + RRCA ; rotate upper nybble to lower + RRCA ; (major version #) + RRCA + RRCA + AND 00001111B ; mask lower nybble + ADD A,'0' ; ..and convert to ascii + CALL COUT ; display major version # + LD A,'.' + CALL COUT + POP AF ; restore version # + AND 00001111B ; mask lower nybble + ADD A,'0' ; ..and convert to ascii + CALL COUT ; display minor version # + CALL CRLF + LD DE,10 ; move forward by another 10 bytes + ADD HL,DE ; (in Z40-1.Z80 three bytes are defined as 'Space + ; reserved for expansion' - this is the last byte) + LD (PFLGADR),HL ; store addr + + ; branch interactive/cmdline mode + LD A,(CPMFCB+1) ; get first char from cmdline + CP ' ' ; is it ? + JP NZ,EVALCMD ; ..if not, jump cmdline mode + CALL EPRINT ; else, interactive mode + DEFB CR,LF,'Turn Time ON in Prompt Line ([Y]/N)? : ' + DEFB 0 + CALL CAPIN ; get user input + LD BC,0FE01H ; default to ON, European format + ; ( 11111110 00000001 B ) + CP 'N' ; is it 'N' ? + JR NZ,RUNIMOD ; ..if not, skip over + LD C,0 ; else, clear C (indicating OFF) + + ; run interactive mode +RUNIMOD: CALL SETOPTB ; set byte + CALL EPRINT + DEFB CR,LF,'US (mm/dd/yy) or European (dd.mm.yy) Dates ([U]/E) : ' + DEFB 0 + CALL CAPIN ; get user input + LD BC,0FD00H ; default to US format + ; ( 11111101 00000000 B ) + CP 'E' ; is it 'E' ? + JR NZ,RUNIM0 ; ..if not, skip over + LD C,00000010B ; else, set European format +RUNIM0: CALL SETOPTB ; set byte + JP EXIT + + ; evaluate command line +EVALCMD: LD HL,CPMDMA + LD A,(HL) ; get # of chars + INC HL ; set ptr to start of cmdline + PUSH HL ; save regs + CALL ADDHLA ; move ptr to end of cmdline + LD (HL),0 ; set terminator + POP HL ; restore start of cmdline + CALL SKPWHSP ; skip any whitespace at the beginning + LD A,(HL) ; get char + CP '/' ; is it option char ? + JR NZ,ECMD0 ; ..if not, skip over + INC HL ; else, move ptr forward +ECMD0: LD A,(HL) ; get byte + OR A + JR Z,ECMD1 ; ..if zero, jump and exit + CALL CMPRMPT ; else, attempt processing option + JR ECMD0 ; ..and loop + +ECMD1: JP EXIT + + + ; cmdline: /T[+|-] Toggle Time in Prompt + ; option byte, bit 0 = 0 off / 1 on + ; + ; cmdline: /U /E US/Europe format + ; option byte, bit 1 = 0 US / 1 European + + ; process prompt on/off +CMPRMPT: CP 'T' ; is char 'T' (Toggle) ? + JR NZ,CMFORMT ; ..if not, try processing format option + INC HL + LD C,00000001B ; prepare for ON + LD A,(HL) ; get next char + CP '+' ; is it '+' ? + JR Z,CMPRMP0 ; ..if so, skip over + LD C,00000000B ; else, prepare for OFF + CP '-' ; is it '-' ? + JR NZ,CMFORMT ; ..if not, rather check format +CMPRMP0: LD B,11111110B ; default to European format + +CMSETOP: CALL SETOPTB ; set +CMSETX: INC HL ; move ptr fwd + RET ; ..and exit + + ; process format +CMFORMT: LD B,11111101B ; default to ON (else, format wouldn't make sense) + LD C,00000010B ; prepare for European + CP 'E' ; is it 'E' ? + JR Z,CMSETOP ; ..if so, set byte + LD C,00000000B ; else, prepare for US + CP 'U' ; is it 'U' ? + JR Z,CMSETOP ; ..if so, set byte + JR CMSETX ; jump exit + + + ; set option byte + ; in: B= format (US/European) + ; C= on/off +SETOPTB: EX DE,HL ; swap regs (save HL) + LD HL,(PFLGADR) ; addr of Prompt flag in ZCPR4 config area + LD A,(HL) ; get byte + AND B ; apply format setting + OR C ; merge on/off setting + LD (HL),A ; ..and save byte + LD HL,010FH ; offset to option byte in SYSBNK + CALL GETFRB ; get current setting + AND B ; apply format setting + OR C ; merge on/off setting + CALL SETINB ; ..and write back + EX DE,HL + RET + + + ; check if help was requested + ; get first token from command line (in FCB #1) +CHKHLP: LD HL,CPMFCB+1 + LD A,(HL) ; get char + CP '/' ; is this a help request ? + RET NZ ; ..if not, return + INC HL ; move ptr fwd + LD A,(HL) ; check following char + CP '/' ; if it is also '/' + RET NZ ; ..if not, return + ; else, fall through and show help screen + + +;::::: HELP SCREEN + +HELP: CALL EPRINT + DEFB CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' Configure Running B/P Command Processor Options.',CR,LF,LF + DEFB ' Syntax:',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' - Configure in Interactive Mode',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' /T[+|-] - Toggle Time in Prompt [Set On/Off]',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' /E - Display Date in European (dd.mm.yy) form',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' /U - Display Date in US (mm/dd/yy) form',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' // - display this screen',CR,LF,LF + DEFB ' Arguments may be combined as:',CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' /T+U - Turn Time On, US-style Date Display',CR,LF,LF + DEFB 'This program will only run in Banked B/P Systems.',CR,LF + DEFB 0 + + +;::::: EXIT PROGRAM + +EXIT: CALL CRLF + LD SP,(STACK) ; restore stack + RET ; ..and return to system + + +;::::: SUPPORT FUNCTIONS + + ; init Z3ENV and check Wheel byte + ; if not successful, exit program +INITZ3: LD HL,(CPMBDOS+1) + CALL WHRENV ; find Z3 Environment Descriptor + LD (ENVADR),HL ; store ENV addr + LD A,H ; check if invalid (= zero) + OR L + JP Z,E$BPBIO ; ..if so, jump exit + CALL Z3INIT ; init for Z3LIB routines + LD A,41 ; offset to addr wheel byte (Z3WHL) + CALL ADDHLA ; move ptr fwd + LD E,(HL) ; get addr in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD A,(HL) ; get value of wheel byte + AND A ; check if zero + RET NZ ; ..if not ON, return + CALL EPRINT ; else, display message and exit + DEFB BEL,CR,LF,'Must be wheel to Execute !',CR,LF + DEFB 0 + JR EXIT + + + ; check if running under B/P Bios + ; if not, program is terminated +CHKSYS: LD HL,(CPMBIOS+1) ; get warm boot addr (BIOS fn #1) + LD L,30*3 ; adjust ptr to fn #30 + LD A,(HL) ; check byte at ptr location + CP 0C3H ; is it opcode 0xC3 (JP) ? + JR NZ,E$BPBIO ; ..if not, jump error and exit + CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO) + LD (BPADDR),BC ; store base addr of B/P Bios + LD (BPCNFG),DE ; " config area addr + LD HL,-6 ; move ptr 6 bytes backward + ADD HL,DE ; (signature string) + LD A,(HL) ; get byte + CP 'B' ; is it 'B' ? + JR NZ,E$BPBIO ; ..if not, jump error and exit + INC HL + LD A,(HL) ; get next byte + CP '/' ; is it '/' ? + JR NZ,E$BPBIO ; ..if not, jump error and exit + INC HL + LD A,(HL) ; and get next byte + CP 'P' ; is it 'P' ? + RET Z ; ..if so, return + ; else, fall through (error and exit) + + + ; error msg +E$BPBIO: CALL EPRINT + DEFB CR,LF,BEL,'Not B/P Bios, aborting...!',CR,LF + DEFB 0 + RST 0 + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PPRGNAM: LD A,(ENVADR+1) ; get high byte of local ENVPTR + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; and let return from there + CALL EPRINT ; else, display default + DEFB 'SIZERAM' ; apparently wrong :-) + DEFB 0 + RET + + + ; skip whitespace ( or ) + ; in: HL= ptr to string + ; out: HL= ptr to first char <> whitespace +SKPWHSP: DEC HL ; prior to loop, set ptr back +SKPWH0: INC HL ; move ptr fwd + LD A,(HL) ; get byte + CP ' ' ; is it ? + JR Z,SKPWH0 ; ..if so, loop + CP TAB ; is it ? + JR Z,SKPWH0 ; ..if so, loop + RET ; else, return + + + ; add A to HL (result in HL) +ADDHLA: ADD A,L ; add L + LD L,A ; store result in L + RET NC ; ..if no overflow, return + INC H ; else, increment H + RET + + + ; the following routines rearrange Top of Stack by injecting an + ; intermediate return addr, and putting the Bios fn call on top + ; so that HL regs are preserved + ; order of steps: + ; [1] HL (= addr) is pushed onto stack + ; [2] intermediate return addr is swapped to Top of Stack + ; [3] HL (= addr) is pushed onto stack again + ; [4] Bios fn JP addr is swapped to Top of Stack + ; [5] Bios is "called" through RET, and returns to intermediate addr + + ; get byte from ram bank (in C) - in the form LD A,(HL) + ; in: HL= addr + ; out: A= byte +GETFRB: PUSH BC + PUSH HL ; save addr + LD BC,(SYSBNK) ; C= System Bank, B= not used + LD HL,GETFRB0 ; load return addr + EX (SP),HL ; put it on stack + PUSH HL ; save HL again (previous top of stack) + LD HL,(BPADDR) ; get B/P Bios base addr + LD L,35*3 ; adjust ptr to fn #35 (FRGETB) + EX (SP),HL ; put addr on stack + RET ; ..and "call" Bios fn through stack + +GETFRB0: POP BC ; restore regs + RET ; ..and finally return + + ; set byte in ram bank (in C) - in the form LD (HL),A + ; in: HL= addr, A= byte to set +SETINB: PUSH BC + PUSH HL ; save addr + LD BC,(SYSBNK) + LD HL,GETFRB0 ; load return addr + EX (SP),HL ; put it on stack + PUSH HL ; save HL again (previous top of stack) + LD HL,(BPADDR) ; get B/P Bios base addr + LD L,37*3 ; adjust ptr to fn #37 (FRPUTB) + EX (SP),HL + RET ; ..and "call" Bios fn through stack + + + ; "called" as a pseudo-routine that returns to caller + ; in: HL= target addr +JUMPHL: JP (HL) ; jump to addr in HL regs + + +;::::: RAM STORAGE (_no_ DSEG !) + +PFLGADR: DEFW 0 ; addr of Prompt flag (last reserved option byte) +SYSBNK: DEFB 0 ; beginning of System Bank(s) +UNUSED1: DEFB 0 ; ##### +BPADDR: DEFW 0 ; base addr B/P Bios +BPCNFG: DEFW 0 ; addr of B/P Bios CONFIG area +BPBNKD: DEFB 0 ; indicator banked system + ; (bit 0 of OPTF1, 0= unbanked, 1= banked) + + DEFS 30H ; room for stack +STACK: DEFW 0 ; stack storage location + + + END + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; Z3LIB - 0x06b4 +; SYSLIB - 0x0762 +; end addr 0x080a (begin DSEG of LIB's) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;************************************************************************ +; Remarks jxl: +; CONFZ4.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file matches exactly the +; original CONFZ4.COM, i.e. no changes to the source were made. Possible +; optimisations detected during disassembly are marked with "#####" in the +; comment. +; The program seems to be in an early stage as it does not comply with +; general coding standards seen by HFB/CWC. For instance, no DSEG is used. +; Only 2 options can be configured with this program. It is not known +; whether provisions were made in ZCPR v4.1 for further options. +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/hashini.z80 b/Source/BPBIOS/UTIL/hashini.z80 new file mode 100644 index 00000000..a74f8e02 --- /dev/null +++ b/Source/BPBIOS/UTIL/hashini.z80 @@ -0,0 +1,752 @@ + TITLE "HASHINI Drive Utility" +;************************************************************************ +;* H A S H I N I * +;* Set Drive Volume Name and Init for File Stamps * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Mar 2025 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: Z3LIB, SYSLIB * +;* * +;* A>Z80ASM HASHINI/RS * +;* A>SLRNK HASHINI/N,/A:100,/D:09E5,HASHINI,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 02 +REV EQU ' ' + +DATE MACRO + DEFB '12 Sep 93' + ENDM + + +CTRLC EQU 03H ; Control-C character +BEL EQU 07H ; Bell character +BS EQU 08H ; Backspace character +TAB EQU 09H ; Tab character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character +ESC EQU 1BH ; Escape character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) +CPMFCB2 EQU 6CH ; CP/M standard FCB #2 +CPMDMA EQU 80H ; CP/M standard DMA buffer + + +; From Z3LIB Get.. + EXTRN GETNAME, PRTNAME, GETQUIET, Z3INIT + +; From SYSLIB Get.. + EXTRN BLINE, EPRINT, CRLF, CAPIN, COUT, CODEND + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +HASHINI: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + DEFB 1 + +ENVADR: DEFW 0 ; addr of Z3 environment + + DEFB 1 + DEFB 'HASHINI ' + DEFB 0 + + ; config area (for ZNCFG.COM) +CFGAREA: DEFB 0 ; default value for program quiet flag + DEFB 0FFH + +START: LD (STACK),SP ; save stack + LD SP,STACK + CALL Z3INIT ; init ENVPTR for Z3LIB routines + CALL GETNAME ; get ptr to program name + CALL GETQUIET ; check ENV quiet flag + LD HL,CFGAREA ; ptr to config area + OR (HL) ; merge flags (ENV + program) + LD (PRGQFLG),A ; store program quiet flag + CALL EPRINT + DEFB CR,LF,'Initialize Volume Label and File Stamps Ver ' + DEFB VER/10+'0','.',VER MOD 10 + '0',REV,' ' + DATE + DEFB CR,LF + DEFB 0 + LD C,25 ; get current disk (BDOS fn #25) + CALL CPMBDOS + LD (OLDDRV),A ; remember drive # + CALL EVALCMD ; evaluate command line + JR INITWSPC + + +;::::: MAIN LOOP + +START0: LD SP,STACK ; reset stack pointer + CALL EPRINT + DEFB CR,LF,LF,'Initialize another Disk? (Y/[N]) : ' + DEFB 0 + CALL CINPUT ; get user input + CP 'Y' ; is it 'Y' ? + JP NZ,EXIT ; ..if not, jump to exit + CALL SELODRV ; restore previously logged drive + CALL CRLF + OR 0FFH ; from now on run interactively + + ; init workspace (ram storage) +INITWSPC: LD (RUNMODE),A ; store mode + LD HL,WSPC ; clear workspace data area + LD B,(STACK-WSPC)-3 + CALL FILLZ + + +;::::: DISK DRIVE + +GETDISK: LD A,(RUNMODE) ; get mode + OR A ; running in cmdline mode ? + JR Z,GETVOLN ; ..if so, drive is known, jump to continue + + ; interactive mode - ask for disk to initialize +IMDISK: CALL EPRINT + DEFB CR,LF,LF,'Initialize which Disk for ' + DEFB 0 + LD A,(STMPTYP) ; stamp format indicator + OR A ; is it P2Dos ? + JR NZ,IMDISK1 ; ..if not, jump to continue + CALL EPRINT ; display chosen format + DEFB 'P2DOS' + DEFB 0 + JR IMDISK2 ; skip over +IMDISK1: CALL EPRINT + DEFB 'NZTIME' + DEFB 0 + +IMDISK2: CALL EPRINT + DEFB ' Date/Time Stamps? : ' + DEFB 0 + CALL CINPUT ; get user input + CP 'A' ; disk drive letter must be + JR C,IMDISK3 ; between 'A' and 'P' + CP 'P'+1 + JR C,IMDISK4 +IMDISK3: CALL EPRINT ; else, notify user and loop + DEFB BEL,BS,' ',BS + DEFB 0 + JR IMDISK + +IMDISK4: LD (CURRDSK),A ; store disk drive letter + + +;::::: VOLUME NAME + +GETVOLN: LD A,(VOLNAME) + OR A + JR NZ,IMVOLN3 + + ; interactive mode - ask for volume name +IMVOLN: CALL EPRINT + DEFB CR,LF,'Enter Volume Name [1-11 chars] : ' + DEFB 0 + LD HL,CPMDMA ; set ptr to standard buffer + LD (HL),11 ; prepare char count (max. 11 chars) + XOR A ; clear A + LD (CPMDMA+1),A ; prepare end-of-string + DEC A ; let capitalize (A= non-zero) + CALL BLINE ; get user input + LD A,(HL) ; check char count + OR A ; is it empty string (nothing entered) ? + JR Z,IMVOLN ; ..if so, loop + LD DE,VOLNAME ; point to volname buffer +IMVOLN1: LD A,(HL) ; get char + LDI ; ..and copy over + OR A ; end of string ? + JR NZ,IMVOLN1 ; ..if not, loop + +IMVOLN3: LD A,(PRGQFLG) ; get program quiet flag + OR A ; running in quiet mode ? + JR Z,DSKPROC ; ..if so, skip over + CALL EPRINT + DEFB CR,LF,' Confirm Initialize Drive ' + DEFB 0 + LD A,(CURRDSK) + CALL COUT + CALL EPRINT + DEFB ': (Y/[N]) ' + DEFB 0 + CALL CINPUT ; get user input + CP 'Y' + JP NZ,FINISH + + +;::::: PROCESS DISK + +DSKPROC: LD A,(CURRDSK) ; get current disk drive letter + SUB 'A' ; make numeric + PUSH AF ; save regs + LD E,A ; drive # in E + CALL BDSELD ; select disk drive (BDOS call) + CALL EPRINT ; display warning + DEFB BEL,CR,LF,'+++ Existing Files will be ERASED! +++' + DEFB CR,LF,' --- Proceed anyway (Y/[N]) : ' + DEFB 0 + + CALL CINPUT ; get user input + CP 'Y' ; is it 'Y' ? + JP NZ,FINISH ; ..if not, jump to finish processing + POP AF ; restore regs + LD C,A ; drive # in C + CALL BIOSELD ; select disk drive (BIOS call) + LD A,H ; check if DPH addr is valid + OR L + JP Z,E$DRVILL ; ..if not, jump display error msg and exit + + ; get parameters of current disk drive + LD E,(HL) ; get addr of skew table in DE + INC HL + LD D,(HL) + LD (SKEWTBL),DE ; and store value + LD DE,9 + ADD HL,DE ; move ptr fwd (to DPH+10) + LD E,(HL) ; addr of DPB in DE + INC HL + LD D,(HL) + PUSH DE ; move addr to IX + POP IX + + ; ??? ##### CODEND not used + CALL CODEND ; get first free memory page addr in HL + + LD D,(IX+8) ; get DirMax in DE + LD E,(IX+7) ; (max. dir entries -1) + INC DE ; +1 + LD (DIRMAX),DE ; store value + SRL D ; /2 + RR E + SRL D ; /4 + RR E + LD (STMPMAX),DE ; store value + ; (1 stamp dir entry for 4 file dir entries) + LD BC,0 + LD HL,CPMDMA ; set to standard buffer + PUSH DE ; save regs + PUSH BC + LD DE,VOLNAME ; ptr to volume name + LD A,(DE) ; get char + OR A ; is it zero ? ( means empty string) + LD B,3*32 ; prepare counter for 3 stamp entries + JR Z,MKSTMP ; ..if no volume name, jump to continue + + ; make a volume name entry + ; HL= ptr to standard buffer, DE= ptr to VOLNAME + ; B= char count, C= char + LD (HL),020H ; set first byte of dir entry (user area) + ; to 0x20 - indicates time stamp + INC HL ; move ptr fwd + LD B,11 ; number of chars +MKVOLN: LD A,(DE) ; get VOLNAME char in A + LD C,' ' ; prepare for byte + OR A ; end of string ? + JR Z,MKVOLN1 ; ..if so, skip over + LD C,A ; else, get char in C + INC DE ; move VOLNAME ptr forward +MKVOLN1: LD (HL),C ; copy char to buffer + INC HL ; move ptr fwd + DJNZ MKVOLN ; loop till done + LD B,32-12 ; clear remaining bytes of stamp entry + CALL FILLZ + LD B,2*32 ; fill next 2 stamp entries + + ; make a stamp entry and write to dir +MKSTMP: LD A,0E5H ; CP/M default byte for free dir entries + CALL FILLA ; fill stamp entries + LD A,(STMPTYP) ; get chosen stamp format (0x00 = P2Dos, 0xFF = NZTime) + OR A ; ..and check + LD A,021H ; prepare for P2Dos + JR Z,MKSTMP1 ; ..if so, skip over + LD A,0A1H ; else, prepare for NZTime +MKSTMP1: LD (HL),A ; store byte + INC HL ; move ptr fwd + LD B,32-1 ; ..and clear remaining bytes of stamp entry + CALL FILLZ + POP BC ; restore regs + POP DE + CALL PVBOSE ; if verbose mode, display msg + DEFB CR,LF,'...Writing Initialized Directory...' + DEFB 0 + + LD DE,0 ; initial start # + LD (STMPCUR),DE ; set # of current stamp entry + CALL WRSTMP ; ..and write stamp to directory + LD HL,CPMDMA ; reset ptr to begin of standard buffer + LD A,0E5H ; clear first part of stamp entry + LD B,32 + CALL FILLA +MKSTMP2: CALL WRSTMP ; ..and write next stamp entry + LD HL,(STMPCUR) ; get current # + LD DE,(STMPMAX) ; get max. # + OR A ; clear flags + SBC HL,DE ; check if all entries were written + ADD HL,DE + JR NZ,MKSTMP2 ; ..if not, loop + LD BC,1 ; set C= 1 to indicate Directory Write (forced) + CALL BIOWRIT ; ..and perform through BIOS + JP DSKDONE + + + ; display help and exit +HLPEXIT: XOR A ; clear A + LD (RUNMODE),A ; ..and store mode (cmdline) + JR HELP + +E$DRVILL: CALL EPRINT ; display error msg and fall through + DEFB CR,LF,LF,BEL,'Illegal drive name' + DEFB 0 + + +;::::: HELP + +HELP: CALL EPRINT + DEFB CR,LF,'Usage: Set Drive Volume Name & ' + DEFB 'Initialize for P2Dos/NzTime file stamps',CR,LF,LF + DEFB 'Syntax:',CR,LF,TAB + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' [d:][volname] [/][P | Z | Q]',CR,LF + DEFB 'Examples:',CR,LF,TAB + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB TAB,'- Enter Interactive Mode',CR,LF,TAB + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' /P',TAB,'- Init Drive interactively w/P2D stamps',CR,LF,TAB + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' d:',TAB,'- Initialize drive "d" w/default Stamp',CR,LF,TAB + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' d:name',TAB,'- Init drive "d" adding Vol ID "name"',CR,LF,TAB + DEFB TAB,TAB,' file with default Stamps',CR,LF,TAB + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' d: ZQ',TAB,'- Init drive "d" for NZTime Stamps',CR,LF,TAB + DEFB TAB,TAB,' suppressing unneeded messages',CR,LF,TAB + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' //',TAB,'- Display this message',CR,LF,LF + DEFB 'Note: ZCNFG may be used to configure a flag to suppress',CR,LF + DEFB ' drive confirmation prompt and status messages',CR,LF + DEFB 0 + + JP FINISH + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PPRGNAM: LD A,(ENVADR) ; get high byte of ENV ptr + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; and let return from there + CALL EPRINT ; else, display default name + DEFB 'HASHINI' + DEFB 0 + RET + + + ; write a stamp entry to directory + ; in: IX= ptr DPB + ; STMPCUR= # of current stamp entry +WRSTMP: PUSH BC ; save regs + PUSH DE + PUSH HL + LD HL,0 + LD BC,(STMPCUR) ; get # of current stamp entry + LD D,(IX+1) ; get sectors per track (DPB+0) + LD E,(IX+0) + LD A,17 ; set counter + + ; determine track # (in BC) and sector # (in HL) +WRSTMP1: OR A ; clear flags + SBC HL,DE ; divide by subtraction + CCF ; inverse C-flag + JR C,WRSTMP2 + ADD HL,DE ; compensate overflow + OR A ; clear flags +WRSTMP2: RL C ; divide BC by 2 (track #) + RL B + DEC A ; decrease counter + JR Z,WRSTMP3 ; ..if zero, exit loop + RL L ; else, also divide HL by 2 (sector #) + RL H + JR WRSTMP1 ; and continue + +WRSTMP3: PUSH HL ; save (log.) sector # + LD H,(IX+14) ; get track offset (# sys tracks) + LD L,(IX+13) + ADD HL,BC ; add to calculated track # + LD B,H + LD C,L + CALL BIOSTTR ; set track + POP BC ; restore (log.) sector # + LD DE,(SKEWTBL) ; get addr of skew table + CALL BIOSTRN ; translate logical to physical sector + LD B,H + LD C,L + CALL BIOSTSE ; set (phys.) sector + LD BC,CPMDMA ; set buffer addr + CALL BIOSTDM + LD BC,0 ; set C= 0 to indicate Unallocated Write + CALL BIOWRIT ; ..and perform through BIOS + OR A ; check for error + JR Z,WRSTMPX ; ..if not, jump to exit subroutine + CALL EPRINT ; else, display msg + DEFB CR,LF,BEL,'Directory write error' + DEFB 0 + JR FINISH + +WRSTMPX: LD BC,(STMPCUR) ; get current stamp # + INC BC ; increase + LD (STMPCUR),BC ; ..and save again + POP HL ; restore regs + POP DE + POP BC + RET + + + ; select disk drive that was logged at start of program + ; using BIOS fn first, then BDOS fn +SELODRV: LD A,(OLDDRV) ; get # of old logged disk drive + LD C,A ; in C + LD B,0 + PUSH BC ; save it + LD DE,1 ; ??? ##### not necessary + CALL BIOSELD ; select disk drive (through BIOS) + POP DE ; restore drive # in E + ; ..and fall through + + + ; call BDOS fn #14 SELDSK + ; in: E= drive # +BDSELD: LD C,14 + JP CPMBDOS ; jump BDOS and let return from there + + +;::::: FINISH PROCESSING DISK + +FINISH: CALL SELODRV ; restore previously logged drive + ; ..and fall through + +DSKDONE: LD A,(CURRDSK) + SUB 40H ; make numeric + LD B,A ; use value as counter + SCF ; set C-flag + LD HL,0 ; start with all bits cleared +DSKDN0: ADC HL,HL ; shift Carry bit into position + DJNZ DSKDN0 ; loop till done + EX DE,HL ; bit mask in DE (selected disk drive) + LD C,37 ; BDOS fn #37 RESDSK reset disk system + CALL CPMBDOS + LD A,(RUNMODE) ; get mode + OR A ; running in cmdline mode ? + JP NZ,START0 ; ..if not, loop for next drive + ; else, fall through and exit + + +;::::: EXIT PROGRAM + +EXIT: LD SP,(STACK) ; restore stack + RET ; ..and return to system + + +;::::: SUPPORT FUNCTIONS + + ; EVALCMD Evaluate command line + ; based on tokens provided by CP/M parser in FCB #1/#2 + ; in: A= # of current drive + ; out: A= 0x00 cmdline mode, 0xFF interactive mode + ; Syntax: [d:][volname] [/][P | Z | Q] +EVALCMD: XOR A ; clear A + LD (CURRDSK),A ; ..and variables + LD (RUNMODE),A + LD HL,CPMFCB ; set ptr to standard FCB #1 + LD A,(HL) ; get drive # + OR A ; check if zero + JR Z,ECMD1 ; ..if so, skip over + ADD A,40H ; else, make ascii + CP 'P'+1 ; check if valid + JR NC,ECMD1 ; ..if not, skip over + LD (CURRDSK),A ; else, save disk drive letter +ECMD1 + INC HL ; move ptr fwd + LD A,(HL) ; get char + LD DE,VOLNAME ; ptr to buffer for volume name + LD B,11 ; max. 11 chars + CP ' ' ; is it ? + JR Z,ECMD2 ; ..if so, jump to continue + CP '/' ; is it option or help request ? + JR NZ,ECMD1V ; ..if not, jump to copy volume name + INC HL ; else, move ptr fwd + CP (HL) ; and check next char + JP Z,HLPEXIT ; ..if also '/', jump to display help + JR ECMD3OPT ; else, this char indicates an option + + ; volume name found, copy it +ECMD1V0: LD A,(HL) ; get char +ECMD1V: CP ' ' ; is it ? + JR Z,ECMD2 ; ..if so, jump to continue + LD (DE),A ; save char in VOLNAME buffer + INC DE ; move both ptr's forward + INC HL + DJNZ ECMD1V0 ; loop till done + + ; eval 2nd cmdline token (FCB #2) +ECMD2: XOR A ; clear A + LD (DE),A ; store in VOLNAME to indicate no name + LD HL,CPMFCB2+1 ; set ptr to standard FCB #2, after drive letter + LD A,(HL) ; get char + CP '/' ; is it option or help request ? + JR NZ,ECMD3OPT ; ..if not, letter must be an option, so skip over + INC HL ; else, move ptr fwd + CP (HL) ; and check next char + JP Z,HLPEXIT ; ..if also '/', jump to display help + + ; eval option and done +ECMD3OPT: CALL EVLOPT ; eval option + RET NZ ; if error, switch to interactive mode and return + ; else, continue final check + LD HL,CPMFCB ; set ptr to standard FCB #1 + LD A,(HL) ; get byte + OR A ; is it zero ? + JR Z,ECMDIM ; ..if so, jump done (interactive mode) + INC HL ; move ptr fwd + LD A,(HL) ; get char + CP ' ' ; is it ? + JR NZ,ECMDCM ; ..if not, jump done (cmdline mode) + LD A,(CPMFCB2+1) ; get char of 2nd token + CP ' ' ; is it ? + JR NZ,ECMDCM ; ..if not, jump done (cmdline mode) + ; else, fall through (interactive mode) + +ECMDIM: OR 0FFH ; set status (interactive mode) + RET +ECMDCM: XOR A ; set status (cmdline mode) + RET + + + ; evaluate _one_ option on cmdline + ; in: HL= ptr to char (already behind a leading '/') + ; out: A= 0x00 cmdline mode, 0xFF interactive mode + ; Z-flag reset (NZ) in case of error, i.e. interactive mode + ; possible flags are /Q (quiet), /P (P2Dos stamps), /Z (NZTime stamps) +EVLOPT: LD B,7 ; max. 7 chars + +EVLOPTQ: LD A,(HL) ; get char + CP 'Q' ; option /Q - quiet ? + JR NZ,EVLOPTP ; ..if not, jump to check next option + LD A,(PRGQFLG) ; get program quiet flag + XOR 0FFH ; toggle + LD (PRGQFLG),A ; ..and save back + JR EVLONXT ; jump to continue + +EVLOPTP: CP 'P' ; option /P - P2Dos stamps ? + JR NZ,EVLOPTZ ; ..if not, jump to check next option + XOR A ; clear A + LD (STMPTYP),A ; ..and store stamp type + JR EVLONXT ; jump to continue + +EVLOPTZ: CP 'Z' ; option /Z - NZTime stamps ? + JR NZ,EVLONX1 ; ..if not, jump to check for whitespace + OR 0FFH ; set A= 0xFF + LD (STMPTYP),A ; store stamp type + ; ..and fall through to read next char + +EVLONXT: INC HL ; move ptr fwd + LD A,(HL) ; get char + ; options are separated by whitespace +EVLONX1: CP ' ' ; is it ? + JR Z,EVLOXIT ; ..if so, jump to exit loop + CP TAB ; is it ? + JR Z,EVLOXIT ; ..if so, jump to exit loop + JR NZ,EVLOERR ; else, invalid option char found + DJNZ EVLOPTQ ; loop till done + +EVLOXIT: XOR A ; set return code 0x00 (clear A and flags) + RET + +EVLOERR: LD A,(PRGQFLG) ; get program quiet flag + OR A ; running in verbose mode ? + LD A,BEL + CALL Z,COUT ; ..if so, notify user + CALL EPRINT + DEFB CR,LF,'+++ Unrecognized Option "' + DEFB 0 + LD A,(HL) + CALL COUT + CALL EPRINT + DEFB '" ... Setting Interactive' + DEFB 0 + OR 0FFH ; set return code 0xFF + RET + + + ; get console input + ; and check for abort request +CINPUT: CALL CAPIN ; get char and capitalize + CP CTRLC ; is it ? + JP Z,EXIT + CP ESC ; is it ? + JP Z,EXIT + CP 'a' ; below 'a' ? (not possible, CAPIN capitalizes) + RET C + CP 'z'+1 ; between lowercase 'a' and lowercase 'z' ? + RET NC + AND 01011111b ; remove bit 5 to capitalize + RET + + + ; ##### unreferenced code (not used) + ; copy 32 (0x20) bytes from (HL) to (DE) + LD B,32 +UNUSED1: LD A,(HL) + LD (DE),A + INC HL + INC DE + DJNZ UNUSED1 + RET + ; ##### + + + ; fill memory with zero, or byte + ; in: A= byte + ; B= # of bytes + ; HL= target addr +FILLZ: XOR A ; clear A +FILLA: LD (HL),A ; store byte + INC HL ; move ptr fwd + DJNZ FILLA ; loop + RET + + + ; verbose print - print string to CON: if quiet flag is off + ; in: (Stack) contains start addr of nul-terminated string +PVBOSE: LD A,(PRGQFLG) ; get program quiet flag + OR A ; running in verbose mode ? + JP Z,EPRINT ; ..if so, jump to print and let return from there + EX (SP),HL ; else, swap HL and top-of-stack +PVBOSE0: LD A,(HL) ; get char + INC HL ; move ptr fwd + OR A ; is byte = zero ? + JR NZ,PVBOSE0 ; ..if not, loop + EX (SP),HL ; else, swap back + RET + + + ; entry points for indirect BIOS calls + ; BC is loaded with absolute offset from WBOOT (fn #1) + ; to respective jump instruction, i.e. 3 bytes per fn +BIOSELD: PUSH BC + LD BC,3*8 ; fn #9 SELDSK select disk + JR BIOSFN + +BIOSTTR: PUSH BC + LD BC,3*9 ; fn #10 SETTRK set track + JR BIOSFN + +BIOSTSE: PUSH BC + LD BC,3*10 ; fn #11 SETSEC set sector + JR BIOSFN + +BIOSTDM: PUSH BC + LD BC,3*11 ; fn #12 SETDMA set buffer addr + JR BIOSFN + +BIOREAD: PUSH BC + LD BC,3*12 ; fn #13 READ read one sector (not used) + JR BIOSFN + +BIOWRIT: PUSH BC + LD BC,3*13 ; fn #14 WRITE write one sector + JR BIOSFN + +BIOSTRN: PUSH BC + LD BC,3*15 ; fn #16 SECTRN sector translation + JR BIOSFN + + + ; call BIOS fn indirectly + ; in: BC= offset to fn in Bios jump table +BIOSFN: EX (SP),HL ; swap HL and top-of-stack (= prev. BC) + PUSH HL ; save HL (prev. BC) + LD HL,(CPMBIOS+1) ; Bios base addr + ADD HL,BC ; add offset to fn # + POP BC ; restore BC + EX (SP),HL ; swap HL and top-of-stack again + RET ; "call" by returning to Bios fn + + +UNUSED2: + DEFB 0,0,0,0,0,0 ; ##### unreferenced chunk of data + DEFB '!!!TIME&DAT' ; obviously not used + DEFB 0,0,0,0,0,0,0,0 + DEFB 0,0,0,0,0,0,0,0 + DEFB 0,0,0,0,0,0,0,0 + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; Z3LIB - 0x08a7 +; SYSLIB - 0x091a +; end addr 0x09e5 (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + + DSEG + +STMPTYP: DEFB 0 ; stamp type flag, 0x00 = P2Dos, 0xFF = NZTime +PRGQFLG: DEFB 0 ; program quiet flag, 0x00 = verbose +VOLNAME: DEFS 12 ; buffer for volume name, 11 bytes + terminator + +RUNMODE: DEFB 0 ; indicator, 0x00 = cmdline mode / 0xFF = interactive mode +OLDDRV: DEFB 0 ; logged drive at program start +CURRDSK: DEFB 0 ; current disk drive letter + +WSPC: ; workspace starts here +DIRMAX: DEFW 0 ; max. # of dir entries (from DPH +1) +STMPMAX: DEFW 0 ; max. # of stamp entries (= DIRMAX / 4) +STMPCUR: DEFW 0 ; current # of stamp entry (used as counter) +SKEWTBL: DEFW 0 ; addr of skew table (from DPH) + + DEFS 070H ; room for stack +STACK: DEFW 0 ; stack storage location + + END + + +;************************************************************************ +; Remarks jxl: +; HASHINI.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file matches exactly the +; original SHOWHD.COM, i.e. no changes to the source were made. Possible +; optimisations detected during disassembly are marked with "#####" in the +; comment. It is fair to say that the program seems to be in an early +; stage; as the version number indicates. Apparently, provisions were made +; to test exitence, or even generate a DateStamper !!!TIME&.DAT file +; (which is not the case right now.) +; The program supports an interactive and a command line mode. Labels +; start with "IM" to indicate code specifically for interactive mode. +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/ldsys.z80 b/Source/BPBIOS/UTIL/ldsys.z80 new file mode 100644 index 00000000..25214797 --- /dev/null +++ b/Source/BPBIOS/UTIL/ldsys.z80 @@ -0,0 +1,640 @@ + TITLE "B/P Bios System Loader" +;************************************************************************ +;* L D S Y S * +;* Load a B/P Bios based system into RAM memory for direct execution * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Dec 2024 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB * +;* * +;* A>Z80ASM LDSYS/RS * +;* A>SLRNK LDSYS/N,/A:100,/D:0CF8,LDSYS,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 12 +REV EQU ' ' + +DATE MACRO + DEFB '17 Jul 96' + ENDM + + +BEL EQU 07H ; Bell character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character + +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) +CPMDMA EQU 80H ; CP/M standard DMA buffer + + +; From VLIB Get.. + EXTRN VPRINT, Z3VINIT + +; From Z3LIB Get.. + EXTRN GETNAME, PRTNAME, ZFNAME, Z3LOG, WHRENV + EXTRN GZMTOP ; ##### not used, but linked + +; From SYSLIB Get.. + EXTRN PUTUD, GETUD, F$OPEN, F$READ, SETDMA, PFN3, PHL4HC, COUT, CODEND + EXTRN F$CLOSE, CRLF ; ##### not used, but linked + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +LDSYS: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0 ; addr of Z3 environment + DEFW LDSYS ; type 4 filler + + DEFB 'LDSYS ',0 ; configuration name + +FTYPE: DEFB 'IMG' ; standard file type + +START: LD (STACK),SP + LD SP,STACK + CALL PUTUD ; currently logged drive/user + LD HL,(CPMBDOS+1) + CALL WHRENV ; find Z3 Environment Descriptor + PUSH AF + LD (ENVADR),HL ; store ENV addr + CALL Z3VINIT ; ..and init for Z3LIB routines + CALL GETNAME ; get actual program name + CALL VPRINT + DEFB CR,LF,1,'B/P Bios System Loader',2,' Vers ',VER/10+'0','.' + DEFB VER MOD 10 + '0',REV,' ' + DATE + DEFB CR,LF,' Copyright (C) 1991,3 by H.F.Bower & C.W.Cotrill',CR,LF + DEFB 0 + + ; get first token from command line (in FCB #1) + LD A,(CPMFCB+1) + CP '/' ; is this a help request ? + JP Z,HELP ; ..if so, jump display help screen + POP AF + JR Z,E$NOFIL ; else, jump error no file specified + + LD HL,(ENVADR) ; get addr Z3ENV + LD DE,70 ; offset to high byte BIOS addr + ADD HL,DE ; move ptr + LD H,(HL) ; get high byte of B/P Bios page addr + LD L,30*3 ; ..and set low byte to fn #30 + LD A,(HL) ; check byte at ptr location + CP 0C3H ; is it opcode 0xC3 (JP) ? + JR NZ,E$NOFIL ; ..if not, jump error and exit + CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO) + LD HL,-6 ; move ptr 6 bytes backward + ADD HL,DE ; (signature string) + LD A,(HL) ; get byte + CP 'B' ; is it 'B' ? + JR NZ,E$NOFIL ; ..if not, jump error and exit + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP '/' ; is it '/' ? + JR NZ,E$NOFIL ; ..if not, jump error and exit + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP 'P' ; is it 'P' ? + JR NZ,E$NOFIL ; ..if not, jump error and exit + LD DE,6 ; else, set ptr to OPTF1 (Bios Option Flags) + ADD HL,DE ; at CONFIG+2 + BIT 7,(HL) ; check bit 7 (0= not locked, 1= locked, can't reload) + JR Z,E$NOFIL ; ..if not set, skip over + + +E$RUNBP: CALL VPRINT + DEFB CR,LF,BEL,'*** Running Bios Cannot be Replaced ! ***',CR,LF + DEFB 0 + JP EXIT + +E$NOFIL: LD A,(CPMFCB+1) + CP ' ' + JR NZ,EVALCMD + CALL VPRINT + DEFB ' *** No file specified ! ***',CR,LF,BEL + DEFB 0 + + +;::::: EXIT PROGRAM + +EXIT: CALL GETUD ; set previous drive/user + LD SP,(STACK) ; set stack to initial location + RET ; ..and return to system + + +;::::: EVALUATE COMMAND LINE + +EVALCMD: LD DE,CPMFCB + LD HL,CPMDMA+1 ; set ptr to start of string +ECMD1: LD A,(HL) ; get char + INC HL ; move ptr fwd + CP ' ' ; is it ? + JR Z,ECMD1 ; ..if so, loop get next char + DEC HL ; non-blank char found, move ptr back + XOR A ; and nullify A + CALL ZFNAME ; parse token into FCB + JP NZ,E$AMBIG ; filename must be unambiguous, jump if error + LD HL,9 ; move ptr to file type + ADD HL,DE + LD A,(HL) ; get char + CP ' ' ; is it ? + JR NZ,RDIMG ; ..if not, skip over + PUSH DE ; else, save regs + EX DE,HL ; swap regs + LD HL,FTYPE ; ptr to standard file type + LD BC,3 ; 3 chars + LDIR ; ... and copy + POP DE ; restore ptr to ZCPR3 FCB + + +;::::: READ IMAGE FILE + +RDIMG: CALL Z3LOG ; log in drive/user + CALL F$OPEN ; attempt to open file + OR A + JP NZ,E$OPEN ; ..if error, jump error and exit + CALL CODEND ; get first available page after code end + LD (WSPCBEG),HL ; ..and store it +RDIMG0: PUSH HL + CALL SETDMA ; set DMA buffer addr (HL) + LD DE,CPMFCB ; set standard FCB #1 + CALL F$READ ; read one sector (128 bytes) + POP HL ; restore start addr + JR NZ,RDIMG1 ; ..if end of file, jump exit loop + LD DE,128 ; else, move buffer addr forward + ADD HL,DE + JR RDIMG0 ; ..and loop +RDIMG1: CALL GETUD ; set previously logged drive/user + CALL VPRINT + DEFB CR,LF,' CCP starts at : ' + DEFB 0 + + +;::::: READ IMAGE HEADER + +; header contains information at following offsets: +; ZCPR CCP 0x10 (16) filename +; 0x1B (27) Unbanked base addr, 0x1D (29) Unbanked size +; 0x1F (31) Banked base addr, 0x22 (33) Banked size +; ZSDOS 0x30 (48) filename +; 0x3B (59) Unbanked base addr, 0x3D (61) Unbanked size +; 0x3F (63) Banked base addr, 0x41 (65) Banked size +; B/P Bios 0x50 (80) filename +; 0x5B (91) Unbanked base addr, 0x5D (93) Unbanked size +; 0x5F (95) Banked base addr, 0x62 (98) Banked size +; 0x70 (112) IMG filename + +RDHDR: LD DE,27 ; offset CCP Unbanked base addr + CALL PSEGAS ; display addr and size of segment + LD DE,33 ; offset CCP Banked size + CALL GBYTEWS ; check if empty (0x0000) + JR Z,RDHDR0 ; ..if so, skip over + CALL VPRINT + DEFB ' Banked Ccp at : ' + DEFB 0 + LD DE,31 ; offset to CCP Banked base addr + CALL PSEGAS ; display addr and size +RDHDR0: CALL VPRINT + DEFB ' DOS starts at : ' + DEFB 0 + LD DE,59 ; offset to DOS Unbanked base addr + CALL PSEGAS ; display addr and size of segment + LD DE,65 ; offset to DOS Banked size + CALL GBYTEWS ; check if empty (0x0000) + JR Z,RDHDR1 ; ..if so, skip over + CALL VPRINT + DEFB ' Banked Dos at : ' + DEFB 0 + LD DE,63 ; offset to DOS Banked base addr + CALL PSEGAS ; display addr and size +RDHDR1: CALL VPRINT + DEFB ' BIOS starts at : ' + DEFB 0 + LD DE,91 ; offset to B/P Bios Unbanked base addr + CALL PSEGAS ; display addr and size of segment + LD DE,97 ; offset to B/P Bios Banked size + CALL GBYTEWS ; check if empty (0x0000) + JR Z,LDSEG ; ..if so, skip over + CALL VPRINT + DEFB ' Banked Bios at : ' + DEFB 0 + LD DE,95 ; offset to B/P Bios Banked base addr + CALL PSEGAS ; display addr and size + + +;::::: LOAD SYSTEM SEGMENTS + +LDSEG: CALL VPRINT + DEFB CR,LF,' ...installing ' + DEFB 0 + CALL CHKBNKD ; check options flag if banked system + JR Z,LDSEG0 ; ..if not, skip over + CALL VPRINT + DEFB 'Banked ' + DEFB 0 +LDSEG0: CALL VPRINT + DEFB 'System',CR,LF,LF + DEFB 0 + +LDSEG1: DI ; disable interrupts + LD HL,(WSPCBEG) ; get addr WSPC area + LD DE,100H ; + 100H to account for file base + ADD HL,DE + + ; ZCPR Unbanked portion + LD (CCPUSTRT),HL ; store start in WSPC area + LD DE,27 ; file offset to ZCPR Unbanked base addr + CALL G2WRDWS + LD (CCPUSIZ),BC ; store size + LD (CCPUADR),DE ; store base addr + LD HL,(CCPUSTRT) ; get start in WSPC + PUSH HL + ADD HL,BC ; calc end / start of ZSDOS Unbanked portion + LD (DOSUSTRT),HL ; ..and store it + POP HL ; restore start + LDIR ; copy ZCPR Unbanked + ; from img file to target addr + + ; ZCPR Banked portion + LD DE,31 ; offset to ZCPR Banked base addr + CALL G2WRDWS + LD (CCPBSIZ),BC ; store size + LD (CCPBADR),DE ; store base addr + LD HL,(DOSUSTRT) ; get previously calc'd end + LD (CCPBSTRT),HL ; ..and store it as Banked start in WSPC + LD A,B ; check if size is zero + OR C + JR Z,LDSEG2 ; ..if so, skip over + ADD HL,BC ; else, calc new start of ZSDOS Unbanked + LD (DOSUSTRT),HL ; ..and update it + + ; ZSDOS Unbanked portion +LDSEG2: LD DE,59 ; offset to ZSDOS Unbanked base addr + CALL G2WRDWS ; DE= base addr, BC= size + LD (DOSUSIZ),BC ; store size + LD HL,(DOSUSTRT) ; get ZSDOS Unbanked start in WSPC area + PUSH HL + ADD HL,BC ; calc end / start of B/P Bios Unbanked portion + LD (BIOUSTRT),HL ; ..and store it + POP HL ; restore start + LDIR ; copy ZSDOS Unbanked + ; from img file to target addr + + ; ZSDOS Banked portion + LD DE,63 ; offset to ZSDOS Banked base addr + CALL G2WRDWS + LD (DOSBSIZ),BC ; store size + LD (DOSBADR),DE ; store base addr + LD HL,(BIOUSTRT) ; get previously calc'd end + LD (DOSBSTRT),HL ; ..and store it as Banked start in WSPC + LD A,B ; check if size is zero + OR C + JR Z,LDSEG3 ; ..if so, skip over + ADD HL,BC ; else, calc new start of B/P Bios Unbanked + LD (BIOUSTRT),HL ; ..and update it + + ; B/P Bios Unbanked portion +LDSEG3: LD DE,91 ; offset to B/P Bios Unbanked base addr + CALL G2WRDWS + LD (BIOUSIZ),BC ; store size + LD (BIOUADR),DE ; store base addr + LD HL,(BIOUSTRT) ; get start in WSPC area + PUSH HL + ADD HL,BC ; calc end / beginning of Banked portion + LD (BIOBSTRT),HL ; ..and store it + POP HL ; restore start + LDIR ; copy B/P Bios Unbanked + ; from img file to target addr + + ; B/P Bios Banked portion + LD DE,95 ; offset to B/P Bios Banked base addr + CALL G2WRDWS + LD (BIOBSIZ),BC ; store size + LD (BIOBADR),DE ; store base addr + + ; use B/P Bios functions at new location (Unbanked portion was just loaded) + LD HL,(BIOUADR) ; get (new) B/P Bios base addr + LD L,82h ; offset to TPABNK in config area + LD A,(HL) ; get value + LD L,27*3 ; offset to B/P Bios fn #27 (SELMEM) + CALL JUMPHL ; "call" fn + LD HL,CCPBSIZ ; ptr to stored ZCPR Banked size + CALL LDBNKD + LD HL,DOSBSIZ ; ptr to stored ZSDOS Banked size + CALL LDBNKD + LD HL,BIOBSIZ ; ptr to stored B/P Bios Banked size + CALL LDBNKD + + ; Z3ENV Descriptor + LD BC,(WSPCBEG) ; get (new) B/P Bios base addr + LD HL,155 ; offset to addr of Z3 Environment Descriptor + ADD HL,BC ; in B/P Bios config area (CONFIG+26) + LD E,(HL) ; get addr in DE + INC HL + LD D,(HL) + LD HL,128 ; offset from start of WSPC area (img file) + ADD HL,BC + LD BC,128 ; bytes to copy + LDIR + + ; boot new system + LD SP,80H ; set stack pointer to default + XOR A ; nullify A + ; ..and fall through, initiating a cold boot + + +;::::: SUPPORT FUNCTIONS + + ; call B/P Bios function (at new base addr in RAM) + ; in: A= offset to JP (fn # *3) +BIOSFN: LD HL,(BIOUADR) ; get (new) B/P Bios base addr + LD L,A ; adjust to JP of fn # + ; ..and fall through + + + ; "called" as a pseudo-routine that returns to caller + ; in: HL= target addr +JUMPHL: JP (HL) ; jump to addr in HL regs + + + ; load banked portions of (new) system from WSPC area to SYSBNK + ; segment information is stored as consecutive 16-bit words + ; in the order + ; in: HL= ptr to + ; uses B/P Bios functions at new location (Unbanked portion) +LDBNKD: LD C,(HL) ; get low byte + LD A,C + INC HL ; move ptr fwd + LD B,(HL) ; get high byte + INC HL ; ptr fwd + OR B ; check if is zero + RET Z ; ..if so, return + + PUSH BC ; save regs + PUSH HL + LD HL,(BIOUADR) ; get (new) B/P Bios base addr + LD L,82H ; offset to TPABNK in config area + LD C,(HL) ; get value + INC HL ; move ptr to SYSBNK + LD B,(HL) ; get value + LD A,29*3 ; offset to B/P Bios fn #29 (XMOVE) + CALL BIOSFN + POP DE ; restore regs, DE now ptr to + POP BC + LD HL,(BIOUADR) ; get (new) B/P Bios base addr + LD L,25*3 ; offset to B/P Bios fn #25 (MOVE) + PUSH HL ; put on stack, so it is called at return + ; and let Bios routine return to initial caller + EX DE,HL ; swap regs + LD E,(HL) ; get in DE + INC HL + LD D,(HL) + INC HL + LD A,(HL) + INC HL + LD H,(HL) ; get in HL + LD L,A + RET ; ..and call B/P Bios fn #25 (MOVE) + ; to copy banked segment to SYSBNK + + + ; get _two_ consecutive 16-bit words from offset addr in WSPC area + ; in: DE= offset + ; out: DE= first value (at addr) + ; BC= second value (at addr+2) + ; HL= ptr to high byte of second value in WSPC area + ; uses BC, DE, HL +G2WRDWS: CALL G1WRDWS ; get first word in HL + EX DE,HL ; swap regs + INC HL ; move ptr fwd + LD C,(HL) ; get second word in BC + INC HL + LD B,(HL) + RET + + + ; print base addr and size of system segment ton CON: + ; in: DE= offset in WSPC area +PSEGAS: CALL G1WRDWS ; get 16-bit word (in HL) at offset (in DE) + CALL PHL4HC ; ..and print to CON: as hex digits + EX DE,HL ; swap regs + INC HL ; move ptr fwd + LD E,(HL) ; get next 16-bit word in DE + INC HL + LD D,(HL) + CALL VPRINT + DEFB ' (' + DEFB 0 + EX DE,HL ; swap regs + CALL PHL4HC ; print value (now in HL) to CON: as hex digits + CALL VPRINT + DEFB 'H Bytes)',CR,LF + DEFB 0 + RET + + + ; get _one_ 16-bit word from offset addr in WSPC area + ; in: DE= offset + ; out: HL= value + ; DE= ptr to high byte in WSPC area +G1WRDWS: LD HL,(WSPCBEG) ; addr WSPC area + ADD HL,DE ; add offset + LD E,(HL) ; get low byte at ptr addr in E + INC HL + LD D,(HL) ; get high byte at ptr addr in D + EX DE,HL ; swap regs + RET + + + ; get byte from offset addr in WSPC area + ; in: DE= offset + ; out: A= value, Z-Flag set if following byte is eqal + ; HL= ptr to next byte in WSPC area +GBYTEWS: LD HL,(WSPCBEG) ; addr WSPC area + ADD HL,DE ; add offset + LD A,(HL) ; get byte + INC HL ; move ptr fwd + OR (HL) ; check if next byte has same value + RET + + + ; check if img file contains a banked system + ; in: - + ; out: Z-Flag set for Unbanked Bios, NZ= Banked +CHKBNKD: LD HL,(WSPCBEG) ; addr WSPC area + INC H ; + 100H to account for file base + EX DE,HL ; swap regs, DE holds result over next calc's + LD BC,29 ; offset to ZCPR Unbanked size + CALL SEGTSIZ ; ..add ZCPR size(s) to DE + LD BC,61 ; offset to ZSDOS Unbanked size + CALL SEGTSIZ ; ..add ZSDOS size(s) to DE + LD HL,128 ; DE= offset to beginning of B/P Bios in + ADD HL,DE ; img file, move fwd by 128 more bytes + LD A,(HL) ; get B/P Bios options flag OPTF1 (at CONFIG+2) + AND 00000001b ; check bit 0, and set Z-Flag accordingly + RET + + + ; get total size of a system segment (add Unbanked and Banked sizes) + ; in: BC= offset in WSPC area to Unbanked size + ; out: DE= sum of segment sizes +SEGTSIZ: LD HL,(WSPCBEG) ; addr WSPC area + ADD HL,BC ; add offset + LD C,(HL) ; get 16-bit word in BC + INC HL ; (Unbanked size) + LD B,(HL) + EX DE,HL ; swap regs + ADD HL,BC ; add retrieved value + EX DE,HL ; ..and swap regs back + INC HL ; move ptr 3 bytes fwd + INC HL + INC HL + LD C,(HL) ; get 16-bit value in BC + INC HL ; (Banked size) + LD B,(HL) + EX DE,HL ; swap regs + ADD HL,BC ; add retrieved value + EX DE,HL ; ..and swap regs back + RET + + +;::::: ERROR MESSAGES + +E$AMBIG: CALL VPRINT + DEFB CR,LF,BEL,' --- Ambiguous File: ' + DEFB 0 + JR E$FNAME + +E$OPEN: CALL VPRINT + DEFB CR,LF,BEL,' --- Error Opening: ' + DEFB 0 + +E$FNAME: LD DE,CPMFCB+1 ; ptr to file name in standard FCB #1 + CALL PFN3 ; print it + JP EXIT + + +;::::: HELP SCREEN + +HELP: CALL VPRINT + DEFB CR,LF,1 + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB 2,' Loads and executes a System image prepared by',CR,LF + DEFB ' BPBUILD containing a B/P Bios.',CR,LF,LF + DEFB ' Syntax:',CR,LF + DEFB ' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' // - print this message',CR,LF + DEFB ' ' + DEFB 0 + CALL PPRGNAM + CALL VPRINT + DEFB ' [du|dir:]name[.typ] - load system image',CR,LF,LF + DEFB ' File Type Defaults to "' + DEFB 0 + LD HL,FTYPE ; ptr to default file type + LD B,3 ; # of chars +HELP0: LD A,(HL) ; get char + INC HL ; move ptr fwd + CALL COUT ; display char on CON: + DJNZ HELP0 ; ..and loop + CALL VPRINT + DEFB '" if not explicitly entered',CR,LF,LF + DEFB 'NOTE: This utility will NOT load a system ' + DEFB 'if the "Lock" bit in',CR,LF + DEFB 'the Option Byte (Bit 7 of CONFIG+2) is Set to "1"',CR,LF + DEFB 0 + JP EXIT + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PPRGNAM: LD A,(ENVADR+1) ; get high byte of ENVPTR + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; and let return from there + CALL VPRINT ; else, display default + DEFB 'LDSYS' + DEFB 0 + RET + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; VLIB - 0x06db +; Z3LIB - 0x08fc +; SYSLIB - 0x0bcf +; end addr 0x0bf8 (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;::::: RAM STORAGE + + DSEG + +WSPCBEG: DEFW 0 ; begin of workspace + ; (first available page, returned by CODEND) + + ; addresses of new system as extracted from img file + ; first _Unbanked_, then _Banked_ +BIOUADR: DEFW 0 ; B/P Bios Unbanked base addr +CCPUADR: DEFW 0 ; ZCPR Unbanked base addr +CCPUSTRT: DEFW 0 ; start in WSPC area +CCPUSIZ: DEFW 0 ; size +DOSUSTRT: DEFW 0 ; ZSDOS Unbanked start +DOSUSIZ: DEFW 0 ; size +BIOUSTRT: DEFW 0 ; B/P Bios Unbanked start +BIOUSIZ: DEFW 0 ; size + +CCPBSIZ: DEFW 0 ; ZCPR Banked size +CCPBADR: DEFW 0 ; base addr +CCPBSTRT: DEFW 0 ; start +DOSBSIZ: DEFW 0 ; ZSDOS Banked size +DOSBADR: DEFW 0 ; base addr +DOSBSTRT: DEFW 0 ; start +BIOBSIZ: DEFW 0 ; B/P Bios Banked size +BIOBADR: DEFW 0 ; base addr +BIOBSTRT: DEFW 0 ; start + + + DEFW GZMTOP ; reference Z3LIB/SYSLIB routines, so they are linked + DEFW F$CLOSE + DEFW CRLF + + DEFS 30H-6 ; room for stack + ; -6 to account for above ref's +STACK: DEFW 0 ; stack storage location + + END + + +;************************************************************************ +; Remarks jxl: +; LDSYS.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are unique up to the seventh +; character to comply with M-REL standards. However, it is recommended to +; use SLR tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file _almost_ matches the +; original LDSYS.COM with the exception of Z3LIB routine GZMTOP, and +; SYSLIB routines F$CLOSE and CRLF. Even though they are part of the +; original program, they are neither needed nor referenced. This seems +; to indicate that other versions of the LIB's were used. To reproduce +; the original program, the above mentioned routines are referenced (in +; stack area) to have them included when linking. +; +; As a byproduct of the disassembly, the structure of a B/P Bios image +; file was documented. This file contains an excerpt. +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/showhd.z80 b/Source/BPBIOS/UTIL/showhd.z80 new file mode 100644 index 00000000..d494acc6 --- /dev/null +++ b/Source/BPBIOS/UTIL/showhd.z80 @@ -0,0 +1,409 @@ + TITLE "B/P Bios HD drive partition display" +;************************************************************************ +;* S H O W H D * +;* Display DPH and DPB data for making B/P HD Partition data the same * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Jan 2025 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: SYSLIB * +;* * +;* A>Z80ASM SHOWHD/RS * +;* A>SLRNK SHOWHD/N,/A:100,/D:064D,SHOWHD,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 10 +REV EQU ' ' + +DATE MACRO + DEFB '2 Nov 91' + ENDM + + +CTRLC EQU 03H ; Control-C character +BEL EQU 07H ; Bell character +TAB EQU 09H ; Tab character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character +ESC EQU 1BH ; Escape character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) + + +; For SYSLIB make visible... + PUBLIC COUT + +; From SYSLIB Get.. + EXTRN EPRINT, BOUT, CAPINE, PAFDC, PHLFDC, PA2HC + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +SHOWHD: JP START ; bypass header + DEFB 'Z3ENV' ; this is (not really) a Z3CPR utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0 ; addr of Z3 environment + +START: LD (STACK),SP + LD SP,STACK + CALL EPRINT + DEFB CR,LF,'Show Hard Drive Partition Data - ' + DATE + DEFB CR,LF + DEFB 0 + + LD A,(CPMFCB+1) ; check first char of cmdline + CP '/' ; is this a help request ? + JP Z,HELP ; ..if so, jump + +START0: CALL EPRINT + DEFB CR,LF,'Enter Drive Letter [A..P] : ' + DEFB 0 + CALL CAPINE ; get user input + CP CTRLC ; is it ? + JP Z,0 ; ..abort + CP ESC ; is it ? + JP Z,0 ; ..abort + CP 'A' ; below ascii 'A' ? + JR C,START0 ; ..if so, loop ask for new input + CP 'P'+1 ; greater than ascii 'P' ? + JR NC,START0 ; ..if so, loop ask for new input + LD (DRLTR),A ; store drive letter + + CALL EPRINT + DEFB CR,LF,LF,'Drive: ' + DEFB 0 + CALL COUT ; display drive + CALL EPRINT + DEFB CR,LF,TAB,'DPH Info',TAB,TAB,'BPCNFG Info',CR,LF + DEFB 0 + + CALL GDPHADR ; get DPH addr for selected Disk drive + LD (DPHADR),HL ; ..and store it + LD A,H ; check if invalid (= zero) + OR L + JR NZ,PDSKDAT ; ..if not, skip over + CALL EPRINT + DEFB CR,LF,BEL,'+++ Invalid Drive : ' + DEFB 0 + LD A,(DRLTR) ; get drive letter + CALL COUT ; ..and display it + JP START0 ; then loop to ask for new input + + +;::::: DISPLAY DISK DRIVE DATA + +PDSKDAT: LD DE,10 ; offset in DPH to DPB addr + ADD HL,DE + LD E,(HL) ; DPB addr in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD (DPBADR),HL ; ..and store DPB addr + CALL EPRINT + DEFB CR,LF,LF,' Sectors/Track = ' + DEFB 0 + LD E,(HL) ; get Sect/Trk from DPB in DE + INC HL + LD D,(HL) + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; ..and display (as decimal) + SRL H ; divide by 2 + RR L + SRL H ; .. /4 + RR L + SRL H ; .. /8 + RR L + LD (KBTRK),HL ; store kByte/Trk + EX DE,HL ; swap regs + CALL P2TAB + CALL EPRINT + DEFB '(same)',CR,LF,' Blk Shift Fctr = ' + DEFB 0 + LD A,(HL) ; get next byte from DPB (= BSH, Block Shift Factor) + INC HL ; move ptr fwd + CALL PAFDC ; display BSH + CALL P2TAB + SUB 3 ; BSH -3 + LD B,A ; use as counter for multiplication + LD (BSH3),A ; ..and also store it + LD A,1 ; set initial value + JR Z,PBLKSIZ ; if BSH -3 = 0, skip over + +BLKSZLP: ADD A,A ; *2 + DJNZ BLKSZLP ; loop + +PBLKSIZ: CALL PAFDC ; display block size + ; (BSH= 3 -> 1k, 4 -> 2k, ... 8 -> 32k) + CALL EPRINT + DEFB 'k/Block',CR,LF,' Block Mask = ' + DEFB 0 + LD A,(HL) ; next byte from DPB (= BSM, Block Mask) + INC HL + CALL PAFDC ; ..display it + CALL EPRINT + DEFB CR,LF,' Extent Mask = ' + DEFB 0 + LD A,(HL) ; next byte from DPB (= EXM, Extent Mask) + INC HL + CALL PAFDC ; ..display it + CALL EPRINT + DEFB CR,LF,' Disk Blocks-1 = ' + DEFB 0 + LD E,(HL) ; next 16-bit value from DPB in DE + INC HL ; (= Disk Size in BLS units -1) + LD D,(HL) + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; display value + CALL P2TAB + INC HL ; +1 (= Disk Size) + LD A,(BSH3) ; get BSH-3 + LD B,A ; set as initial loop counter + OR A ; check if zero (means single density 1k/block) + LD A,0 ; nullify A + JR Z,PDSKCAP ; ..if already zero, no more calc needed + +DSKCLP: ADD HL,HL ; double HL (2, 4, 8 etc. k/block) + ADC A,0 ; a power-of-two multiple + DJNZ DSKCLP ; ..and loop + LD (DCAPH),A ; store disk capacity in kByte + LD (DCAPML),HL ; as 24-bit value + +PDSKCAP: CALL PDSKSZ ; ..and display it + CALL EPRINT + DEFB 'k Total (' + DEFB 0 + PUSH DE + LD DE,(KBTRK) ; kByte/Trk + LD HL,(DCAPML) ; disk capacity in kByte + LD A,(DCAPH) + LD BC,-1 ; set initial counter value + OR A + +DSKTRLP: INC BC ; increase counter (quotient) + SBC HL,DE ; divide by subtraction + SBC A,0 ; check for underflow + JR NC,DSKTRLP ; ..and loop while more to go + + LD H,B ; result in HL + LD L,C + CALL PHLFDC ; ..display it + CALL EPRINT + DEFB ' Tracks)' + DEFB 0 + POP DE ; restore DPB ptr + EX DE,HL ; swap to HL + CALL EPRINT + DEFB CR,LF,' Max Dirs - 1 = ' + DEFB 0 + LD E,(HL) ; get next 16-bit value from DPB in DE + INC HL ; (= Dir Max -1) + LD D,(HL) + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; ..and display value + CALL P2TAB + INC HL ; +1 (= Dir Max) + CALL PHLFDC ; ..and display, too + EX DE,HL + CALL EPRINT + DEFB ' Dir Entries',CR,LF,' Alloc bytes = ' + DEFB 0 + LD A,(HL) ; next byte from DPB (= AL0, Allocation byte 0) + INC HL + LD D,(HL) ; (= AL1, Allocation byte 1) + INC HL + CALL PA2HC ; display AL0 as hex + CALL EPRINT + DEFB 'H, ' + DEFB 0 + LD A,D ; AL1 in A + CALL PA2HC ; ..and display as hex + CALL EPRINT + DEFB 'H',CR,LF,' Check Size = ' + DEFB 0 + LD E,(HL) ; next 16-bit value from DPB in DE + INC HL ; (= CKS, Check Size) + LD D,(HL) + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; display value + EX DE,HL ; swap regs back + CALL EPRINT + DEFB CR,LF,' Track Offset = ' + DEFB 0 + LD E,(HL) ; next 16-bit value from DPB in DE + INC HL ; (= Track Offset) + LD D,(HL) + INC HL + EX DE,HL ; swap regs + CALL PHLFDC ; display value + EX DE,HL ; swap regs back + CALL P2TAB + CALL EPRINT + DEFB '(same)',CR,LF + DEFB 0 + JP 0 ; and exit with Warm Boot + + + ; print 2 tabs on CON: +P2TAB: PUSH AF + LD A,TAB ; in A + CALL COUT ; display on CON: + CALL COUT ; 2x + POP AF ; restore + RET + + +;::::: HELP + +HELP + CALL EPRINT + DEFB CR,LF,'SHOWHD - Display DPH and DPB data for ' + DEFB 'specified drive for making B/P',CR,LF + DEFB ' Hard Drive Partition data the same as ' + DEFB 'an operating system.',CR,LF,LF + DEFB ' Syntax:',CR,LF,LF + DEFB TAB,'SHOWHD <-- Execute program interactively',CR,LF + DEFB TAB,'SHOWHD // <-- Display this message',CR,LF + DEFB 0 + LD SP,(STACK) + RET + + +;::::: SUPPORT FUNCTIONS + + ; get addr of Disk Parameter Header (DPH) + ; in: Disk drive letter in mem variable + ; out: HL= addr DPH +GDPHADR: LD HL,(CPMBIOS+1) ; addr Bios fn #1 (WBOOT) + LD L,9*3 ; adjust ptr to fn #9 (SELDSK) + LD A,(DRLTR) ; get drive letter + SUB 'A' ; ..and convert to number + LD C,A ; copy to reg. C (for Bios call) + LD E,0 + JP (HL) ; "call" Bios fn #9 and let return from there + ; (SELDSK returns DPH addr in HL) + + + ; print disk size to CON: (capacity of a drive in kB) + ; output as decimal with provision for 3-byte values - see ZXD21.Z80 PRBIG + ; in: 24-bit value to print in A,H,L +PDSKSZ: PUSH DE ; save regs + PUSH BC + EX AF,AF' ; swap AF + PUSH AF ; save it + EX AF,AF' ; ..and swap back + LD B,0 + LD C,-1 ; set initial result + LD DE,86A0H ; 100,000 = 0x0186A0, set lower 2 bytes + OR A ; clear C-Flag +PDSKSZ0: INC C ; accumulate count + SBC HL,DE ; subtract lower 2 bytes + SBC A,1 ; ..and upper byte + JR NC,PDSKSZ0 ; loop till done + ADD HL,DE ; adjust underflow + ADC A,1 + CALL PHLD1 + LD DE,10000 ; print 10000's + CALL PHLD + LD DE,1000 ; print 1000's + CALL PHLD + LD DE,100 ; print 100's + CALL PHLD + LD DE,10 ; print 10's + CALL PHLD + LD A,L ; print 1's + CALL PHLD2 + POP AF ; restore regs + EX AF,AF' ; swap + POP BC ; ..and also restore other regs + POP DE + RET + + + ; print content of HL to CON: as decimal + ; divide HL by DE, convert remainder to ascii digit and print it + ; (similar to SYSLIB's PHLFDC/PHDC1 - see ZXD21.Z80 DECDSP) + ; in: HL= value, DE= divisor +PHLD: LD C,-1 ; set initial count + OR A ; clear C-Flag +PHLD0: INC C ; accumulate count + SBC HL,DE ; divide by subtraction + SBC A,0 + JR NC,PHLD0 ; ..and loop while more to go + ADD HL,DE ; compensate underflow + ADC A,0 +PHLD1: EX AF,AF' ; swap to retain flags + LD A,C ; get result (quotient) + OR A ; is it zero ? + JR NZ,PHLD2 ; ..if not, skip over + OR B ; get prior digit print flag + JR Z,PHLD3 ; ..if anything printed yet, jump + XOR A ; else, print a zero +PHLD2: ADD A,'0' ; convert to ascii + LD B,A ; remember for next loop + CALL COUT ; ..and display it +PHLD3: EX AF,AF' ; swap regs back + RET + + + ; intercept COUT to re-route SYSLIB calls to to BOUT + ; --> declare COUT as PUBLIC, and do _not_ import from SYSLIB +COUT: JP BOUT + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; SYSLIB - 0x0530 +; end addr 0x064d (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;::::: RAM STORAGE + + DSEG + +KBTRK: DEFW 0 ; kByte/Trk (Sect/Trk divided by 8) +BSH3: DEFB 0 ; BSH -3 (Block Shift Factor -3) + + ; disk capacity as 24-bit value +DCAPH: DEFB 0 ; high byte +DCAPML: DEFW 0 ; middle and low byte + +DRLTR: DEFB 0 ; drive letter (entered by user) +DPHADR: DEFW 0 ; addr DPH (not used) +DPBADR: DEFW 0 ; addr DPB (not used) + + DEFS 30H ; room for stack +STACK: DEFW 0 ; stack storage location + + END + + +;************************************************************************ +; Remarks jxl: +; SHOWHD.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file matches exactly the +; original SHOWHD.COM, i.e. no changes to the source were made. +; +; The program is not very complex. However, one thing might be worth +; to be pointed out: SYSLIB's routine COUT is replaced with an own +; implementation. While it is just a re-routing to another SYSLIB routine, +; it shows how simply this can be achieved. Bear in mind that _all_ +; SYSLIB routines calling COUT would now call the local implementation +; instead. With this technique existing routines can be modified without +; rewriting them entirely. +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/sizeram.z80 b/Source/BPBIOS/UTIL/sizeram.z80 new file mode 100644 index 00000000..71626856 --- /dev/null +++ b/Source/BPBIOS/UTIL/sizeram.z80 @@ -0,0 +1,546 @@ + TITLE "B/P Bios RAM size display" +;************************************************************************ +;* S I Z E R A M * +;* Determine size and location of (banked) Memory * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Dec 2024 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB * +;* * +;* A>Z80ASM SIZERAM/RS * +;* A>SLRNK SIZERAM/N,/A:100,/D:0750,SIZERAM,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 12 +REV EQU ' ' + +DATE MACRO + DEFB '30 Aug 01' + ENDM + + +BEL EQU 07H ; Bell character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMFCB EQU 5CH ; CP/M standard FCB #1 (+1 filename, +9 filetype) + + +; From Z3LIB Get.. + EXTRN GETNAME, PRTNAME, Z3INIT, WHRENV + +; From SYSLIB Get.. + EXTRN EPRINT, CRLF, PAFDC, PHLFDC, COUT, CODEND + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +SIZERAM: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 0 ; addr of Z3 environment + DEFW SIZERAM ; type 4 filler + + DEFB 'SIZERAM ',0 ; configuration name + +START: LD (STACK),SP + LD SP,STACK + CALL EPRINT + DEFB 'B/P Banked RAM Sizing Utility V',VER/10+'0','.' + DEFB VER MOD 10 + '0',REV,' ' + DATE + DEFB CR,LF + DEFB 0 + CALL CHKZ3E ; check if Z3 Environment is valid + CALL GETNAME ; get actual program name + CALL CHKHELP ; check cmdline for help request + CALL CHKSYS ; check if running under B/P Bios + CALL M$BVER ; display version # msg + LD HL,(BPCNFG) ; get addr of config area + INC HL ; move ptr fwd + INC HL + LD A,(HL) ; get OPTF1 (option flag at CONFIG+2) + AND 00000001b ; mask bit 0 + LD (BPBNKD),A ; ..and store it + JP NZ,BNKDSYS ; if banked, jump to continue + + +;::::: NON-BANKED SYSTEM + +NBNKSYS: INC HL ; move ptr to TPABNK in config area + INC HL + CALL EPRINT + DEFB CR,LF,LF,'Non-Banked System using TPA Banks = ' + DEFB 0 + LD A,(HL) ; get value + PUSH AF + CALL PAFDC ; ..and display + LD A,'/' + CALL COUT + POP AF ; restore value + INC A ; increase it + CALL PAFDC ; ..and display + CALL CRLF + JP EXIT + + +;::::: BANKED SYSTEM + +BNKDSYS: INC HL ; move ptr to UABNK in config area + LD DE,UABNK ; ..and make local copies + LD BC,5 ; (5 bytes, UABNK..MAXBNK) + LDIR + CALL CODEND ; get first available page after code end + LD (WSPCBEG),HL ; and store it + EX DE,HL ; swap regs + + ; memory read/write tests for all ram banks at addr 0x0000 + ; building a map in WSPC area: b1= zero if no bank found, b2= initially read byte + + ; test #1: 0x00/0xFF byte - iterate over banks in forward order + LD HL,0 ; set addr 0x0000 + LD C,0 ; start with bank #0 (TPA) +MEMRW: CALL GETFRB ; get byte + LD B,A ; store in B + CPL ; invert (complement) byte + CALL SETINB ; write it back + CALL GETFRB ; read again + CPL ; ..and invert + XOR B ; xor'd with initially read byte + JR NZ,MEMRW0 ; ..if no match, skip over + LD A,B ; get initially read byte + CALL SETINB ; write it + CALL GETFRB ; and read again + SUB B ; subtract initially read byte + JR NZ,MEMRW0 ; ..if not zero, skip over + + ; injected opcode 0xF6 (OR n) to skip following XOR A + DEFB 0F6h ; = OR 0AFH (write non-zero) +MEMRW0: XOR A ; nullify A + LD (DE),A ; store in WSPC area + INC DE ; move ptr fwd + LD A,B ; get initially read byte + LD (DE),A ; store it, too + INC DE ; move ptr fwd + INC C ; bank # +1 + JR NZ,MEMRW ; ..loop till all possible (256 / 0x100) banks tested + + ; test #2: write no. in each bank (iterate backward), then read and compare (forward) + DEC C ; correct bank # (loop was 1 ahead) +MEMWRB: DEC DE ; move ptr back + DEC DE + LD A,(DE) ; get byte + OR A ; check if bank exists + JR Z,MEMWRB0 ; ..if not, skip over + LD A,C ; else, get bank # + CALL SETINB ; and write in bank +MEMWRB0: LD A,C ; get bank # + SUB 1 ; -1 + LD C,A ; set bank # + JR NC,MEMWRB ; ..if not below zero, loop + INC C ; correct bank # + +MEMRDB: LD A,(DE) ; get byte from WSPC area + OR A ; check if bank exists + JR Z,MEMRDB0 ; ..if not, skip over + CALL GETFRB ; read byte from bank + CP C ; compare to bank # + JR Z,MEMRDB0 ; ..if match, skip over + XOR A ; else, set as indicator + LD (DE),A ; that bank doesn't exist +MEMRDB0: INC DE ; move ptr fwd + INC DE + INC C ; bank # +1 + JR NZ,MEMRDB ; ..loop till all possible (256 / 0x100) banks tested + + ; restore bytes initially read in all banks + LD DE,(WSPCBEG) ; set ptr to start of WSPC addr +MEMRST: LD A,(DE) ; get byte + OR A ; check bank exists + JR Z,MEMRST0 ; ..if not, skip over + INC DE ; move ptr fwd + LD A,(DE) ; get initially read byte + CALL SETINB ; ..and restore it + INC DE ; ptr fwd + JR MEMRST1 ; skip over +MEMRST0: INC DE ; ptr fwd + INC DE +MEMRST1: INC C ; bank # +1 + JR NZ,MEMRST ; loop till done + ; ..then fall through to display collected data + + + ; display information for Banked System + ; detect ranges of continuous ram banks + ; + ; HL= ptr in WSPC area + ; C= counter (up) bank #, B= counter (down) for outer loop + ; D= bank # begin of range, E= bank # end of range + LD BC,0 + LD HL,(WSPCBEG) ; set ptr to start of WSPC addr +BRANGLP: LD A,(HL) ; get byte + OR A ; check bank exists + JR NZ,BRANGE ; ..if so, skip over + INC HL ; else, use a shorter loop + INC HL ; ..move ptr fwd + INC C ; ..and bank # + JR NZ,BRANGLP ; loop until max. reached (256 / 0x100) + JR PCNFIG ; else, display Bios config report + +BRANGE: LD D,C ; store start of range (bank # in D) +BRANG0: INC HL ; ptr fwd + INC HL + INC C ; bank # +1 + JR NZ,BRANG1 ; ..if not max., skip over + DEC B + JR PBRANG ; else, display bank ranges + +BRANG1: LD A,(HL) ; get byte + OR A ; check bank exists + JR NZ,BRANG0 ; ..if so, loop + ; else, fall through + + ; display collected information +PBRANG: LD E,C ; get current bank # in E + DEC E ; loop is ahead, so -1 + CALL EPRINT + DEFB CR,LF,'RAM Banks ' + DEFB 0 + LD A,D ; get begin of range + CALL PAFDC ; ..and display it + CALL EPRINT + DEFB ' - ' + DEFB 0 + LD A,E ; get end of range + CALL PAFDC ; ..and display it + CALL EPRINT + DEFB ' (' + DEFB 0 + LD A,E ; get end of range + INC A ; adjust for correct calc + SUB D ; calc difference of begin/end + PUSH HL + LD L,A ; get value in L + LD H,0 ; ..and multiply for display + ADD HL,HL ; *2 + ADD HL,HL ; *4 + ADD HL,HL ; *8 + ADD HL,HL ; *16 + ADD HL,HL ; *32 (fixed bank size of 32k assumed) + CALL PHLFDC ; ..and display + POP HL + CALL EPRINT + DEFB 'k Bytes)' + DEFB 0 + LD A,B ; check if more to go + OR A + JR Z,BRANGLP ; loop till done + + ; display information as stored in B/P Bios config area +PCNFIG: CALL EPRINT + DEFB CR,LF,LF,'Bios Reports:',CR,LF + DEFB ' TPA Banks = ' + DEFB 0 + LD A,(TPABNK) ; get TPA bank # + PUSH AF ; save regs + CALL PAFDC ; and display it + LD A,'/' + CALL COUT + POP AF ; restore value + INC A ; +1 (TPA bank is build by 2 consecutive banks) + ; fixed size of 32k per bank is assumed + CALL PAFDC ; and display it + CALL EPRINT + DEFB CR,LF,' System Bank = ' + DEFB 0 + LD A,(SYSBNK) ; get SYSTEM bank # + CALL PAFDC ; and display it + CALL EPRINT + DEFB CR,LF,' User Bank = ' + DEFB 0 + LD A,(UABNK) ; get # of USER banks + OR A + JR NZ,PCNFIG0 ; ..if not zero, skip over + CALL EPRINT + DEFB '(None)' + DEFB 0 + JR PCNFIG1 +PCNFIG0: CALL PAFDC ; display # of USER banks +PCNFIG1: CALL EPRINT + DEFB CR,LF,' RAM Disk Start = ' + DEFB 0 + LD A,(RAMBNK) ; get # of begin RAM Disk + CALL PAFDC + CALL EPRINT + DEFB CR,LF,' Last Used Bank = ' + DEFB 0 + LD A,(MAXBNK) ; get max. available bank # + CALL PAFDC + CALL EPRINT + DEFB CR,LF,LF,' -- Scan Complete.',CR,LF + DEFB 0 + JP EXIT + + +;::::: SUPPORT FUNCTIONS + + ; get first token from command line (in FCB #1) + ; and check if help was requested +CHKHELP: LD HL,CPMFCB+1 + LD A,(HL) ; get byte + CP '/' ; is this a help request ? + RET NZ ; ..if not, return + INC HL ; else, move ptr fwd + LD A,(HL) ; and get next byte + CP '/' ; is it also '/' ? + RET NZ ; ..if not, return + ; else, fall through and display help + + +;::::: HELP SCREEN + +HELP: CALL EPRINT + DEFB CR,LF,' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' Determines location and Size of Banked Memory.',CR,LF + DEFB ' (Only TPA Banks printed if Non-Banked)',CR,LF,LF + DEFB ' Syntax:',CR,LF + DEFB ' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' - Print 32k RAM banks present and B/P Allocations',CR,LF + DEFB ' ' + DEFB 0 + CALL PPRGNAM + CALL EPRINT + DEFB ' // - display this screen',CR,LF + DEFB 0 ; fall through and exit + + +;::::: EXIT PROGRAM + +EXIT: CALL CRLF + LD SP,(STACK) ; restore stack pointer + RET ; ..and return to system + + +;::::: SUPPORT FUNCTIONS + + ; check if running under ZCPR3 and status of wheel byte + ; terminate program if not succesful +CHKZ3E: LD HL,(CPMBDOS+1) + CALL WHRENV ; find Z3 Environment Descriptor + LD (ENVADR),HL ; store ENV ptr + LD A,H ; check if invalid (= zero) + OR L + JP Z,E$BPBIO ; ..if so, jump error and terminate + CALL Z3INIT ; else, init for Z3LIB routines + LD A,41 ; offset to addr of wheel byte (Z3WHL) + CALL ADDHLA ; adjust ptr + LD E,(HL) ; get addr in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD A,(HL) ; get value of wheel byte + AND A ; check if zero + RET NZ ; ..if not (wheel on), return + CALL EPRINT ; else, display message and exit + DEFB BEL,CR,LF,'Must be wheel to Execute !',CR,LF + DEFB 0 + JR EXIT + + + ; check if running under B/P Bios + ; if not, program is terminated +CHKSYS: LD HL,(CPMBIOS+1) ; get warm boot addr (BIOS fn #1) + LD L,30*3 ; adjust ptr to fn #30 + LD A,(HL) ; check byte at ptr location + CP 0C3H ; is it opcode 0xC3 (JP) ? + JR NZ,E$BPBIO ; ..if not, jump error and terminate + CALL JUMPHL ; else, "call" B/P Bios fn #30 (RETBIO) + LD (BPVERS),A ; store version of B/P Bios + LD (BPADDR),BC ; " base addr + LD (BPCNFG),DE ; " config area addr + LD HL,-6 ; move ptr 6 bytes backward + ADD HL,DE ; (signature string) + LD A,(HL) ; get byte + CP 'B' ; is it 'B' ? + JR NZ,E$BPBIO ; ..if not, jump error and exit + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP '/' ; is it '/' ? + JR NZ,E$BPBIO ; ..if not, jump error and exit + INC HL ; ptr fwd + LD A,(HL) ; get byte + CP 'P' ; is it 'P' ? + RET Z ; ..if so, return + ; else, fall through (error and exit) + + + ; msg aborting +E$BPBIO: CALL EPRINT + DEFB CR,LF,BEL,'Not B/P Bios, aborting...!',CR,LF + DEFB 0 + RST 0 + + + ; print program name on CON: device + ; (either the actual name, or fallback to default) + ; only used by HELP +PPRGNAM: LD A,(ENVADR+1) ; get high byte of ENVPTR + OR A ; check if valid (<> zero) + JP NZ,PRTNAME ; ..if so, display actual name + ; ..and let return from there + CALL EPRINT ; else, display default + DEFB 'SIZERAM' + DEFB 0 + RET + + + ; msg B/P Bios Vers x.x +M$BVER: CALL EPRINT + DEFB ' (B/P Bios Vers ' + DEFB 0 + LD A,(BPVERS) ; get version # + RRCA ; reverse nybbles in A + RRCA + RRCA + RRCA + AND 00001111b ; mask lower nybble + ADD A,'0' ; make it ascii + CALL COUT ; ..and display + LD A,'.' + CALL COUT + LD A,(BPVERS) ; get version # + AND 00001111b ; mask lower nybble + ADD A,'0' ; make it ascii + CALL COUT ; ..and display + CALL EPRINT + DEFB ')',CR,LF + DEFB 0 + RET + + + ; add A to HL (result in HL) +ADDHLA: ADD A,L ; add L + LD L,A ; store result in L + RET NC ; ..if no overflow, return + INC H ; else, increment H + RET + + + ; the following routines rearrange Top of Stack by injecting an + ; intermediate return addr, and putting the Bios fn call on top + ; so that HL regs are preserved + ; order of steps: + ; [1] HL (= addr) is pushed onto stack + ; [2] intermediate return addr is swapped to Top of Stack + ; [3] HL (= addr) is pushed onto stack again + ; [4] Bios fn JP addr is swapped to Top of Stack + ; [5] Bios is "called" through RET, and returns to intermediate addr + + ; get byte from ram bank - in the form LD A,(HL) + ; in: C= bank #, HL= addr + ; out: A= byte +GETFRB: PUSH BC + PUSH HL ; save addr + LD HL,GETFRB0 ; load return addr + EX (SP),HL ; put it on stack + PUSH HL ; save HL again (previous top of stack) + LD HL,(BPADDR) ; get B/P Bios base addr + LD L,35*3 ; adjust ptr to fn #35 (FRGETB) + EX (SP),HL ; put addr on stack + RET ; ..and "call" Bios fn through stack + +GETFRB0: POP BC ; restore regs + RET ; ..and finally return + + ; set byte in ram bank - in the form LD (HL),A + ; in: C= bank #, HL= addr, A= byte to set +SETINB: PUSH BC + PUSH HL ; save addr + LD HL,GETFRB0 ; load return addr + EX (SP),HL ; put it on stack + PUSH HL ; save HL again (previous top of stack) + LD HL,(BPADDR) ; get B/P Bios base addr + LD L,37*3 ; adjust ptr to fn #37 (FRPUTB) + EX (SP),HL ; put addr on stack + RET ; ..and "call" Bios fn through stack + + + ; "called" as a pseudo-routine that returns to caller + ; in: HL= target addr +JUMPHL: JP (HL) ; jump to addr in HL regs + + +;::::: LOCAL DATA (not in DSEG) + +WSPCBEG: DEFW 0 ; addr begin of workspace area + ; (first available page, returned by CODEND) + + ; data retrieved from running system +BPVERS: DEFB 0 ; B/P Bios version +BPADDR: DEFW 0 ; B/P Bios base addr +BPCNFG: DEFW 0 ; addr of Config Area +BPBNKD: DEFB 0 ; indicator banked system (bit 0 of OPTF1) --> not used + + ; local copies of RAM bank configuration +UABNK: DEFB 0 ; beginning of User Bank(s) +TPABNK: DEFB 0 ; TPA Bank +SYSBNK: DEFB 0 ; beginning of System Bank(s) +RAMBNK: DEFB 0 ; base bank # for Ram Disk +MAXBNK: DEFB 0 ; highest permissible Bank # + + + DEFS 30H ; room for stack +STACK: DEFW 0 ; stack storage location + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; Z3LIB - 0x05ae +; SYSLIB - 0x065c +; end addr 0x0750 (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;::::: RAM STORAGE + + DSEG + + END + + +;************************************************************************ +; Remarks jxl: +; SIZERAM.COM, included in available B/P Bios package(s), was dis- +; assembled and extensively commented. Labels are up to seven chars long +; to comply with M-REL standards. However, it is recommended to use SLR +; tools that support labels up to sixteen chars. +; In its current state, the compiled/linked file matches exactly the +; original INITRAM.COM, i.e. no changes to the source were made. +; +; The program uses an interesting technique to read and write data in +; alternative ram banks utilizing B/P Bios functions no. 35 FRGETB and +; no. 37 FRPUTB. Top of Stack is manipulated to keep registers intact +; and "call" functions through a RET statement (instead of CALL.) +; Another specialty which is worth mentioning: Routine MEMRW (memory +; read/write) contains an "injected" opcode to alter the behaviour at +; runtime. Otherwise a more complex logic and/or additional routine +; would have been necessary. +; Storage of local data is in CSEG (code segment), not DSEG. There +; seems to be no particular reason for this. So, it can be assumed that +; this just happened by mistake. +;************************************************************************ diff --git a/Source/BPBIOS/UTIL/zscfg2.z80 b/Source/BPBIOS/UTIL/zscfg2.z80 new file mode 100644 index 00000000..d91d1846 --- /dev/null +++ b/Source/BPBIOS/UTIL/zscfg2.z80 @@ -0,0 +1,1323 @@ + TITLE "Change ZSDOS v2 Configuration Settings" +;************************************************************************ +;* Z S C F G 2 * +;* Set the user-configurable parameters in a running ZSDOS v2 system * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl Jan 2025 * +;* public release 1.0 Apr 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* LINK with Version 4 libraries: VLIB, Z3LIB, SYSLIB * +;* * +;* A>Z80ASM ZSCFG2/RS * +;* A>SLRNK ZSCFG2/N,/A:100,/D:145E,ZSCFG2,VLIBS/S,Z3LIBS/S,SYSLIBS/S,/E * +;************************************************************************ + +VER EQU 20 +REV EQU 'b' + +DATE MACRO + DEFB '' + ENDM + + +CTRLC EQU 03H ; Control-C character +BEL EQU 07H ; Bell character +TAB EQU 09H ; Tab character +LF EQU 0AH ; Line Feed character +CR EQU 0DH ; Carriage Return character + +CPMBIOS EQU 0 ; CP/M BIOS warm boot (JP) +CPMBDOS EQU 5 ; CP/M BDOS entry point (JP) +CPMDMA EQU 80H ; CP/M standard DMA buffer + + +; From VLIB Get.. + EXTRN GXYMSG, VPRINT, AT, EREOL, STNDOUT, STNDEND, CLS, GOTOXY, Z3VINIT + +; From Z3LIB Get.. + EXTRN GETQUIET, WHRENV + +; From SYSLIB Get.. + EXTRN BDOS, CRLF, CIN, PHL4HC, COUT, CAPS, @B2HH, @B2HL + + +;::::: PROGRAM START + + ORG 100H + CSEG + + +ZSCFG2: JP START ; bypass header + DEFB 'Z3ENV' ; this is a ZCPR3 utility + DEFB 1 ; show external environment + +ENVADR: DEFW 8000H ; addr of Z3 environment + +START: LD (STACK),SP + LD SP,STACK + + ; clear variables in ram + LD HL,DOSBASE + LD B,DOSTYVE-DOSBASE +CLRVAR: LD (HL),0 + INC HL + DJNZ CLRVAR + + LD A,0FFH ; set effective Bit Mask + LD (OFLGMSK),A ; to default state (all bits = 1) + LD HL,(CPMBDOS+1) ; starting from BDOS warm boot addr + CALL WHRENV ; find Z3 Environment Descriptor + LD (ENVADR),HL ; store ptr + CALL Z3VINIT ; ..and init for VLIB/Z3LIB routines + LD C,12 + CALL BDOS ; get BDOS version # + CP 22H ; must be CP/M 2.2 + JP NZ,E$ZSDOS ; ..if not, jump error and exit + LD C,48 + CALL BDOS ; check if ZSDOS + LD (DOSTYVE),HL ; save DOS type and version # + LD HL,CPMDMA ; set to cmdline buffer + LD B,(HL) ; get char count + INC HL ; move ptr fwd + CALL CMDPDL ; get past delimiters (skip , , and Comma) + JP Z,START0 ; ..if cmdline empty, jump to continue (interactive mode) + CP '/' ; is this a help request ? + LD (RUNMODE),A ; store run mode + JP NZ,START0 ; ..if not, jump to continue + INC HL + LD A,(HL) ; else, get next char + CP '/' ; help requested ? + JP NZ,START0 ; ..if not, jump to continue + + +;::::: HELP SCREEN + + CALL VPRINT + DEFB CR,LF,LF,1,'ZSCFG2',2,' Ver ',VER/10+'0','.' + DEFB VER MOD 10 + '0',REV,' - Examine/Set ZSDOS Vers 2 parameters' + DEFB CR,LF,LF,' Syntax:',CR,LF,LF + DEFB ' ZSCFG - Interactive',CR,LF + DEFB ' ZSCFG o[p],[o[p]],.. - Expert Mode',CR,LF,LF + DEFB ' Options [parameters]:',CR,LF,LF + DEFB ' P [-] Public Files R [-] Read/Only sustain',CR,LF + DEFB ' ! [-] Disk Change Alert F [-] Fast Relog',CR,LF + DEFB ' W [-] Public/Path Write S [-] Path w/o SYStem',CR,LF + DEFB ' C [ -, B or Hex value ] Clock address',CR,LF + DEFB ' * [ -, Z, or Hex value ] Wheel write protect',CR,LF + DEFB ' > [ -, Z, I, or Hex value ] DOS Search Path',CR,LF,LF + DEFB ' + [ A, C, M ][ - ] Access, Create, Modify Time Stamps',CR,LF,LF + DEFB '[more]..' + DEFB 0 + CALL CIN + CP CTRLC ; is it ? + JP Z,EXIT0 ; ..then exit program + LD A,CR ; print extra + CALL COUT + CALL EREOL + CALL VPRINT + DEFB ' Examples:',CR,LF,LF + DEFB ' ZSCFG2 *Z,P,!-',CR,LF + DEFB ' (ZCPR3 Wheel, Public ON, Warning OFF)',CR,LF,LF + DEFB ' ZSCFG2 CE800 F R',CR,LF + DEFB ' (Clock Routine=E800H, Fast Relog ON, R/O Sustain ON)',CR,LF,LF + DEFB ' ZSCFG2 CB,>I',CR,LF + DEFB ' (Clock=Bios+4EH, Int Path)',CR,LF,LF + DEFB ' Note:',CR,LF + DEFB ' Delimiters are : TAB, SPACE and Comma',CR,LF,LF + DEFB 0 + JP EXIT0 ; ..and exit program + + +START0: CALL VPRINT + DEFB CR,LF,1,'ZSCFG2'2,' V',VER/10+'0','.' + DEFB VER MOD 10 + '0',REV,' Copyright (C) 1991/2' + DEFB ' Harold F. Bower/Cameron W. Cotrill',CR,LF,LF + DEFB 0 + + LD A,(RUNMODE) ; check mode + OR A ; running interactively ? + CALL Z,CLS ; ..if so, clear screen first + LD A,(DOSTYVE+1) ; get DOS type + CP 'S' + JP NZ,E$ZSDOS ; ..if not ZSDOS, jump error and exit + LD A,(DOSTYVE) ; get DOS version # (BCD) + CP 20H ; minimum 2.0 required + JR NC,PDOSVER ; ..if so, jump to continue + CALL VPRINT ; else, display error and exit + DEFB CR,LF,BEL,'+++ Must have ZSDOS 2.0 or later +++',CR,LF + DEFB 0 + JP EXIT0 ; ..and exit program + + ; print DOS version +PDOSVER: PUSH AF + CALL VPRINT + DEFB ' ...Configuring ZSDOS Ver ' + DEFB 0 + POP AF ; restore version # + PUSH AF + CALL @B2HH ; convert upper nybble (major vers.) + CALL COUT ; and display it + LD A,'.' + CALL COUT + POP AF + CALL @B2HL ; convert lower nybble (minor vers.) + CALL COUT ; and display it + CALL CRLF + LD A,(RUNMODE) ; check run mode + OR A ; is interactive ? + JR NZ,PENVBA0 ; ..if not, jump + LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + JR NZ,PENVBAS + CALL VPRINT + DEFB CR,LF,'No Z3 Environment Found',CR,LF + DEFB 0 + JP FNDDOS + + ; Z3ENV found, print basic information +PENVBAS: CALL GXYMSG + DEFB 1,40,'Z3 Environment at : ' + DEFB 0 + LD HL,(ENVADR) ; get ENV addr + CALL PHLXH ; display addr (as hex) + CALL CRLFGXY + DEFB 2,40,'ZCPR Path Address : ' + DEFB 0 +PENVBA0: LD DE,9 + LD HL,(ENVADR) ; get ENV addr + ADD HL,DE ; adjust ptr to EXPATH + LD E,(HL) ; addr ZCPR Path in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD (ZPTHADR),HL ; store addr + LD A,(RUNMODE) ; check run mode + OR A ; is interactive ? + JR NZ,PENVBA1 ; ..if not, skip over + CALL PHLXH ; display addr (as hex) + CALL CRLFGXY + DEFB 3,45,'Wheel Byte at : ' + DEFB 0 +PENVBA1: LD DE,41 + LD HL,(ENVADR) ; get ENV addr + ADD HL,DE ; adjust ptr to Z3WHL + LD E,(HL) ; addr ZCPR Wheel byte in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + LD (ZWHLADR),HL ; store addr + LD A,(RUNMODE) ; check run mode + OR A ; is interactive ? + JR NZ,FNDDOS ; ..if not, skip over + CALL PHLXH ; display addr (as hex) + CALL CRLF + + ; find DOS base +FNDDOS: LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if reasonable + OR L + JR C,FNDDSIZ ; ..if not, continue with standard DOS size + LD DE,8 ; offset to Environment ID byte + EX DE,HL + ADD HL,DE ; adjust ptr + BIT 7,(HL) ; test bit 7 (set means Extended Environment Descr.) + JR Z,FNDDSIZ ; ..if not set (= zero), continue with standard size + LD HL,66 ; offset to DOS start addr + ADD HL,DE ; adjust ptr + LD E,(HL) ; and get addr in DE + INC HL + LD D,(HL) + EX DE,HL ; swap regs + JR FNDDO0 ; jump to continue + + ; use DOS standard size (0xE00H, 3.5kB) +FNDDSIZ: LD A,(CPMBIOS+2) ; high byte of Bios WBOOT addr + SUB 0Eh ; DOS assumed 3.5kB below Bios + LD H,A ; make it 16-bit + LD L,0 + +FNDDO0: LD (DOSBASE),HL ; store DOS base addr + PUSH HL ; move to IX + POP IX + LD DE,21 ; offset to FLAGS byte in ZSDOS header + ADD IX,DE ; (hdr is similar to v1.x) + LD (OFLGADR),IX ; store addr + LD A,(RUNMODE) ; check run mode + OR A ; is interactive ? + JP NZ,EXPMODE ; ..if not, jump + + +;::::: INTERACTIVE MODE + + ; print current settings (based on Flag bytes) on CON: +PSETTG: CALL CRLF + CALL AT ; pos cursor + DEFB 22,1 + CALL EREOL ; clear line + LD HL,0501H ; row 5, col 1 + CALL GOTOXY + + CALL VPRINT + DEFB ' 1 - Public Files : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + BIT 0,(IX+0) ; check bit 0 (Public Files, 1= enabled) + CALL PYESNO ; display Yes/No + + CALL VPRINT + DEFB CR,LF,' 2 - Pub/Path Write Enable : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + BIT 1,(IX+0) ; check bit 1 (Public/Path Write, 1= enabled) + CALL PYESNO + + CALL VPRINT + DEFB CR,LF,' 3 - Read-Only Vector : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + BIT 2,(IX+0) ; check bit 2 (Read-Only, 1= enabled) + CALL PYESNO + + CALL VPRINT + DEFB CR,LF,' 4 - Fast Fixed Disk Log : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + BIT 3,(IX+0) ; check bit 3 (Fast Relog, 1= enabled) + CALL PYESNO + + CALL VPRINT + DEFB CR,LF,' 5 - Disk Change Warning : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + BIT 4,(IX+0) ; check bit 4 (Disk Chg Warning, 1= enabled) + CALL PYESNO + + CALL VPRINT + DEFB CR,LF,' 6 - Path w/o System Attr : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + BIT 6,(IX+0) ; check bit 6 (Path w/o System, 1= enabled) + CALL PYESNO + + CALL VPRINT + DEFB CR,LF,' 7 - DOS Search Path : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + BIT 5,(IX+0) ; check bit 5 (ZCPR Path, 1= eanbled) + JR Z,PSETTG1 + CALL VPRINT + DEFB 1,'Enabled',2 + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD E,(IX-4) ; get addr DOS internal path + LD D,(IX-3) + LD L,(IX+8) ; get reference addr (new in v2) + LD H,(IX+9) + OR A + SBC HL,DE ; compare the 2 addr's + JR NZ,PSETTG0 ; ..if not internal, skip over + CALL VPRINT + DEFB ' - Internal' + DEFB 0 + JR PSETTG2 + +PSETTG0: CALL VPRINT + DEFB ' Addr = ' + DEFB 0 + EX DE,HL + CALL PHLXHHI ; display addr (as hex w/ highlighting) + JR PSETTG2 + +PSETTG1: CALL VPRINT + DEFB 1,'Disabled',2 + DEFB 0 + +PSETTG2: CALL EREOL + CALL VPRINT + DEFB CR,LF,' 8 - Wheel Byte Protect : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD L,(IX-2) ; get addr of WHEEL byte + LD H,(IX-1) + LD A,H ; check if valid (<> zero) + OR L + JR Z,PSETTG3 ; ..if not, skip over + PUSH HL + CALL VPRINT + DEFB 1,'Enabled',2,' Addr = ' + DEFB 0 + POP HL + CALL PHLXHHI ; display addr (as hex w/ highlighting) + CALL EREOL + JR PSETTG4 +PSETTG3: CALL VPRINT + DEFB 1,'Disabled',2,'..Assumed ON' + DEFB 0 + CALL EREOL + +PSETTG4: CALL VPRINT + DEFB CR,LF,' T - Time Routine (Clock) : ' + DEFB 0 + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD L,(IX+2) ; get addr of time/date routine + LD H,(IX+3) + CALL PTIMERS ; display Time Routine status (addr or 'disabled') + + CALL VPRINT + DEFB CR,LF,' A - Stamp Last Access Time : ' + DEFB 0 + LD A,00000001b ; check bit 0 + CALL PSTAMPS ; and display status + + CALL VPRINT + DEFB CR,LF,' C - Stamp Create Time : ' + DEFB 0 + LD A,00000010b ; check bit 1 + CALL PSTAMPS ; and display status + + CALL VPRINT + DEFB CR,LF,' M - Stamp Modify Time : ' + DEFB 0 + LD A,00000100b ; check bit 2 + CALL PSTAMPS ; and display status + + CALL CRLF + LD HL,01501H ; row 21, col 1 + CALL GOTOXY ; pos cursor + CALL EREOL ; clear line + CALL GXYMSG + DEFB 20,1,'Entry to Change ("X" to EXIT) : ' + DEFB 0 + CALL EREOL + ; --- << end of print settings >> --- + + + ; interactive mode - get console input and branch accordingly + ; B indicates the bit to be changed +IMCINPT: CALL CIN + CALL CAPS ; capitalize input + CP ' ' ; is it a control char (below ) ? + JR C,IMCINPT ; ..if so, loop to get new input + CALL COUT ; else, echo char + CP 'X' ; is it 'X' ? + JP Z,EXIT ; exit program + LD B,00000001b + CP '1' ; Public Files ? + JP Z,IMTGOP ; toggle bit in Option Flag (interactive) + LD B,00000010b + CP '2' ; Public/Path Write ? + JP Z,IMTGOP + LD B,00000100b + CP '3' ; Read-Only ? + JP Z,IMTGOP + LD B,00001000b + CP '4' ; Fast Relog ? + JP Z,IMTGOP + LD B,00010000b + CP '5' ; Disk Change Warning ? + JP Z,IMTGOP + LD B,01000000b + CP '6' ; Search Path w/o System Attr ? + JP Z,IMTGOP + CP '7' ; DOS Search Path ? + JP NZ,IMWHL ; ..if not, jump to continue checking input + + + ; interactive mode - change Path + CALL CRLFGXY ; else, fall through to change DOS Path + DEFB 21,16,'DOS Path [(' + DEFB 1,'D',2,')isable, (' + DEFB 1,'S',2,')et, (' + DEFB 1,'I',2,')nternal' + DEFB 0 + LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + JR Z,IMPATH + CALL VPRINT + DEFB ', (',1,'Z',2,')CPR3' + DEFB 0 +IMPATH: CALL VPRINT + DEFB '] : ' + DEFB 0 + + ; input +IMPTHIN: CALL CINCAPS ; get user input and capitalize + CP 'D' ; is it 'D'isable ? + JR Z,IMPTHDS + CP 'Z' ; is it 'Z'CPR ? + JR Z,IMPTHZ + CP 'I' ; is it 'I'nternal ? + JR NZ,IMPTHST ; ..if not, jump to check other options + ; else, fall through + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD L,(IX+8) ; get reference addr (new in v2) + LD H,(IX+9) + JR IMPTHEN + + ; set +IMPTHST: CP 'S' ; is it 'S'et addr ? + JR NZ,IMPTHIN ; ..loop if input not valid + CALL CRLFGXY + DEFB 22,25,'Enter PATH Address : ' + DEFB 0 + LD HL,0 ; set initial value + CALL CINADR ; get user input, converted addr in HL + JR IMPTHEN ; jump to set addr and enable + + ; disable +IMPTHDS: LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + RES 5,(IX+0) ; bit 5 = 0 to disable Path + JP PSETTG ; jump display (new) settings + + ; zcpr +IMPTHZ: LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + JP Z,PSETTG ; ..if not, jump display settings + LD HL,(ZPTHADR) ; else, get addr of Path in ENV + + ; enable +IMPTHEN: LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + SET 5,(IX+0) ; bit 5 = 1 to enable path + LD (IX-3),H ; ..and set addr + LD (IX-4),L + JP PSETTG ; jump display (new) settings + + + ; input >8 i.e. not Option Flag byte, change other options + + ; interactive mode - change Wheel +IMWHL: CP '8' ; change Wheel ? + JP NZ,IMTIME ; ..if not, jump to next + CALL CRLFGXY + DEFB 21,20,'WHEEL Addr [(' + DEFB 1,'D',2,')isable, (' + DEFB 1,'S',2,')et' + DEFB 0 + LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + JR Z,IMWHL0 ; ..if no ENV, skip over + CALL VPRINT + DEFB ', (',1,'Z',2,')CPR3' + DEFB 0 +IMWHL0: CALL VPRINT + DEFB '] : ' + DEFB 0 + + ; input +IMWHLIN: CALL CINCAPS ; get user input and capitalize + LD HL,0 ; prepare for disable + CP 'D' ; is it 'D'isable ? + JR Z,IMWHLST + CP 'Z' ; is it 'Z'CPR Wheel ? + JR Z,IMWHLZ + CP 'S' ; is it 'S'et addr ? + JR NZ,IMWHLIN ; ..loop if no valid input + CALL CRLFGXY + DEFB 22,25,'Enter WHEEL Address : ' + DEFB 0 + LD HL,0 ; set initial value + CALL CINADR ; get user input, converted addr in HL + JR IMWHLST ; jump set value + + ; zcpr +IMWHLZ: LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + JP Z,PSETTG ; ..if not, jump display settings + LD HL,(ZWHLADR) ; get Wheel byte addr from ENV + + ; set +IMWHLST: LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD (IX-1),H ; and set addr + LD (IX-2),L + JP PSETTG ; jump display (new) settings + + ; interactive mode - change Time +IMTIME: CP 'T' ; change Time ? + JR NZ,IMASTMP ; ..if not, jump to next + CALL CRLFGXY + DEFB 21,15,'Time (Clock)' + DEFB 0 + CALL ASKSET ; ask disable/set + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD (IX+2),L ; get addr of time/date routine (GSTIME) + LD (IX+3),H + LD A,0FFH ; prepare for unload value + ADC A,0 ; C-Flag is dummy vector flag + LD (IX+6),A ; ...to set UNLOAD to 0 + LD (IX+7),A ; (rather than 0xFFFF) + JP PSETTG ; jump display (new) settings + + + ; changes are reflected in Time flag byte (new in v2) +IMASTMP: CP 'A' ; change Stamp Access Time ? + JR NZ,IMCSTMP ; ..if not, jump to next + CALL CRLFGXY + DEFB 21,15,'Stamp Last Access Time' + DEFB 0 + CALL ASKENBL ; ask disable/enable (C-Flag is indicator) + LD B,00000001b ; mask bit 0 + JP IMTFLG ; and toggle in Time Flag byte (interactive) + ; +IMCSTMP: CP 'C' ; change Stamp Create Time ? + JR NZ,IMMSTMP ; ..if not, jump to next + CALL CRLFGXY + DEFB 21,15,'Stamp Create Time' + DEFB 0 + CALL ASKENBL ; ask disable/enable (C-Flag is indicator) + LD B,00000010b ; mask bit 1 + JP IMTFLG ; and toggle + ; +IMMSTMP: CP 'M' ; change Stamp Modify Time ? + JR NZ,INPINVL ; ..if not, jump invalid user input + CALL CRLFGXY + DEFB 21,15,'Stamp Modify Time' + DEFB 0 + CALL ASKENBL ; ask disable/enable (C-Flag is indicator) + LD B,00000100b ; mask bit 2 + JP IMTFLG ; and toggle + + + ; interactive mode - invalid (not a menu option) +INPINVL: CALL VPRINT ; alert and ask for new input + DEFB 8,' ',8,BEL + DEFB 0 + JP IMCINPT + + +;::::: EXIT PROGRAM + +EXIT: CALL VPRINT + DEFB CR,LF,LF,'Returning to system ...',CR,LF + DEFB 0 +EXIT0: LD SP,(STACK) ; restore stack + RET + + +;::::: SUPPORT FUNCTIONS (interactive mode) + + ; toggle bit in Flag byte + ; in: B= bit mask (respective bit is set) +IMOFLG +IMTGOP: LD A,B + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + XOR (IX+0) ; toggle bit + LD (IX+0),A ; and save value again + JP PSETTG ; jump, display (new) settings + + + ; set/reset bit in Time flag byte (new in v2) + ; in: B= bit maks (respective bit is set) + ; C-Flag set = disable, NC= enable +IMTFLG: LD A,B ; get bit + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + JR C,IMTFLGR ; ..if C-Flag set, jump + OR (IX+1) ; merge with current value (= set bit) + + ; set +IMTFLGS: LD (IX+1),A ; and save value again + JP PSETTG ; jump display (new) settings + + ; reset +IMTFLGR: CPL ; invert bit mask + AND (IX+1) ; merge with current value (= reset bit) + JR IMTFLGS + + +;::::: EXPERT MODE + +EXPMODE: LD HL,CPMDMA ; set ptr to command line buffer + LD B,(HL) ; get char count + INC HL ; move ptr forward to first char + + ; evaluate command line +EMEVCMD: CALL CMDPDL ; get past delimiters (skip , , and Comma) + JP Z,EMSETOF ; ..if end of cmdline, jump set Option Flags + CP '*' ; change Wheel ? + JP Z,EMWHL + CP '+' ; change Time ? + JP Z,EMSTAMP + CP 'C' ; change Clock (stamp) ? + JP Z,EMTIME + CP 'R' ; change R/O ? + JR NZ,EMRELOG ; ..if not, jump to next + + ; first, handle options which can be switched on/off + ; more complex handling routines further down below + + ; change R/O Vector + CALL PVBOSE + DEFB 'R/O Sustain = ' + DEFB 0 + LD C,00000100b ; mask bit 2 + JP EMOFLG ; toggle Option Flags (Read Only) + +EMRELOG: CP 'F' ; change Fast Relog ? + JR NZ,EMDWARN ; ..if not, jump to next + CALL PVBOSE + DEFB 'Fast Relog = ' + DEFB 0 + LD C,00001000b ; mask bit 3 + JP EMOFLG ; toggle Option Flags + +EMDWARN: CP '!' ; change Disk Warning ? + JR NZ,EMPUBFL ; ..if not, jump to next + CALL PVBOSE + DEFB 'Change Warning = ' + DEFB 0 + LD C,00010000b ; mask bit 4 + JP EMOFLG ; toggle Option Flags + +EMPUBFL: CP 'P' ; change Public Files Flag ? + JR NZ,EMPUBWR ; ..if not, jump to next + CALL PVBOSE + DEFB 'Public Files = ' + DEFB 0 + LD C,00000001b ; mask bit 0 + JP EMOFLG ; toggle Option Flags + +EMPUBWR: CP 'W' ; change Public/Path Write ? + JR NZ,EMSYSAT ; ..if not, jump to next + CALL PVBOSE + DEFB 'Pub/Path Write = ' + DEFB 0 + LD C,00000010b ; mask bit 1 + JP EMOFLG ; toggle Option Flags + +EMSYSAT: CP 'S' ; change Path w/o Sys Attr ? + JR NZ,EMSETPA ; ..if not, jump next + CALL PVBOSE + DEFB 'Path w/o SYS = ' + DEFB 0 + LD C,01000000b ; mask bit 6 + JP EMOFLG ; toggle Option Flags + +EMSETPA: CP '>' ; set Path ? + JP Z,EMPATH ; ..if so, jump to continue + ; else, fall through (not a valid option) + + ; move forward in command line to next possible option +EMCMDFW: CALL CMDATDL ; move forward to next , , or Comma + JP NZ,EMEVCMD ; and continue evaluating cmdline + + ; set Option flag when end of cmdline was reached +EMSETOF: LD A,(OFLGMSK) ; get effective Bit Mask + LD HL,OFLGWIP ; ptr to Option Flag byte (wip) + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + AND (IX+0) ; Bit Mask AND current Flag Byte + OR (HL) ; set new flags (wip) + LD (IX+0),A ; write back new Option Flag byte + JP EXIT0 ; ..and exit program + + ; change Wheel +EMWHL: CALL PVBOSE + DEFB 'Wheel Protect = ' + DEFB 0 + CALL CMDNCHR ; get next char from cmdline + CALL Z,PV$INVL ; ..if end-of-string (), display msg + JR Z,EMSETOF ; ...and jump, set Option Flags + CP '-' ; disable ? + JR NZ,EMWHL0 ; ..if not, jump + CALL PV$DABL ; else, display msg + LD DE,0 ; zero addr to disable + JR EMWHL2 ; ..and jump to continue + +EMWHL0: CP 'Z' ; use Z3WHL ? + LD DE,(ZWHLADR) ; get Wheel byte addr from ENV + JR Z,EMWHL4 ; ..if so, jump to continue + CALL CMDADR ; else,read addr from cmdline in DE + CALL Z,PV$INVL ; ..if not valid, display msg + JR Z,EMCMDFW ; ..and jump + +EMWHL1: CALL PV$DEX ; display addr +EMWHL2: LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD (IX-1),D ; set new Wheel byte addr + LD (IX-2),E +EMWHL3: CALL CMDATDL ; move forward to next , , or Comma + JP EMEVCMD ; then continue evaluating cmdline +EMWHL4: PUSH HL ; save regs (ptr in cmdline) + LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + POP HL ; restore regs + JR NZ,EMWHL5 ; ..if valid, skip over + CALL PV$INVL ; else, display msg + JP EMEVCMD ; ..and continue evaluating cmdline + +EMWHL5: CALL PVBOSE + DEFB 'Z-System @ ' + DEFB 0 + JR EMWHL1 ; jump to set addr (in DE) + + ; change Path +EMPATH: CALL PVBOSE + DEFB 'Search Path = ' + DEFB 0 + CALL CMDNCHR ; get next char from cmdline + CALL Z,PV$INVL ; ..if end of string (), display msg + JP Z,EMSETOF ; ...and loop, set Option Flags + CP '-' ; disable ? + JR NZ,EMPTH0 ; ..if not, jump + CALL PV$DABL ; else, display msg + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + RES 5,(IX+0) ; bit 5 = 0 to disable Path + JP EMEVCMD ; and continue evaluating cmdline + +EMPTH0: CP 'I' ; 'I'nternal Path ? + JR NZ,EMPTH1 ; ..if not, jump + LD E,(IX+8) ; get reference addr (new in v2) + LD D,(IX+9) + CALL PVBOSE + DEFB 'Internal',CR,LF + DEFB 0 + JR EMPTH3 ; jump to set addr (in DE) +EMPTH1: CP 'Z' ; 'Z'CPR Path ? + LD DE,(ZPTHADR) ; get addr of Path in ENV + JR Z,EMPTH4 ; ..if option, jump + CALL CMDADR ; else,read addr from cmdline in DE + CALL Z,PV$INVL ; ..if not valid, display msg + JP Z,EMCMDFW ; ..and jump +EMPTH2: CALL PV$DEX ; display addr +EMPTH3: LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD (IX-3),D ; set new Path addr + LD (IX-4),E + SET 5,(IX+0) ; and set bit 5 = 1 to enable Path + JP EMWHL3 +EMPTH4: PUSH HL ; save regs (ptr in cmdline) + LD HL,(ENVADR) ; get ENV addr + LD A,H ; check if valid (<> zero) + OR L + POP HL ; restore regs + JR NZ,EMPTH5 ; ..if valid, skip over + CALL PV$INVL ; else, display msg + JP EMEVCMD ; ..and continue evaluating cmdline + +EMPTH5: CALL PVBOSE + DEFB 'Z-System @ ' + DEFB 0 + JR EMPTH2 ; jump to set addr (in DE) + + + ; change Clock Routine + ; ##### CHECK: changed order, requires additional PUSH/POP AF +EMTIME: CALL CMDNCHR ; get next char from cmdline + PUSH AF + CALL PVBOSE + DEFB 'Clock Routine = ' + DEFB 0 + POP AF + CALL Z,PV$INVL ; ..if end of string (), display msg + JP Z,EMSETOF ; ..and loop, set Option Flags + CALL EMTROUT ; check Time routine options (addr in DE) + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD (IX+2),E ; set addr of time/date routine (GSTIME) + LD (IX+3),D + LD A,0FFH ; prepare for unload value + ADC A,0 ; C-Flag is dummy vector flag + LD (IX+6),A ; ...to set UNLOAD to 0 + LD (IX+7),A ; (rather than 0xFFFFH) + JP EMSTMX0 ; jump to continue evaluating cmdline + + + ; change Time Stamp(s) +EMSTAMP: CALL CMDNCHR ; get next char from cmdline + JP Z,EMSETOF ; ..if end of string (), loop set Option Flags + LD (CHARCMD),A ; store char + CALL CMDNCHR ; and get next one from cmdline + JR NZ,EMASTMP ; ..if not end of string, jump to continue + INC B ; set counter back (= 1 char remaining) + DEC HL ; set ptr back + LD A,' ' ; set as if it were read from cmdline + +EMASTMP: PUSH AF ; save this char + LD A,(CHARCMD) ; restore previous char + CP 'A' ; is it 'A'ccess ? + JR NZ,EMCSTMP ; ..if not, jump next + CALL PVBOSE + DEFB 'Stamp Access = ' + DEFB 0 + LD D,00000001b ; bit mask (bit 0= Access Stamp) + JR EMSTMST ; and jump to set/reset + +EMCSTMP: CP 'C' ; is it 'C'reate ? + JR NZ,EMMSTMP ; ..if not, jump next + CALL PVBOSE + DEFB 'Stamp Create = ' + DEFB 0 + LD D,00000010b ; bit mask (bit 1= Create Stamp) + JR EMSTMST ; and jump to set/reset + +EMMSTMP: CP 'M' ; is it 'M'odify ? + JR NZ,EMSTMX ; ..if not, skip over and loop + CALL PVBOSE + DEFB 'Stamp Modify = ' + DEFB 0 + LD D,00000100b ; bit mask (bit 2= Modify Stamp) + + ; set/reset +EMSTMST: POP AF ; restore following char + CALL EMTFLG ; get new Time flag in E + LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + LD (IX+1),E ; and write back Time flag byte + JR EMSTMX0 ; skip over, and loop + +EMSTMX: POP AF +EMSTMX0: JP EMEVCMD ; continue evaluating cmdline + + +;::::: SUPPORT FUNCTIONS (expert mode) + + ; expert mode - toggle bit in wip Option Flag byte based on following char + ; in: HL= ptr cmdline + ; B= char count (remaining chars) + ; C= bit mask (respective bit is set) +EMOFLG: CALL CMDNCHR ; get next char and capitalize it + CP '-' ; disable ? + LD A,C ; bit mask in A + JR NZ,EMOFLG0 ; ..if not '-', jump (default to enable) + PUSH AF + CALL PV$DABL ; display 'Disabled' if verbose + POP AF + LD C,0 + JR EMOFLG1 + +EMOFLG0: PUSH AF + CALL PVBOSE + DEFB 'Active',CR,LF + DEFB 0 + POP AF +EMOFLG1: CPL ; invert mask + PUSH HL + LD HL,OFLGMSK ; ptr to effective Bit Mask + AND (HL) ; merge (= reset) current bit + LD (HL),A ; ..and store new Bit Mask + LD HL,OFLGWIP ; ptr to Flag byte (wip) + LD A,C ; get current bit + OR (HL) ; merge (set/reset) with Option Flag (wip) + LD (HL),A ; ..and save back + POP HL + JP EMCMDFW ; ..and loop + + + ; expert mode - return bit pattern to toggle Time Stamp (Access/Create/Modify) + ; set/reset bit in Time flag byte (new in v2) + ; in: D= bit mask (respective bit is set) + ; A= char from cmdline + ; ( disable = '-' / enable = , , Comma + ; everything else is invalid ) + ; out: E= new Time flag byte +EMTFLG: LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + PUSH AF ; save char + LD A,(IX+1) ; get current Time flag byte + OR D ; set respective bit (= 1) + XOR D ; and invert it (= 0) + LD E,A ; new Time flag in E (prepared to disable) + POP AF ; restore char + CP '-' ; disable ? + JR Z,PV$DABL ; ..if so, jump display msg + ; ...and return from there with C-Flag set + CALL CHKDLM ; else, must be , , or Comma + JR NZ,PV$INVL ; ..if not, jump display 'invalid' and return from there + LD A,E ; get new Time flag byte + OR D ; set respetive bit (= 1) + LD E,A ; and copy as new Time flag byte + CALL PVBOSE + DEFB 'Enabled',CR,LF + DEFB 0 + XOR A + RET + + ; expert mode - change Time Routine + ; either disable or get addr of routine +EMTROUT: CP '-' ; disable ? + LD DE,(TIMEDIS) ; get disable vector + JR NZ,EMTROU0 ; ..if not '-', jump to continue + ; else, fall through + +PV$DABL: CALL PVBOSE + DEFB 'Disabled',CR,LF + DEFB 0 + SCF + RET + +EMTROU0: LD DE,(CPMBIOS+1) ; get Bios WBOOT addr (fn #1) + LD E,26*3 ; adjust to fn #26 (TIME) + CP 'B' ; 'B'ios routine ? + JP Z,PV$DEX ; ..if not, diplay msg and let return from there + CALL CMDADR ; else, read addr from cmdline (in DE) + JP NZ,PV$DEX ; ..if valid, display addr and let return from there + CALL PV$INVL ; else, display msg + POP DE ; restore regs + JP EMCMDFW ; ..and jump + +PV$INVL: PUSH AF + CALL PVBOSE + DEFB '-- Invalid --',CR,LF + DEFB 0 + POP AF + RET + + + ; get hex addr from command line + ; in: HL= ptr in cmdline string + ; B= char counter (remaining chars) + ; out: A= 0 and Z-Flag set if end of string, else NZ= valid + ; DE= addr + ; HL= moved fwd, B= decremented by digit count +CMDADR: LD DE,0 ; set initial value +CMDADR0: CALL CHKXDIG ; check if char is valid hex digit + JR NC,CMDADR1 ; ..if not, jump to additional check + EX DE,HL ; swap regs + CALL ADDDIGA ; new result in HL + EX DE,HL ; swap back + CALL CMDNCHR ; get next char from cmdline + JR NZ,CMDADR0 ; ..if not (end of string), loop + DEC HL ; else, move ptr back + INC B ; ..and correct counter + JR CMDADRX ; ..then exit + +CMDADR1: LD A,(HL) ; get char again + CALL CHKDLM ; check if , , or Comma + JR Z,CMDADRX ; ..if so, jump to exit + LD DE,0 ; else, set zero addr (char not valid) +CMDADRX: LD A,D ; set status (Z-Flag), non-zero = ok + OR E + RET + + ; get _past_ delimiter(s) parsing command line + ; read string, skip whitespace (, ) and Comma + ; stop if other char or terminating byte is found + ; in: HL= ptr to string + ; B= max. char count + ; out: HL= ptr to first non-matching char, Z-Flag set if end reached +CMDPDL: LD A,(HL) ; get byte + OR A ; check for (end of string) + RET Z ; ..if so, return (Z-Flag set) + CALL CAPS ; make char uppercase + CALL CHKDLM ; check for , , or Comma + RET NZ ; ..if other char, return + INC HL ; else, ptr fwd + DJNZ CMDPDL ; ..and loop + XOR A ; reached max. char count, set flag + RET ; and return + + + ; stop _at_ next delimiter parsing command line + ; read string, skip any char until , , or Comma is found + ; (opposite to previous fn), stop if , , Comma or terminating + ; in: HL= ptr in cmdline string + ; B= char count (remaining chars) + ; out: HL= ptr to found , , or Comma / at end of string + ; B= decremented accordingly + ; A= char, Z-Flag not set (NZ) if found + ; A= 0, Z-Flag set if not found +CMDATDL: LD A,(HL) ; get byte + OR A ; check for (end of string) + RET Z ; ..if so, return (Z-Flag set) + CALL CHKDLM ; check for , , or Comma + JR Z,CMDATD0 ; ..if found, jump exit + INC HL ; else, ptr fwd + DJNZ CMDATDL ; ..and loop + XOR A ; reached max. char count, set flag + RET ; and return + +CMDATD0: OR A ; char is , , or Comma - set status (NZ) + RET + + + ; checks if char is a delimiter (, , or Comma) + ; in: A= char + ; out: Z-Flag set if match, NZ= none of them +CHKDLM: CP ' ' + RET Z + CP ',' + RET Z + CP TAB + RET + + + ; get next char from command line + ; in: HL= ptr in cmdline string + ; B= char counter (remaining chars) + ; out: A= next char (capitalized) + ; Z-Flag set if end of string, NZ= valid + ; HL= incremented, B= decremented +CMDNCHR: INC HL ; move ptr fwd + LD A,(HL) ; get char + CALL CAPS ; capitalize it + DEC B ; counter -1 + RET + + ; get console input (1 char) and capitalize +CINCAPS: CALL CIN + JP CAPS + + + ; get console input, hex addr in HL + ; in: A= (possible) first char + ; out: HL= addr +CINADR: CALL CAPS ; capitalize A + LD (CHARTMP),A ; store for echo + CP CR ; is it (marks end) ? + RET Z ; ..if so, return + CALL CHKXDIG ; else, check if hex digit + JR NC,CINADR0 ; ..if not, get next char + PUSH AF + LD A,(CHARTMP) ; get char back + CALL COUT ; ..and echo + POP AF + CALL ADDDIGA ; add to HL +CINADR0: CALL CIN ; get console input + JR CINADR ; ..and loop + + + ; check if char is a valid hex digit + ; in: A= char + ; out: A= converted char, C-Flag set if ok, NC= not ok +CHKXDIG: SUB '0' ; convert ascii to number + JP M,CHKXDI0 + CP 9+1 ; is it below 10 ? + RET C ; ..if so, return (= ok) + SUB 7 ; else, check A..H + CP 10 + JR C,CHKXDI0 + CP 16 + RET ; return with C-Flag (status) set accordingly + +CHKXDI0: XOR A ; nullify A + DEC A ; exit with C-Flag reset (digit not valid) + RET + + + ; add hex digit in A to HL +ADDDIGA: ADD HL,HL ; make room for new digit in HL by shifting + ADD HL,HL ; 4 bits left (*8, power-of-two-multiple) + ADD HL,HL + ADD HL,HL + ADD A,L ; add A + LD L,A ; and store new total + RET + + + ; print YES / NO with highlighting + ; in: Z-Flag not set (NZ) = YES, set = NO +PYESNO: JR Z,PYSNO0 + CALL VPRINT + DEFB 1,'YES',2 + DEFB 0 + RET +PYSNO0: CALL VPRINT + DEFB 1,'NO',2,' ' + DEFB 0 + RET + + + ; verbose print - print string to CON: if quiet option is off + ; in: (Stack) contains start addr of nul-terminated string +PVBOSE: CALL GETQUIET ; get quiet flag + JP Z,VPRINT ; if verbose (= not quiet), jump to display + ; and let return from there + EX (SP),HL ; swap HL and string addr +PVBOSE0: LD A,(HL) ; get char + INC HL ; move ptr fwd + OR A ; is it (= end of string) ? + JR NZ,PVBOSE0 ; ..if not, loop get next char + EX (SP),HL ; else, swap back (on Stack = addr behind string) + RET + + + ; print value as hex if in verbose mode (quiet flag = off) + ; in: DE= value +PV$DEX: CALL GETQUIET ; get quiet flag + JR NZ,PV$DEX0 ; if quiet, skip over + EX DE,HL ; swap regs + CALL PHLXH ; display addr in HL (as hex) + EX DE,HL ; swap back + CALL CRLF ; display extra +PV$DEX0: AND A ; clear C-Flag + RET + + + ; print status of Access/Create/Modify routines + ; based on Time flag byte (new in v2) + ; in: A= bit to test (0= Acc, 1= Cre, 2= Mod) +PSTAMPS: LD IX,(OFLGADR) ; ptr to ZSDOS Flag byte + AND (IX+1) ; compare with flag byte + ; (did not exist in v1, apparently added in v2) + JR PSTMPS0 ; jump to continue + + ; ##### orphaned code, seems as if combined print function was planned + LD DE,(TIMEDIS) ; get disable vector + OR A + SBC HL,DE + ADD HL,DE + ; ##### + +PSTMPS0: JR Z,PDISABL ; ..if bit not set, jump display 'disabled' + CALL VPRINT ; else, display 'enabled' + DEFB 1,'Enabled',2 + DEFB 0 + JP EREOL + + + ; print status of Time routines - addr or 'disabled' +PTIMERS: LD DE,(TIMEDIS) ; get disable vector + OR A ; clear Flags + SBC HL,DE ; compare HL and DE + ADD HL,DE ; preserving registers + JR Z,PDISABL ; ..if disable vector, display msg + CALL PHLXHHI ; else, display addr (as hex w/ highlighting) + JP EREOL + +PDISABL: CALL VPRINT + DEFB 1,'Disabled',2 + DEFB 0 + JP EREOL + + ; print addr in HL with highlighting + ; in: HL= addr +PHLXHHI: CALL STNDOUT ; turn on 'standout' display + CALL PHLXH ; display as hex plus 'H' + JP STNDEND ; turn off 'standout' + + + ; print addr in HL as four-digit hex and append 'H' + ; in: HL= addr +PHLXH: CALL PHL4HC ; display as 4-digit hex + LD A,'H' ; and display 'H' + JP COUT ; print , then jump to GXYMSG (return addr on stack) + + +CRLFGXY: CALL CRLF + JP GXYMSG ; ask user whether to disable routine, or set addr for it + + + ; print 'Routine...' and ask for disable/set +ASKSET: CALL VPRINT + DEFB ' Routine [(' + DEFB 1,'D',2,')isable), (' + DEFB 1,'S',2,')et] : ' + DEFB 0 +ASKSET0: CALL CINCAPS ; get user input (capitalized) + CP 'D' ; disable ? + LD HL,(TIMEDIS) ; get disable vector + SCF ; set C-Flag for later calc + RET Z ; ..if disable, return + CP 'S' ; set addr ? + JR NZ,ASKSET0 ; ..if not, loop ask for new input + CALL CRLFGXY ; else, prompt user to enter addr + DEFB 22,25,'Enter Address of Routine : ' + DEFB 0 + LD HL,0 + JP CINADR ; jump to get input, and let return from there + + + ; print 'Routine...' and ask for disable/enable it + ; out: C-Flag set = disable, NC= enable +ASKENBL: CALL VPRINT + DEFB ' Routine [(' + DEFB 1,'D',2,')isable), (' + DEFB 1,'E',2,')nable] : ' + DEFB 0 +ASKENB0: CALL CINCAPS ; get user input (char) and capitalize it + CP 'D' ; is it 'D'isable ? + SCF ; set C-Flag (indicator) + RET Z + CP 'E' ; is it 'E'nable ? + JR NZ,ASKENB0 ; ..if not, loop ask for new input + RET ; else, return with C-Flag reset (NC) + + + ; error msg +E$ZSDOS: CALL VPRINT + DEFB CR,LF,BEL,'*** ERROR: DOS is not ZSDOS!',CR,LF + DEFB 0 + JP EXIT + + +;::::::::::::::::::::::::::::::::::::::::::::::::::::: +; VLIB - 0x114f +; Z3LIB - 0x1370 +; SYSLIB - 0x13e9 +; end addr 0x145e (begin DSEG) +;::::::::::::::::::::::::::::::::::::::::::::::::::::: + + +;::::: RAM STORAGE + + DSEG + +DOSBASE: DEFW 0 ; DOS base addr +OFLGADR: DEFW 0 ; addr FLAGS byte in ZSDOS hdr +ZPTHADR: DEFW 0 ; addr of Path in ENV +ZWHLADR: DEFW 0 ; addr of Wheel byte in ENV +TIMEDIS: DEFW 0 ; addr of Time routines disable vector +CHARCMD: DEFB 0 ; ExMod Time Stamp - remember char from cmdline +OFLGWIP: DEFB 0 ; Option Flag ('work in progress') +OFLGMSK: DEFB 0 ; effective Bit Mask for Option Flag +RUNMODE: DEFB 0 ; indicator run mode (0= interactive) + DEFB 0 ; not used +CHARTMP: DEFB 0 ; temporary storage of char +DOSTYVE: DEFW 0 ; (ZS)DOS type and version # + + DEFS 40H ; room for stack +STACK: DEFW 0 ; stack storage location + + END + + +;************************************************************************ +; Remarks jxl: +; From available options in ZSCFG2 it can be assumed that configuration +; area in ZSDOS v2 is almost identical to v1. Most options can be altered +; by changing the respective bit in the OPTION FLAG byte. +; +; Bit 7 6 5 4 3 2 1 0 +; \ \ \ \ \ \ \ \__ Public Files enable (1) - disable (0) +; \ \ \ \ \ \ \____ Public/Path Write enable (1) - disable (0) +; \ \ \ \ \ \______ Read-Only enable (1) - disable (0) +; \ \ \ \ \________ Fast Fixed Disk Relog enable (1) - disable (0) +; \ \ \ \__________ Disk Change Warning enable (1) - disable (0) +; \ \ \____________ ZCPR Path enable (1) - disable (0) +; \ \______________ Path w/o System Attr enable (1) - disable (0) +; \________________ Reserved +; +; Offsets to other features remained unchanged, compared to v1, and so +; Path and Wheel addresses can be found at the same locations. Apparently, +; a new "reference" Path address was added at offset Option Flag byte +8/9. +; It is used to reset the configurable Path address, but cannot be changed +; itself. +; Some changes were obviously be made to Time Stamp related options. An +; additional flag byte was implemented at offset Option Flag byte +1. The +; address of the Time Stamp routine (v1: GSTIME) was moved by one byte +; position and is located at offset +2/3. The pointer to remove Time Stamp +; routine (v1: UNLOAD) is now located at offset +6/7. +; Bytes at offset +4/5 are not in use anymore. +; +; TIME FLAG byte +; Bit 7 6 5 4 3 2 1 0 +; \ \ \__ Access stamp enable enable (1) - disable (0) +; \ \____ Create stamp enable (1) - disable (0) +; \______ Modify stamp enable (1) - disable (0) +; +; +; Source code +; ZSCFG2.COM, included in available B/P Bios package(s), was disassembled +; and extensively commented. Labels are up to seven chars long to comply +; with M-REL standards. However, it is recommended to use SLR tools that +; support labels up to sixteen chars. +; The program supports an interactive and a so-called expert mode. +; To indicate the respective mode, labels start either with "IM" or "EM" +; where appropriate. +; +; In its current state, the compiled/linked file matches exactly the +; original ZSCFG2.COM, i.e. no changes to the source were made. Possible +; optimisations detected during disassembly are marked with "#####" in the +; comment. +;************************************************************************ diff --git a/Source/BPBIOS/bpart.txt b/Source/BPBIOS/bpart.txt new file mode 100644 index 00000000..3c127ba2 --- /dev/null +++ b/Source/BPBIOS/bpart.txt @@ -0,0 +1,1247 @@ + Banked/Portable Basic IO System (B/P Bios) Pt I + by + Harold F. Bower and Cameron W. Cotrill + +=============================================================== +NOTE: The first two parts of this article were published in The +Computer Journal (TCJ), but the third part was pending when TCJ +ceased publishing. Harold F. Bower +=============================================================== +For the past several years we have attempted to address some of +what we consider to be fundamental problems in the 8-bit +Z80/Z180/HD64180 system software arena. Our first effort, ZSDOS, +was directed toward what we believed to be architectural weak- +nesses in CP/M and its clones in the late 1980s. Such weaknesses +included; inefficient code, inconsistent implementations of some +DOS functions, numerous different and incompatible file Date/Time +Stamping methods, and just plain errors (remember Function 37?). +Now in the 1990s, even more effort is needed to correct the +proliferation of systems designed on faulty (or at least weak) +architectures, and to provide a logical and consistent path to +increase the functionality of our systems. + +To understand our concerns in this area, let us review the way in +which CP/M 2.2, as modified by the Z-System, uses available +memory. For standard CP/M and compatible systems, the only +absolute memory addresses are contained in the Base Page which is +the range of 0 to 100H. All addresses above this point are +variable (within certain limits). User programs are normally run +from the Transient Program Area (TPA) which is the space from the +top of the Base Page (100H) to the base of the Basic Disk Operat- +ing System (BDOS). Figure 1 depicts assigned areas pictorially +along with some common elements assigned to each memory area. + + FFFFH +------------------+ + | Z-System Buffers | ENV, TCAP, IOP, FCP, RCP + +------------------+ (~5k) + | Bios | Code + ALV, CSV, Sector Buffers + +------------------+ (~5.5k) + | Operating System | CP/M 2.2, ZRDOS, ZSDOS1 + +------------------+ (3.5k) + | Command Processor| CCP, ZCPR3.x + +------------------+ (2k) + | Transient | + | | + | Program | + | | + | Area | + 0100H +------------------+ + | Base Page | IOBYTE, Jmp WB, Jmp Dos, FCB, Bufr + 0000H +------------------+ + Figure 1. Typical Z-System Memory Map + +The sizes depicted for the Z-System buffers is typical of many, +and allows a certain functionality. It is sometimes necessary to +delete some capabilities to add others, since every addition in +this area pushes the other components lower, decreasing available +TPA space. Likewise, any new features or more elaborate routines +in the Bios decreases available TPA. + +There have been some attempts at ameliorating these difficulties, +but none have directly addressed the entire problem. One system +in relatively widespread use is NZCOM. It allows a fairly easy +method of changing systems "on the fly". The main drawback, +however, is that to obtain large TPA, system features must be +sacrificed by deleting or downsizing the resident Z-System seg- +ments (FCP,IOP,RCP,NDR,TCAP). To us, this method is only viable +in systems which do not have extended memory capabilities. With +the ever-increasing use of systems based on the Hitachi 64180 and +Zilog Z180, other solutions are more attractive and offer a +larger TPA without sacrificing system capabilities. + +The final major factor contributing to shrinkage of TPA is the +increasing commonality of large hard disk drives. Disk space is +managed by a bit-mapped buffer (ALV) where each bit represents an +allocation block of storage space. Typical allocation units are +2k for floppy diskettes and 4k for Hard Disk Partitions. Assum- +ing 4k allocation blocks, a 20 MB drive needs approximately +20000/4 = 5000 bits or 625 bytes. With 80 to 100 MB drives being +common these days (one B/P user reported that the smallest drive +he could obtain was 850 MB!) you should see that several kilo- +bytes are now required, further reducing available TPA space. + +The first requirement to place us on the road to more powerful +systems is to overcome the 64k memory limit imposed on direct +access by the Z80 family of processors in a consistent and logi- +cal manner. Such a technique, generically called memory banking, +means that we can access more than 64k of memory for something +more than simply a RAM disk. + +One of the first attempts to tackle the 64k memory barrier was +Digital Research with CP/M Plus (aka CP/M3). While it banked +both portions of the BIOS as well as the Basic Disk Operating +System (BDOS) and included some useful additions to the BIOS, it +was relatively incompatible with CP/M 2.2 in many key features. +In addition, CP/M Plus made no provision for banking application +code. The adoption of a CP/M 2.2 standard for the Z-System has +served to widen the compatibility gap even further on the majori- +ty of our systems. + +There are some internal inconsistencies in the CP/M 3 architec- +ture as well which were never fully resolved. A prime case in +point is the function to return Disk Free Space (Function 46). +The specification states that three bytes are returned reflecting +the number of available 128-byte records on a disk. This equates +to 2^24 * 128 or 16,777,216 * 128 = 2,097,152 kB. While we know +of no one who has actually installed a single disk partition of +more than 2 Gigabytes on a Z-System, it would create problems +since CP/M Plus can handle disks up to eight times this size, but +not correctly report free space. Simply returning free space in +terms of 128-byte records is inconsistent as well since disk +space is allocated in blocks which have a minimum size of 1k, +with 2k and 4k commonly used. This is only one example of +several, and we do not consider it a viable system for future Z- +System growth; although it is still being actively installed. + +Several manufacturers have attempted to bank portions of operat- +ing system software over the years, yet either locked the soft- +ware into their hardware as Epson did with the QX-10, or made +such changes as to limit portability of common tools as in the +XLM-180. This latter system, while it used the Hitachi 64180 +processor with its memory mapping capabilities, required system +tailoring of much of the common Z-System software base. + +The release of MicroMint's SB-180 in the early 1980s marked a +decision point in Z-System development. First, it retained all +standard ZCPR3 definitions, it used a CP/M 2.2 compatible BDOS, +and it forced programmers to think more of portability and compa- +tibility in system software. This was a major thrust in the +development of XBIOS which placed the greatest possible amount of +BIOS code in alternate memory locations outside of the primary +64k address space. Furthermore, capabilities to bank additional +features (Resident System eXtensions, or RSXs) were widely sup- +ported with DateStamper, DosDisk and others requiring no sacri- +fice in TPA to execute. Since its last upgrade, however, several +severe problems have come to light, among them are the inability +to properly handle hard disk sizes greater than 32MB and sluggish +performance due to banking of Console routines. + +We considered this history and wanted to develop a system which +included as much machine independence as possible. Not only +should newer systems with the 64180/Z180 processor be included, +but S100 systems with banked memory, addon boards such as Terry +Hazen's MDISK for the Ampro Little Board, and homebrew systems as +well. The goal here was as much selfish desire as anything else. +By developing a single common architecture, only one tool for a +given purpose would be needed across a variety of machines. As +an example, Hal has several YASBECs, two SB-180s (one modified +with static memory), an SB180FX, an Ampro Little Board, a couple +of mongrel S-100 systems, and recently acquired a P112. Each +system had its own Formatter, Configuration utility, Clock type, +native disk formats, etc. To us, this seems out of place now, +particularly with the scarcity of systems programmers in the Z- +Community. It made more sense to develop a common software +architecture so that more programming resources could be devoted +to applications type efforts. + +Another goal of the effort was to retain the maximum compatibili- +ty with existing Z-System software for the same reasons cited +above. Customizing a huge number of common utilities as was done +in the XLM-180, seemed to be the wrong approach. We therefore +decided to retain the greatest possible commonality with CP/M 2.2 +(actually our ZSDOS), and use existing Z-System segments to their +greatest potential without sacrificing performance. As those of +you who tracked our efforts as we developed ZSDOS know, we do not +like slow systems or large code sizes (TCJ issues 37 and 38). We +also decided that our architecture had to be capable of outra- +geous expansion and extension capabilities without invalidating +previous software efforts. Further, we wanted to create a gener- +al purpose banked memory interface that allows applications +programs as well as the operating system to access alternate +banks of memory. The final results are the Banked & Portable +(B/P) Bios. + +B/P Bios attacks the memory problem in a manner which is easily +adaptable to different hardware. All HD64180/Z180-based systems +bank memory in 4k slices, and many S100 and addon systems bank in +16 or 32k increments. We therefore decided on an architecture +which retains common memory in the upper 32k of address space +(8000-FFFFH), and switches the lower 32k (0-7FFFH) among any +available banks of RAM. Figure 2 displays this architecture +pictorially. + + FFFFH +----------+ + | | + | BNK1 | + | | + 8000H +----------+ +----------+ +----------+ +----------+ + | | | |+ | |+ | |+ + | BNK0 | | System || | User || | RAM Disk ||+ + | | | || | || | ||| + 0000H +----------+ +----------+| +----------+| +----------+|| + +- - - - - + +- - - - - + +- - - - - +| + | Max Bank | + +----------+ + Figure 2. B/P Bios Memory Scheme + +BNK1 is ALWAYS present in the address space and is referred to as +the Common Bank. It contains all Z-System buffers, Common por- +tions of the Bios, BDOS and the Command Processor as well as the +upper portion of TPA. Part of the Bios which makes B/P unique is +the structure which allows controlled access to other banks in +the lower 32k. + +At least one 32k bank is required in a minimal banked B/P system. +The system bank, as a minimum, holds portions Bios and a copy of +the Command Processor which speeds Warm Boots by simply copying +the banked code to the Common bank and executing the warm entry. +Figure 3 depicts memory use in a maximally-configured banked +system. In such configurations the System bank holds banked +portions of; the ZSDos2 operating System, banked Command Proces- +sor, BIOS, and Hard Disk allocation bit maps. + + FFFFH +------------------+ + | Z-System Buffers | + +------------------+ + | User Space | + +------------------+ + | Bios | + +------------------+ + | Operating System | +------------------+ 8000H + +------------------+ / | Bios Buffers | + | Command Processor| / | Banked Bios Part | + +------------------+/ +------------------+ + 8000H | Transient | | Banked Dos Part | + | | +------------------+ + | Program | | Banked CCP Part | + | | +------------------+ + | Area | | CCP Restoral | + 0100H +------------------+ +------------------+ 0100H + | Base Page | | Base Page Copy | + 0000H +------------------+ +------------------+ 0000H + TPA (BNK0/BNK1) System Bank + Figure 3. Fully-banked Memory Map + +The B/P Bios began with one of Cam's superb architectures. He +started with the standard CP/M 2.2 Jump Table, added in those +from CP/M Plus with changes to correct some of the inconsisten- +cies, then added in a new series to permit logical and easy +access to new routines. The code, in assembly source form, was +divided into logically functioning elements, with the greatest +possible amount placed into machine independent modules. As an +example, the Disk deblocker and IOBYTE decoder functions are +machine independent and need no change between systems, while the +actual disk and character device drivers require custom tailoring +for each type of computer. Standard interfaces, in terms of +register usage and value limits, result in common software re- +quirements across vastly different hardware systems. + +Each software module of the Bios includes relocation directives +to the assembler telling it whether the code is to go into the +main memory, or into another bank of memory. If a non-banked +system is assembled, all code is placed into the main 64k area, +while banked systems use the main 64k area for common code and +data as well as banked code and data areas. All tools (format- +ter, configuration utility, etc) automatically accommodate both +types of Bios without any intervention. The choice of whether to +bank each section of code or not was painstakingly examined for +performance and size penalties. Many of our design choices may +be debated, but B/P is here and it works! + +By itself, fixing the Bios is not a complete answer to our cur- +rent Z-System dilemma, but it is a prerequisite. We also consid- +ered it essential to bank the Disk Operating System. Starting +with ZSDOS, Hal used the new BIOS banking functions to bank +significant portions of the BDOS. At every juncture, size and +speed were traded off to keep the system small and fast. We +corrected the flaw in the CP/M Plus Disk Size function cited +above by returning four bytes containing the number of kilobytes +free (a more meaningful measure). File Time/Date stamping func- +tions for DateStamper(tm), P2DOS (CP/M Plus compatible), and Joe +Wright's NZTIM are all embedded within the Operating System and +are concurrently active. While ZSDos2 is still a work in pro- +gress, copies are included in the B/P Bios package to allow users +to benefit from the newer system. Latest versions were posted in +the BPBIOS: directory on the Ladera Z-Node until its demise, and +no replacement is yet available. The most recent version of +ZSDos2 in 1993 added directory hashing for true speed demons. + +Also incorporated in ZSDos2 is a ZCPR34-compliant Command Line +Parser. With the permission of Jay Sage, we also modified ZCPR34 +to operate in the banked environment, added many common features +of Resident Command Processor packages, and simplified it to use +the new ZSDos2 Command Line Parser. By folding all features into +the CPR, the need for a Resident Command Processor (RCP) exten- +sion in high memory all but disappears, typically adding 2k to +the TPA. + +As a closing note to this first installment, systems using B/P +Bios, ZSDos2 and the expanded CPR are currently in operation on +the new D-X Designs Pty Ltd P112, Micromint's SB180, a modified +SB180 with static memory, two versions of the SB180FX, three +YASBEC configurations including a laptop with VGA LCD display, +Ampro Little Board (with Terry Hazen's MDISK expansion), and in +non-banked mode on a Compu/Time S100 and Teletek. All tools are +common across the hardware systems with a complete Z3 Environment +and additional segments typically resulting in the equivalent of +a "standard" 60k CP/M system. This size is without the RCP +typically used to enhance the Command Processor. + +The next part of this article will describe the B/P Bios inter- +faces and standards, while part 3 will cover proposed standards +for the evolving ZSDos2, its associated Command Processor and +some of the support utilities. + +=================================================================== + Banked/Portable Basic IO System (B/P Bios) Pt II + by + Harold F. Bower and Cameron W. Cotrill + +As we discussed in the first part of this article, our efforts in +the design and construction of our Banked/Portable Bios were +directed towards building an architecture that would viably +support applications on Z80/180 computers for a number of years. +One of the initial ground rules was a prohibition on the use of +Self-Modifying code. As in our development of ZSDOS, we want to +retain the ability to place operating system components into ROM +if desired. This goal was met, but at the price of slightly +increased code size, particularly in non-banked systems such as +those placed on system boot disks. Exceptions to this rule do +exist, but primarily in system components which are intended +specifically for execution from RAM such as portions dynamically +relocated at load time. + +Another key consideration addressed in B/P Bios was the need to +provide a mechanism to identify the Bios and to locate Bios- +specific data areas and options. The solution to this was Bios +Function 30 which returns, among other things, a pointer to the +start of a standardized data structure containing configuration +information. This vector allows examination or alteration of +various parameters such as Data Rates, Drive parameters and +configuration flags. Using this vector instead of assuming +absolute locations within the BIOS is crucial to obtaining and +maintaining portability and standardization. + +The Configuration Area pointer serves a secondary purpose as +well. The six bytes preceding the returned address point to a +string which must begin with the Ascii letters "B/P". The fol- +lowing three characters contain a suffixing identifier for the +hardware base. Between us, we have either implemented or planned +B/P Bios installations to varying degrees on the following sys- +tems: + + "-18" - MicroMint SB-180 (HD64180 CPU, 9266 FDC, 5380 SCSI) + "-FX" - MicroMint SB180FX (Z180 CPU, 9266 FDC, 53C80 CSI) + "-YS" - YASBEC (Z180 CPU, 1772 FDC, DP8490 SCSI) + "-DX" - D-X Designs P112 (Z182 CPU, 37C665 FDC, Flash ROM) + (Add-on 5380 SCSI supported) + "-CT" - Compu/Time S-100 set (Z80 CPU, 1795 FDC, 1MB Memory) + "-TT" - Teletek (Z80 CPU, 765 FDC) + "-AM" - Ampro Little Board (Z80 CPU, 1770 FDC, T. Hazen's MDISK) + "-XL" - XL M-180 SBC (HD64180 CPU, 9266 FDC, PIO SCSI) + +This method of identification can serve to prevent customized +programs from operating on the incorrect hardware. For example, +the HDBOOT hardware-specific program distributed for YASBEC and +Ampro Little Board computers will not modify a Hard Disk boot +record unless the system on the Boot Tracks contains either the +"-YS" or "-AM" identifiers. + +With the additions made to the ZCPR3 Environment Descriptor in +Version 3.4, it readily became apparent to us that the Environ- +ment belongs to low-level hardware-dependent portions of the +Operating System, with allowances being made for high-level use. +While this decision may be debated, we adopted the ENV structure +and require it within the Bios with only one necessary change. +The four bytes associated with the second printer have been +usurped to provide data on a resident User Space. To provide +compatibility with other vectors added to Operating System com- +ponents, the four bytes are reallocated as: + + 1 byte - Number of free 128-byte blocks + 2 bytes - Pointer to start of User Space + 1 byte - Total size in 128-byte blocks + +The User Space is always assigned below all other ZCPR3 System +Segments and the Starting Address Pointer serves double-duty as +the lowest address in reserved memory. This is needed in hard +disk systems since the ALV buffers are dynamically calculated at +system load (boot) time. For Non-banked systems, if the amount +of space needed by the ALV buffers extends beyond the base of the +User Space pointer, a warning is printed to alert users that a +smaller system is required to allow full use of the hard drive +without overwriting System Segments. In banked systems, the +check is performed against the end of the primary 32k System +Bank. The use of a byte to indicate amount of free space remain- +ing will allow multiple RSX-like additions to be chained into the +User Space in a (hopefully) controlled manner. A similar con- +struct is being developed for banked applications, but has not +yet been fully developed. + +As most of us are painfully aware, Floppy Disk formats in the +CP/M compatible world are woefully non-standardized. To maximize +the efficiency of B/P Bios, we have NO required format. Our +system may be assembled with hard-coded invariant formats (the +smallest code requirements), with calculated skew values or +indexed tables, or with a user-configurable suite of non-con- +flicting formats, including 3.5", 5.25" and 8" drives as well as +"High-Density" formats where the hardware is supported. For +standard distribution, the Ampro/SB-180 5.25" formats are includ- +ed in an auto-select mode. 8" drive capability is in the SB-180, +SB180FX, P112, Compu/Time and Teletek versions, but not in YASBEC +or Ampro Little Board since those controllers will not handle the +higher data rates. Using this scheme, tailoring options may be +used to gain every byte and clock cycle possible, for example, by +deleting 8" formats if you only have 3.5 or 5.25" drives connect- +ed to the system. + +The B/P BIOS is divided into a number of files, some of which are +machine dependent, and some are generic and need not be edited to +assemble a working system. Much use is made of conditional +assembly to include option-dependent modules and relocation +bases. The Basic file, BPBIO-xx.Z80, specifies which source code +elements are used to assemble the Bios image under the direction +of an included file, DEF-xx.LIB, which selects features and +contains Hardware-dependent equates. Modules requiring customi- +zation for different hardware systems are given names which end +with a generic "-xx" designator to identify specific versions. +These names correspond to the suffix embedded in the identifier +string covered above. By maintaining the maximum possible code +in common modules which require no alteration, B/P Bios is rela- +tively easy to convert to different machines. + +While some of these versions cannot take full advantage of B/P +Bios, such as the Ampro Little Board which, without Terry Hazen's +MDISK, contains only 64k of memory, the benefits of having only +one set of support utilities and common operating procedures +across different computers often outweigh the disadvantages of a +slightly larger Bios. Those of you with several different types +of computers will readily understand. + +With B/P Bios, systems may be changed "on the fly" in a manner +similar to that employed with NZBLITZ/NZCOM. The system placed +on the boot disk's system tracks must be relatively small to fit +in the limited space, often sacrificing features. Once started, +however, the rules change. A special loader is used to move pre- +configured system images in place and start execution. These +images are built from an assembled B/P Bios REL file, ZSDOS +version 1 or 2 ZRL file, and a Command Processor REL or ZRL file. +The utilities to build the image file and load it into position +account for both banked and unbanked component locations. The +build utility also allows you to alter many of the Environment +parameters as the image is built. For example, the extra large +Command Processor demonstrated several years ago at the Trenton +Computer Fest includes most of the common features from RCPs. +Consequently, RCP space is often not needed and may be removed +typically freeing 2k for the TPA. + +Different system images may be generated with BPBUILD and then +loaded as specific functions or configurations are desired, +without regard to the system on the Boot Tracks. Tailoring of +these image files is performed with the B/P Bios configuration +utility, BPCNFG, to include Startup Alias file names unique to +that system. In this manner, different images may chain from one +to another as system sizes and needs change. A given image file +might be duplicated with only minor configuration changes. Hal +uses this technique in system backups where two hard disk parti- +tions are activated for backups to external hard drives, but +different parameters are configured for various backup media and +drive types. + +To provide some comparative numbers, a YASBEC with a 20MB hard +drive is typically limited to a 53K non-banked system for place- +ment on the Boot Tracks. A 56K system is achieved simply by +banking portions of the Bios. With the banked ZSDos2 and the +associated large Command Processor, Z41, a 58.0K system is stan- +dard with the default 2K RCP and 1.5K IOP space reservations. +This expands to 60K with no RCP and 61.5K if no IOP is needed. +The large expansion in size with the banked ZSDos2 is due to +banking of the ALV and CSV bit storage areas needed for hard and +floppy drives. Placing these elements into the system bank means +that large system sizes are no longer dependent on the hard disk +sizes (yes, even a 200 MB hard drive on a YASBEC sports a 60K +system configuration), but with the penalty that normal programs +which count ALV bits to determine disk free space and file size +no longer function correctly. This difficulty has, in part, been +addressed by providing modules in the DSLIB utility library (a +companion to SYSLIB and Z3LIB) which "know" about ZSDos2 and +properly return disk free space values. Source code for DSLIB +was released to Z-Nodes several years ago, and many of the in- +cluded routines are used in our utilities, such as the ZXD direc- +tory lister provided as part of the B/P Bios package. + +If even more Transient Program Area is needed, one additional +means exists to expand available memory, but at a possible ex- +pense. Part of the BPBUILD process is to size the Code and Data +requirements of the relocatable modules, and locate them at +static addresses for loading. Since the resident portions of +both the Z41 Command Processor and ZSDos2 are smaller than their +non-banked counterparts, the lower limit for applications pro- +grams, which are allowed to overwrite the Command Processor, and +Resident System Extensions (RSXes) which nestle immediately below +the Command Processor see a higher memory address. The caveat to +this approach, however, is that only programs which use the +enhanced environment parameters compliant with ZCPR 3.4 and later +will function properly. To avoid such potential problems and +provide maximum commonality with existing CP/M programs, BPBUILD +also allows the user to direct that the Command Processor and +resident DOS elements be linked to begin at "standard" locations +reflecting sizes of 2K and 3.5K respectively. + +THE INTERFACE. + +B/P Bios entry points are contained in a Table of 3-byte Absolute +jumps at the beginning of the Bios Image. Parameters needed for +each function are passed to the Bios in specified registers. To +avoid future compatibility problems, some of the ground rules for +Bios construction include; No alteration of Alternate or Index +registers as a result of Bios calls, and all registers listed in +the documentation as being Preserved/Unaffected MUST be returned +to the calling program in their entry state. The first seventeen +jumps (indices 0-16) constitute the standard CP/M 2.2 jump table. + +Following those are additional sequences patterned roughly after +CP/M 3 and the B/P-unique extensions. The Bios entry points +listed in order of their appearance in the jump table are: + + 0 - CBOOT Execute Cold Start initialization on the first + execution. The code is later overwritten, and the + argument of this jump then points to the IOP Device + jump table. (all registers used) + 1 - WBOOT Execute Warm Restart initialization, reload the + Resident part of the Command Processor and log onto + the default drive. (all registers used) + 2 - CONST Return Console Input Status as; A=0FFH if Character + is ready, A=0 if No character is ready. (Uses AF) + 3 - CONIN Read a character from the Console, waiting until one + if ready, then return it in A masked as specified in + the Bios, Normally with Bit 7 set to 0. (Uses AF) + 4 - CONOUT Send the character in C register to the console masked + as specified in the Bios (Uses AF) + 5 - LIST Send the character in C register to the List Device + (normally a printer) masked as specified in the Bios. + (Uses AF) + 6 - AUXOUT Send the character in C register to the Auxiliary + Output masked as specified in the Bios. (Uses AF) + 7 - AUXIN Read a character from the Auxiliary Input port masked + as specified in the Bios. (Uses AF) + 8 - HOME Position the head(s) on the selected drive to Track 0. + (Uses All primary registers) + 9 - SELDSK Select the drive specified by the value in Drive C + where Drive A=0...P=15. (Uses All primary registers) +10 - SETTRK Select the Logical track contained in Register BC for + a future disk operation (All registers preserved) +11 - SETSEC Select the Logical sector contained in Register BC + for a future This difficulty has, in part, been + addressed by providing modules in the DSLIB utility + library (a companion to SYSLIB and Z3 disk operation + (All registers preserved) +12 - SETDMA Set the address in Register BC for a future disk + operation (All registers preserved) +13 - READ Read a Logical 128-byte sector from the Disk, Track + and Sector set by Functions 9-11 to the address set + with Function 12. On return, Register A=0 if the + operation was successful, Non-Zero if Errors occurred. + (Uses All primary registers) +14 - WRITE Write a logical 128-byte sector to the Disk, Track and + Sector set by Functions 9-11 from the address set with + Function 12. If Register C=1, an immediate write and + flush of the Bios buffer is performed. If C=0, the + write may be delayed due to the deblocking. (Uses all + Primary registers) +15 - LISTST Return A=FF if the Printer is ready to accept a charac- + ter for printing, otherwise return A=0. (Uses AF) +16 - SECTRN Translate the Logical Sector Number in register BC + (Only C used at present) to a Physical Sector number + using the Translation Table addressed in the Selected + Drive's DPH. (Uses All Primary regs) + +This ends the strict CP/M 2.2-compliant portion of the Bios Jump +Table. The next series of entry Jumps roughly follows those used +in CP/M Plus (aka CP/M 3), but with corrections to what we per- +ceived to be deficiencies in the calling parameters and struc- +tures. + +17 - CONOST Return A=FF if the Console is ready to accept another + output character, otherwise return A=0. (Uses AF) +18 - AUXIST Return A=FF if the Auxiliary Input has a character + waiting, otherwise return A=0. (Uses AF) +19 - AUXOST Return A=FF if the Aux. Output is ready to accept + another character for output, otherwise return A=0. + (Uses AF) +20 - DEVTBL This corresponds roughly to an analogous CP/M Plus + function although precise bit definitions vary some- + what. The Character IO table consists of four + devices; defaulting to COM1, COM2, PIO, and NUL. + Each has an input and output mask, data rate settings + and protocol flags. Not all defined settings (e.g. + ACK/NAK and XON/XOFF handshaking, etc) are imple- + mented in all versions, but are available for use. + (Uses HL) +21 - DEVINI Initialize Character IO settings and other specified + functions. This is very close to the CP/M Plus + function and can be used torestore IO configurations + after alteration by programs which directly access + hardware such as modem programs. (Uses all primary + registers) +22 - DRVTBL Return a Pointer to the DPH table for Drives A-P where + a 16-bit 00 entry means that no drive is defined. + (Uses HL) +23 - MULTIO +24 - FLUSH Write any pending Data to disk as mentioned in Func- + tion 14 above. (Uses all primary registers) +25 - MOVE Move number of bytes specified in BC from the location + starting at (HL) to an area addressed by (DE). For + banked moves, the Source and Destination banks must + have been previously specified with an XMOVE function. + Note that this function reverses the functions of the + DE and HL register pairs from the CP/M Plus function. + (Uses all Primary registers except A) +26 - TIME If Register C=0, Read the Date and Time to a 6-byte + field addressed by (DE). If C=1, Set the Date and + Time from 6-byte field addressed by (DE). On exit, + register A=1 if the operation was successful, A=0 if + an error occurred or No clock exists. The Date/Time + string is in ZSDOS format as opposed to Digital + Research's format used in CP/M Plus for this function. + Also, This function must conform to additional re- + quirements of DateStamper(c) in that on exit, register + E must contain the entry contents of (DE+5) and HL + must point to the entry (DE)+5. If the clock supports + 1/10 second increments, the current .1 second count + may be returned in register D. A recent addition + (suggested by Terry Hazen in TCJ #79) uses BC to + return the address of a free-running 8-bit counter + decremented every 100 milliseconds. Such a feature is + invaluable in user programs such as modem drivers. + (Uses all primary registers) +27 - SELMEM Select the Memory Bank specified in the A register and + make it active in the address range 0-7FFFH. (All + registers preserved) +28 - SETBNK Set the Bank Number in A for the next Disk IO. (All + registers preserved) +29 - XMOVE Set Source and Destination Bank numbers in registers C + and B respectively for a future Move (Function 25). + (All registers preserved) + +This marks the end of the CP/M Plus "Type" jumps and begins the +unique additions to the B/P Bios table to support Banking, Direct +IO and interfacing. + +30 - RETBIO Return the Bios version number and a pointer to + internal BIOS data areas as: + A = Bios Version Number + BC --> Page Address of B/P Bios + DE --> Start of Configuration area + HL --> Start of Device Vector table +31 - DIRDIO Execute low-level functions directly on Floppy or SCSI + devices. (described below) +32 - STFARC Set the bank number for a subsequent Function 33 + execution. (All resisters preserved) +33 - FRJP Switch to bank number specified with Function 32, then + execute routine at address in HL, returning to + address on stack top. (Uses all primary registers) +34 - FRCLR This entry is used for error exits from banked routines + to return to the entry bank. (Uses all primary + registers) +35 - FRGETB Load the byte addressed by HL from the bank number + specified by the C register into the register A. + (Uses A) +36 - FRGETW Load the Word addressed by HL from the bank number + specified by the C register into the DE register pair. + (Uses DE) +37 - FRPUTB Store the byte in register A to the memory addressed by + HL in the bank specified in register C. (All registers + preserved) +38 - FRPUTW Save the Word in DE to the memory addressed by HL in + the bank specified in register C. (All registers + preserved) +39 - RETMEM Return a Byte identifying the Memory Bank number + currently in context in the A Register. (Uses A) + + +DIRECT DISK IO. BIOS Function 31 permits low-level access to +Floppy and Hard Disks (currently via SCSI interface) by specify- +ing a Driver Number and desired Function. While some hardware +types do not support all of the parameters specified, particular- +ly for Floppy Drives, this architecture supports all types, +although specific systems may ignore certain functions. In this +manner, for example, a single Format program supports NEC765, +SMC9266, SMC37C665, DP8743 and WD1770/1772/179x controller types +with widely differing interfaces. Floppy Disk functions are +accessed by entering a 1 value into Register B (Floppy Driver +Number) and the desired function number in Register C, then +jumping to or calling BIOS Entry jump number 31. + +FLOPPY DISK SUBFUNCTIONS: + + 0 - (STMODE) Set the Floppy Disk Controller for Read/Write opns. + On entry, Register A contains a Density Flag (0 = Double, + 0FFH = Single Density). No data is returned from this + function. NOTE: This routine assumes that Functions 1 + (STSIZE) and 3 (STSECT) have been called first. (Uses AF) + 1 - (STSIZE) Set Drive Size (3.5/5.25" or 8"), Drive Speed (300 or + 360 rpm) and Motor Needed flag. On entry, A=0 for normal + floppy speed (synonymous with "Normal" 250 kbps MFM Double- + Density), A=0FFH for High speed motors (synonymous with "Hi- + Density" 500 kbps MFM). Register D=0 if the motor is always + on or no motor control is needed, while D=0FFH if motor + control is necessary. Finally, register E must contain the + drive size as; 0=Hard Disk, 001B=8" Drive, 010B=5.25" Drive, + and 011B=3.5" Drive. Nothing is returned from this command. + While all of these functions may not be supported on any + specific computer type, the interface from using programs + should always pass the necessary parameters for compatibility. + NOTE: This routine assumes that Function 2 (STHDRV) has been + called first. Call this routine before calling Function 0 + (STMODE). (Uses AF) + 2 - (STHDRV) Set Head and Drive Number for Disk Operations. This + routine is entered with register A containing the Floppy unit + number coded in bits 0 and 1 (Unit 0=00, 1=01 ..3=11), and the + Head in Bit 2 (0=Head 0, 1=Head 1). Nothing is returned from + this function. (Uses AF) + 3 - (STSECT) Set Physical Sector Number, Size and Last Sector + Number on the Track. On entry, Register A contains the + desired physical sector number desired, D contains the sector + size where 0=128 byte sectors, 1=256..3=1024, and E contains + the last sector number on a side. Normally register E is + unused in Western Digital controllers, but is needed with 765- + compatible units. Nothing is returned from this function. + (Uses AF) + 4 - (SPEC) Set Step Rate and Head Load/Unload Time. On entry, the + A register contains the drive step rate in milliseconds. + Within the Bios, this rate is rounded up to the nearest slower + controller rate if the specified rate is not an even match. + Implementation of this function in the Bios also accommodates + the need to adjust values reflecting the step rate when the + data rates are changed from 250 to 500 kbps and vice versa. + Register D should contain the desired Head Unload time in mil- + liseconds, and E to the desired Head Load time in mS. With + some controllers such as the Western Digital 177x and 179x + family, only the Step Rate is universally variable. In these + systems, rates signaled by the Bios settings are rounded up to + the closest fixed step rate such as the 2, 3, 5, or 6 milli- + second rates in the 1772 (YASBEC) or 6, 10, 20, or 30 milli- + second rates used in the 1770 (Ampro Little Board) and 1795 + (Compu/Time). Nothing is returned from this function. + (Uses AF) + 5 - (RECAL) - Recalibrate Drive (moves the head to track 0). There + are no entry parameters for this function. On exit, the zero + flag is Set and A=0 if no errors occurred, otherwise the Zero + flag is Reset and A is Non-Zero. NOTE: This routine assumes + that STHDRV, STSIZE and SPEC have been called first. (Uses AF) + 6 - (SEEK) - Set the Track for disk operations and seek to it. On + entry, Register A is set to the desired Track Number, D sig- + nifies whether Verification of the seek is required (D=0 for + No Verify, D=0FFH if verifying), and E indicates whether or + not to double-step (E <> 0 for Double-Step, E=0 for No Double- + Step). On exit, A=0 and the Zero Flag is Set (Z) if the + operation was successfully completed while A <> 0 and the Zero + Flag is cleared (NZ) if an error occurred. NOTE: This routine + assumes that STHDRV, STMODE and SPEC have been called first. + (Uses AF) + 7 - (SREAD) - Read from the floppy disk. On entry, HL must point + to a Buffer to receive the data read. It assumes that Mode, + Track, Head/Drive, and Sector have been previously set. On + exit, A=0 and the Zero flag is set (Z) if the sector was + satisfactorily read, A <> 0 and the Zero flag is cleared (NZ) + if an error occurred. (Uses AF and HL) + 8 - (SWRITE) - Write to the floppy disk. On entry, HL must point + to a Buffer from which to send the data. It assumes that + Mode, Head/Drive, Track, and Sector have been previously set. + On exit, A=0 and the Zero flag is set (Z) if the sector was + successfully written, A <> 0 and the Zero flag is cleared (NZ) + if an error occurred. (Uses AF and HL) + 9 - (READID) - Read the first correct ID information on a track. + There are no entry parameters for this function. The Zero + flag is set (Z) and A=0 if no errors occurred, otherwise the + Zero flag is Reset (NZ) and A is non-zero. NOTE: This routine + assumes that STHDRV and STMODE have been called first. + (Uses AF) +10 - (RETDST) - Return the status of a drive. There are no entry + parameters for this function. On exit, A contains the raw + unmasked status byte of the drive or the last operation + depending on the controller type, BC contains the binary + number representing the FDC controller type (e.g. 765, 9266, + 1772, etc), and HL contains the address of the status byte + returned in register A. NOTE: This routine assumes that + STHDRV has already been called. (Uses AF, BC and HL) +11 - (FMTTRK) - Format a complete track on one side of a Floppy + Disk. It assumes that the Mode, Head/Drive, Track, and + Sector have already been set. On entry, HL points to data + required by the controller to format a track. This varies + between controllers, so RETDST should be called to determine + controller type before setting up data structures. On entry, + D must also contain the number of Sectors per Track, and E + must contain the number of bytes to use for Gap 3 in the + floppy format. On exit, A=0 and the Zero flag is Set (Z) if + the operation was satisfactorily completed, A <> 0 and the + Zero flag cleared (NZ) if errors occurred. (Uses all primary + registers) + +HARD DISK SUBFUNCTIONS: + +These functions are available to directly access Hard Drives. To +date, only drives connected by a SCSI type interface have been +used, but the interface is generic enough to allow mapping to +other interfaces such as IDE. The functions are accessed by +loading the desired function number in the C register, loading a +2 (SCSI driver) into the B register and calling or jumping to +Jump number 31 in the Bios entry jump table. Since this inter- +face is not as standardized as Floppy functions in order to +handle SASI as well as SCSI devices, the interface has only basic +functions with the precise operations specified by the User in +the Command Descriptor Block passed with Function 2. This places +a greater burden on User programs, but it allows more flexibility +to take advantage of changing features in the newer SCSI drives. + +An additional constraint placed on the Hard Disk interface is the +restriction to 512 byte physical sectors at the interface. Since +most hard drives now default to this sector size, no difficulties +have been reported in the few years since B/P Bios has been +released, so this constraint should pose no serious limitation. + + 0 - Set User Data Area Address for Direct SCSI IO, Return number + of bytes available for the SCSI Command Descriptor Block. + On entry, DE must point to a 512 byte User Data Area to Send/ + Receive. This is mandatory since 512 bytes are always + returned from a direct access due to the wide variety of + controller types handled. On exit, A contains the number of + bytes available in the Command Descriptor Block which will + usually be 10, but may be scaled back to 6 in limited + applications. (Uses AF and HL) + + 1 - Set Physical Device bit and store Logical Unit Number (LUN) in + SCSI Command Block (Byte 1, bits 7-5) from byte in A. On + entry, register A contains a bit-mapped byte indicating the + SCSI Physical Unit number (bits 0-2) and Logical Unit Number + (bits 5-7). On exit, A returns a "1" bit in the proper + position for the SCSI physical drive unit with Bit 7 being the + host computer, Bit 0 indicating Unit 0, etc. (Uses AF) + + 2 - Direct SCSI driver. This routine performs the function + described by the command in the SCSI Command Descriptor Block + addressed by DE. On entry, register A must also contain a + flag signifying whether or not user data is to be written by + this command (A=0 if No data to be written, FF if the address + set with Function 0 contains user data to write). At the end + of the function, 512 bytes are always transferred from the + Bios IO Buffer to the User's Space set by Fcn 0. This may be + inefficient, but was the only way we could accommodate the + wide variety of different SASI/SCSI controllers within reason- + able code constraints. Additionally, Register A contains 0 if + the function performed with no errors, and 02H if a check + condition was encountered. Also, Register L returns the + unmasked Status byte (0FFH indicating a timeout error), and H + returns the first Message byte received. (Uses all primary + registers) + NOTE: This routine assumes the Command Block is properly + configured for the type of Hard Disk Controller set in B/P + Bios, and that the selected disk is properly described in the + Bios Unit definitions (if necessary). Errors in phasing + result in program exit and Warm Boot. It assumes the user + has executed Functions 0 and 1 to set the data transfer source/ + destination address and logical/physical drive addresses. + +In the final part of this series, we will describe some of the +utilities developed and modified to support banked systems and +address our ongoing efforts with the banked ZSDos2, Command +Processor and future directions. + +=================================================================== + Banked/Portable Basic IO System (B/P Bios) Pt III + by + Harold F. Bower and Cameron W. Cotrill + +Having covered the Bios in detail in Part 2 of this series, we +now turn our attention to the rest of the operating system. For +those who have seen or operate a B/P Bios-based system, you +probably wondered if the Command Processor (Z4x) or the Banked +Operating System (ZSDos2) will ever be finished. In a nutshell, +probably not. They are furnished with the B/P Bios package to +allow system owners to glimpse the possibilities and to take full +advantage of the Bios primitives as well as experiment with some +different concepts. With that said, ZSDos2 is still a "work-in- +progress". + +Banking the operating system creates some inefficiencies and +incompatibilities. An example of the former is that for file +functions, File Control Block (FCB) information must be copied to +high memory, the banked portion of the operating system swapped +in context, and the operation concluded. This is not the end, +however, for the modified FCB must then be copied back to the +User Transient Program Area (TPA) in case the application needs +to access the updated data such as record number which is au- +tomatically incremented after each sequential read or write. +This adds overhead and was optimized as much as possible. Also, +certain functions such as character IO were not banked at all to +keep responsive to acceptable levels. + +Incompatibilities were handled by documenting them, and providing +utilities adapted to handle the new features. An example of this +is the free space calculations handled by counting bits in the +Allocation Bit Map (ALV) buffer which contains one bit for each +allocation unit on the drive. ALV data is placed in the system +bank to allow large (several hundred megabyte) drives to be used +without sacrificing any TPA space. We provide the ZXD.COM direc- +tory lister (a heavily modified version of Richard Conn's XD) +linked with DSLIB routines which "know" about the banked systems +and correctly compute and return free space. DSLIB is freely +available from many systems. + +The last "standard" version of the banked ZSDos2 was produced in +1993 as ZS227G.ZRL, with a significant change released shortly +thereafter as ZS203.ZRL (the .ZRL type stands for Z-System Relo- +catable, a Microsoft .REL file with named Commons for selected Z- +System structures). This latter version supports "hashed" direc- +tories for very rapid access to files since it drastically reduc- +es the number of comparisons needed to locate files in the direc- +tory. Both are included in the distribution package for use. +The reasons why will become clear after a small tutorial. + +Conventional CP/M 2.2 (and clones) set a pointer to the first +file in a directory upon a Search First (function 17) then use a +sequential search method with Search Next (function 18) until the +request is satisfied or the list of files is exhausted. With +ZS203 running with a hashed directory (identified by a 20H in the +user byte of the first file on a disk when logged in), a Search +First request performs a mathematical calculation over a portion +of the FCB to obtain the number of a "bucket" which is a fixed +number of directory entries. Subsequent Search Next requests +then begin a sequential search until either the file is found, or +an uninitialized entry (E5H in the User byte) is located. For +sparsely-populated directories, the search seems nearly instanta- +neous, and a comparable time is taken to find the first file +placed in a disk as the last. Only in a very heavily-loaded disk +does the time approach that of a conventional CP/M 2.2 system. + +One nuance of this type of a directory structure is that removing +a file from the directory cannot be done in the common way by +placing an E5H in the User byte, since that signifies an unini- +tialized entry and would terminate a search if following entries +hashed to the same value. 0C6H was defined to mark an unused +(erased), but not terminal entry. Adding or renaming a file +computes the hash value, then examines the computed "bucket" +sequentially until either a C6H or E5H byte is found, then uses +that position. + +With this brief description, you might be wondering why anyone +would want to continue with non-hashed directories, so to 'fess +up...there are some incompatibilities. First, this is a "classi- +cal" hashing structure taught in Computer Science classes and not +the table-driven method used in CP/M+, so anyone using tools for +that system will probably encounter problems. Next, directory +listing programs that do not recognize the C6H byte in the User +position as a deleted entry will probably report the file with a +weird user number. In addition, DateStamper(tm) File Stamps are +not supported since the !!!TIME&.DAT needed by that system cannot +use the first directory entry due to the hash flag, so you must +use P2DOS or ZSTIME stamps. + +If you carefully tickled the gray matter while reading the de- +scription, you probably wondered what the impact of a REName +function would be on performance. In a word..horrible! To +rename a file, the new name must be hashed and an available +directory entry (or more) must be located. Next, the contents of +each directory entry after the File Type field for the old file +name must be copied to the corresponding new location, and the +old entries must be marked as unused with the C6H User byte. For +this reason, programs such as WordStar4 which frequently rename +files pause noticeably with much head activity during these +operations. + +Finally, the biggest caution of all with hashed directories is to +insure that you NEVER write to a hashed directory with a non- +hashed Operating System. For this reason, your A: drive upon +bootup should always contain a Non-hashed directory. When creat- +ing a large image file (see Part 2), you can exchange drive and +partitions to place a hashed unit as A: but only with ZS203 as +the Operating system. Should you make an error, you will prob- +ably see files in a directory list that you cannot access and +can't remove without using raw sector reads and writes with DU3 +or suffering further corruption of the directory system! + +With all of these cautions, you might wonder why anyone in their +right mind would want to choose this scheme! The short answer is +SPEED!!! Once set up properly, overlays, such as those used with +WordStar4 load almost instantly. This is due to finding the file +in the directory very quickly, on the first disk read for sparse- +ly-occupied directories. This is where you really begin to +appreciate how much time is wasted in the operating system simply +searching for files. Consequently, we offer it as an alternative +for learning. + +Both variants of ZSDos2 contain some new Operating System func- +tion calls which can be used to advantage by your programs if +they first verify that you are running under ZSDos2. They are +also used by many of the support utilities as well as the banked +Command Processor. They are: + +46 - Return Disk Free Space in kilobytes to DMA location (4 + bytes) + Enter: C = 46 + E = drive (A=0) + Exit : Drive free space in K is at DMA+0 (LSB)..DMA+3 (MSB) + A reflects 0 on success, <>0 on Error logging drive + +49 - Return Address of Environment Descriptor + Enter: C = 49 + Exit : HL - Points to Z34+ Environment Descriptor + +152 - Parse Filename to Z34 specs + Enter: C = 152 + DE - points to FCB to receive parse + DMA points to start of string to parse + Exit : A = L = Number of Question Marks in fn.ft + DE - points to character after last one parsed (delim) + FCB+15 will be 0 for Ok parse, 0FFH if errors occurred + + +Z41.ZRL is the latest version of the banked Command Processor +based on ZCPR34. One of the first things you will probably +notice is that warm boots of the system after completing an +operation that overwrites the Command Processor is that the +system does not reload the Command Processor from Disk. A copy +of the portion that resides in TPA space is retained in the +System Bank and simply restored via an Inter-Bank block move; +much faster than a disk seek and read! + +Z41 integrates many of the RCP features commonly in use and may +mean that you can completely eliminate the use of a Resident +Command Processor (RCP) at a typical saving of 2k bytes. Dis- +playing the built-in Help with Wheel privileges (the Z-System +"Superuser" equivalent) results in the following: + + CPR + CLS cp DATE DIR ECHO + era feed get go H + jump list NOTE p poke + port prot reg ren res + save sp spop TIME type + VER WHL + +Of the 27 resident commands available, only the ones listed in +capital letters are available when the Wheel Byte is turned off, +such as when operating in a dial in BBS system. Even some func- +tions available to all users, have certain features disabled, +such as the DATE/TIME Setting functions which are reserved for +those with Wheel privileges. For those not familiar with the Z- +System, these built-in functions are: + + CLS - Clear the screen using the current TermCap definition + cp - Copy a file from one location to another + DATE - Display the date + DIR - Display files in the current or a specified directory + ECHO - Print the remainder of the line to the Console + era - Erase a file or files + feed - Send a Form Feed byte to the Paper (eject) + get - Load a file from the current directory to a specified + memory address + go - Execute code at 100H. Typically used to re-execute + command files + H - Help. Display list of available commands in CP, RCP and + FCP + jump - Execute code at specified address + list - Send specified file to the List Device (usually printer) + NOTE - Simply ignore the rest of the line + p - Display (Peek) memory contents + poke - Enter Hex bytes into memory at specified address + port - Read from or write a byte to a specified IO Port + prot - Set/Clear System and Read-Only Attribute bits in + specified file + reg - Set, increment, decrement, clear the 10 ZCPR3 Registers + ren - Rename a file + res - Reset Disk Subsystem and relog all drives + save - Write memory from 100h to file for specified length + sp - Return free space on specified drive + spop - "Pop" the value from the Top of the ZCPR3 Shell Stack + TIME - Display the time (Set if Wheel) + type - Display a file on the Console + VER - Display the Z41, ZSDos2 and B/P Bios Version Numbers + WHL - Turn Wheel Byte On (w/password), Off or Display status + +This Command Processor relies on ZSDos2 and a banked B/P Bios and +will NOT work without them. To keep duplicated code to a mini- +mum, the Command Line parser in ZSDos2 as well as the other new +functions are used instead of discrete code used in other Command +Processor Replacements. As additional enhancements, the prompt +line can optionally display the time from ZSDos2, and the date +display can be configured to display in either "Mmm DD,YY" (US +style) or "DD Mmm YY" (European) forms. These two features were +"hard-wired" in the original Z40 distributed several years ago +but have since been made configurable via the CONFZ4.COM Utility +with Z41. + +The actual TPA memory requirements of Z41 and ZSDos2 are less +than the "standard" CP/M sizes of 2 and 3.5 kilobytes respective- +ly. For the largest possible TPA space, they can be autosized +(an option in the BPBUILD utility). Unfortunately, there are +still some legacy programs out there that incorrectly subtract +the BDOS "standard" size from the base of the BIOS jump table +resulting in an incorrect memory reference. To handle this +occasional hiccup, there is an option to locate the start of Z41 +and ZSDos2 TPA portions at "standard" locations below the BIOS +with dead space on the high end padding to the next higher system +element. This has proven to be an adequate method of handling +the occasional problem if the need arises. + +We have developed a suite of utilities to support B/P Bios in the +same manner as we did with the original ZSDOS1. Several of these +are modifications to older routines and contain changes necessary +to function in the banked environment. In addition, a few of +them have been released in source code to illustrate methods of +accessing the enhanced features of B/P Bios. The core programs +distributed with the package are: + +BPBUILD - Create a loadable banked image file. Input files + needed include the output of assembling a BPBIO-xx file + (in MicroSoft REL format), a REL or ZRL image of an + Operating System (ZSDOS1 or the current version of the + banked ZSDos2 are recommended), and a REL or ZRL image of + a Command Processor (ZCPR33.REL or later, or the current + banked ZCPR4 are recommended). + +BPCNFG - Configure the B/P Bios options in a system Image File, + Diskette Boot Tracks, or executing in memory. Due to the + memory mapping, some features such as re-defining hard + drive partitions are disabled if configuring the currently + executing system. + +BPDBUG - A DDT-like debugger with support for B/P Bios Banked + memory. While primitive, it allows poking around in a + banked or non-banked environment. + +BPFORMAT - Format a floppy drive under B/P Bios from either built-in + formats (from available DPB definitions) or from a library + of alien formats. + +BPSWAP - Swap B/P Bios logical drive definitions. + +BPSYSGEN - Our generic version of the classic SYSGEN program used to + add a system image onto the boot sectors of a hard or floppy + disk. + +EMULATE - Lock any or all Floppy Disk Drive(s) to specified formats, + native or alien, from a Database of formats. Also displays + current formats and restores drives to auto-selection if the + Bios was assembled with AUTOSEL option. + +HDBOOT - Add Hard Drive Boot record to an image applied to the first + tracks of a Hard Drive with BPSYSGEN (currently only avail- + able for YASBEC and AMPRO). + +HDIAG - Run Diagnostics, Format, Verify and examine Hard Drive + parameters. While SASI/SCSI controllers have been supported + since the first release, GIDE support was added in 1997. + Due to the wide variation in disks, controllers, vendors and + versions, not all functions are supported on all variations. + The program currently recognizes the following Hard Disk/ + Controller subsystems: + + Adaptec ACB-4000A + Shugart 1610-3 / Xebec 1410A + Seagate SCSI + Shugart 1610-4 (Minimal SCSI) + Conner SCSI + Maxtor SCSI + Quantum SCSI + Syquest SCSI + GIDE (Generic IDE) + +INIRAMD - Initialize a RAM Drive and prepare it for P2DOS and/or + DateStamper style file stamps. + +INITDIR - ZSDOS utility to initialize disks with P2DOS (CP/M+) + stamps. + +INSTAL12 - Install CCP, DOS, B/P Bios in a MOVCPM "type" image from + standard size (2k CCP, 3.5k DOS, ~4.375k Bios) files. + +IOPINIT - Initialize an IOP Buffer defined in a Z3 Environment to + the standard Dummy format and patch it into the Jump Table. + This utility was necessary to overcome size constraints in + a Boot Track image where some of the initialization code + normally in a Bios had to be removed to fit existing popular + disk formats. + +LDSYS - Load an IMG file created by BPBUILD into memory and begin + execution. + +MOVxxSYS - System generation facility for Boot Track installation + where the "xx" identifies the version. System images of 50 + to 53k are typically configured in non-banked bootable + systems. An image size of 53k will typically accommodate a + 20 MB Hard drive with three partitions. If you configure + for more storage or use 2k allocation blocks, you may have + to configure a smaller system. You will be warned of this + necessity by a beep and "Mem Ovfl" warning on bootup. These + programs can create a system image in memory, or write the + image to a disk file for later transfer to boot tracks with + BPSYSGEN. + +PARK - Move Hard Drive heads to designated Landing Zone if available + (provided in source code form as an example of using direct + drivers). + +SETCLOK - Extract a clock from ZSDOS1 CLOCKS.DAT file and set the + B/P Bios clock from a library of different clocks. This is + a legacy program from ZSDOS1 and is usually not needed. + +SIZERAM - Test the memory complement of the system and display the + RAM allocation by 32k bank number as well as the parameters + reported in the Environment. + +SHOWHD - Display current Drive Disk Parameter Block data on any + system to assist in maintaining Hard Drive Partitions during + conversion to B/P Bios. + +TDD - Customized version of ZSDOS utility TD to display, set or + update the Bios Interrupt clock as well as a growing number + of additional clocks such as the Dallas DS-1216E (aka No- + Slot-Clock) and Dallas DS-1202 used in the D-X Designs' P112. + +TURB - A routine available for Z8S180 and Z80182 systems which allow + bypassing of the divide-by-two circuit from the crystal + oscillator via chip-level register settings. It also allows + addition and removal of Memory Wait States to accommodate + speed changes. This program was originally named TURBO, but + shortened when we realized the name conflict with Borland's + Pascal Compiler. + +ZSCFG2 - Configure ZSDos2 options in running system. + +ZXD - Directory Lister from ZSDOS1, updated to function properly + with the banked ZSDos2. Other directory listers may not + correctly display disk free space in banked systems. + +As with all of the programs we produce, each of the above utili- +ties contains built-in Help accessed with the // argument, and is +aware of necessary environment limitations. We have attempted to +make them as bulletproof as possible, but they have been known to +err. User feedback is always welcome in this regard. + +WHAT'S NEXT? + +This package is probably the end of the line for us. Will we +ever release the source? Yes, when we decide to stop supporting +it. Until then, it remains our "labor of love" product and an +exciting as well as challenging learning experience. We are all +a little older, hopefully wiser, and looking for new challenges, +so stay tuned for UZI180, an adaptation of Doug Braun's original +Unix Z80 Implementation, enhanced by Stefan Nitschke for the +Z280, now ported to the Zilog Z180 family. + +-------------------------------------------------------------- +Closing note: The B/P Bios System is released under the GNU GPL +in 2001. It is now Free Software subject to the provisions of +the GPL. H.F.Bower, 2 December 2001. diff --git a/Source/Build.cmd b/Source/Build.cmd index d258ef54..e654579f 100644 --- a/Source/Build.cmd +++ b/Source/Build.cmd @@ -4,7 +4,6 @@ setlocal :: call BuildDoc || exit /b call BuildProp || exit /b call BuildShared || exit /b -call BuildBP || exit /b call BuildImages || exit /b call BuildROM %* || exit /b call BuildZRC || exit /b diff --git a/Source/BuildBP.cmd b/Source/BuildBP.cmd deleted file mode 100644 index c1139fdd..00000000 --- a/Source/BuildBP.cmd +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -setlocal - -pushd BPBIOS && call Build || exit /b & popd \ No newline at end of file diff --git a/Source/BuildShared.cmd b/Source/BuildShared.cmd index 38aa8fc6..8d7afc47 100644 --- a/Source/BuildShared.cmd +++ b/Source/BuildShared.cmd @@ -8,8 +8,10 @@ pushd QPM && call Build || exit /b & popd pushd ZCPR && call Build || exit /b & popd pushd ZCPR-DJ && call Build || exit /b & popd pushd ZSDOS && call Build || exit /b & popd +pushd ZSDOS2 && call Build || exit /b & popd pushd CPM3 && call Build || exit /b & popd pushd ZPM3 && call Build || exit /b & popd +pushd BPBIOS && call Build || exit /b & popd pushd CPNET && call Build || exit /b & popd pushd pSys && call Build || exit /b & popd pushd Apps && call Build || exit /b & popd diff --git a/Source/CBIOS/cbios.asm b/Source/CBIOS/cbios.asm index 26c55e33..6f4c8a87 100644 --- a/Source/CBIOS/cbios.asm +++ b/Source/CBIOS/cbios.asm @@ -3201,8 +3201,9 @@ MAKDPH0: ; HANDLE RAM/ROM CP DIODEV_MD ; RAM/ROM DISK? JR Z,MAKDPH0 ; HANDLE SPECIAL LD DE,DPB_FD144 ; PRELOAD FLOPPY DPB - CP DIODEV_FD ; FLOPPY? - JR Z,MAKDPH1 ; IF SO, PROCEED TO DPH CREATION + ;CP DIODEV_FD ; FLOPPY? + BIT 7,C ; FLOPPY? + JR NZ,MAKDPH1 ; IF SO, PROCEED TO DPH CREATION LD DE,DPB_RF ; PRELOAD RAM FLOPPY DPB CP DIODEV_RF ; RAM FLOPPY? JR Z,MAKDPH1 ; IF SO, PROCEED TO DPH CREATION @@ -3381,7 +3382,7 @@ DEVUNK .DB "UNK$" RST 08 ; CALL HBIOS LD A,D ; RESULTANT DEVICE TYPE PUSH DE ; NEED TO SAVE UNIT NUMBER (IN E) - AND $0F ; ISOLATE DEVICE BITS + AND $1F ; ISOLATE DEVICE BITS ADD A,A ; MULTIPLY BY TWO FOR WORD TABLE LD HL,DEVTBL ; POINT TO START OF DEVICE NAME TABLE CALL ADDHLA ; ADD A TO HL TO POINT TO TABLE ENTRY @@ -3407,6 +3408,7 @@ DEVTBL: ; DEVICE TABLE .DW DEV04, DEV05, DEV06, DEV07 .DW DEV08, DEV09, DEV10, DEV11 .DW DEV12, DEV13, DEV14, DEV15 + .DW DEV16 ; DEVUNK .DB "???$" DEV00 .DB "MD$" @@ -3424,7 +3426,8 @@ DEV11 .DB "IMM$" DEV12 .DB "SYQ$" DEV13 .DB "CHUSB$" DEV14 .DB "CHSD$" -DEV15 .EQU DEVUNK +DEV15 .DB "USB$" +DEV16 .EQU DEVUNK ; #ENDIF ; diff --git a/Source/CPM22/ReadMe.txt b/Source/CPM22/ReadMe.txt index e46a6b08..3a0b2fd2 100644 --- a/Source/CPM22/ReadMe.txt +++ b/Source/CPM22/ReadMe.txt @@ -38,7 +38,7 @@ It is an independent disassembly and reconstruction of CCP/BDOS. DRI CPM22PAT01 was already applied. Unclear why, but the BDOS source was checking for a blank instead of a ctrl-s in the KBSTAT routine. Ctrl-s seems to be correct based on all other -BDOS images I have encountered. Also, these files imbed the +BDOS images I have encountered. Also, these files embed the CP/M version number into the serial number fields. Other than this, they are byte identical to the OS2CCP/OS3BDOS images above. @@ -51,17 +51,24 @@ BDOS22.ASM - Modified ORG & fix for ctrl-S CCPB03 & BDOSB01 ---------------- -Sourced from N8VEM effort to create an enhanced -variant of CP/M 2.2. +These files were derived from a disassembly of the Jade DD CP/M-80 +image by William Beech in 1982. -It appears to be a disassembly and reconstruction of CCP/BDOS, -but there are no comments attributing the work. DRI CPM22PAT01 -was already applied. The message string literals are all +- Modified by Bill Beech for global CP/M size configuration + and separate CCP and BDOSE 2013. + +- Modified by Bill Beech for addition of MON + command and display/change of user on command line + 1984. Also removed all SN checks. + +Eventually modified as part of the N8VEM project and converted to +the Z80 instruction set. + +DRI CPM22PAT01 has been applied. The message string literals are all in CAPS in BDOS. Additionally, there is explicit filler of 0x55 value bytes at the end of the CCP/BDOS files padding their length out to full page. Other than this, the BDOS -is byte identical to the others above. CCP contains multiple -enhancements and is, therefore, not identical to others. +is byte identical to the others above. CCPB03.ASM - Enhanced reassembly of CCP diff --git a/Source/Clean.cmd b/Source/Clean.cmd index 0b879078..c878314b 100644 --- a/Source/Clean.cmd +++ b/Source/Clean.cmd @@ -8,6 +8,7 @@ pushd QPM && call Clean.cmd & popd pushd ZCPR && call Clean.cmd & popd pushd ZCPR-DJ && call Clean.cmd & popd pushd ZSDOS && call Clean.cmd & popd +pushd ZSDOS2 && call Clean.cmd & popd pushd CBIOS && call Clean.cmd & popd pushd CPM3 && call Clean.cmd & popd pushd ZPM3 && call Clean.cmd & popd diff --git a/Source/Doc/Applications.md b/Source/Doc/Applications.md index 8dd5a8e6..5d881b33 100644 --- a/Source/Doc/Applications.md +++ b/Source/Doc/Applications.md @@ -56,8 +56,22 @@ User Guide, and for the sake of completeness there is some overlap here. When a RomWBW system is started the user is presented with a sign-on message at the default console detailing the RomWBW version and build date. The system follows this with the list of hardware that it has -discovered, a list of devices and the system units assigned to them, -before finally inviting the to select a boot device with the prompt: +discovered, a list of devices and the system units assigned to them. + +If autoboot is configured then the message (below) will count down +and once 0 is reached the system will automatically boot with the configured +options + +``` +AutoBoot in 3 Seconds ( aborts, now)... +``` + +Pressing `esc` - will bypass the auto boot process going immediately +to the `Boot` prompt, or pressing `enter` - will proceed with autoboot +immediately. Auto boot is configured using the `W` boot menu option. + +If autoboot is bypassed (or not configured) the user is asked to +select a boot device with the prompt: ``` Boot [H=Help]: @@ -74,18 +88,23 @@ Furthermore, a ROM application may also be started from this prompt. This start-up process is described in some detailed in the RomWBW User Guide, and there is some overlap here. -## Help +#### Help After pressing H or ? at the boot prompt the user will be presented with the following list of available commands: ``` -L - List ROM Applications -D - Device Inventory -R - Reboot System -I [] - Set Console Interface/Baud code -V [] - View/Set HBIOS Diagnostic Verbosity -[.] - Boot Disk Unit/Slice +Boot [H=Help]: H + + L - List ROM Applications + D - Device Inventory + S - Slice Inventory + R - Reboot System + W - RomWBW Configure + I [] - Set Console Interface/Baud code + V [] - View/Set HBIOS Diagnostic Verbosity + N - Network Boot + [.] - Boot Disk Unit/Slice ``` The function performed by each command is described below: @@ -102,24 +121,45 @@ D: system was started. +S: + +: Displays the list of disk Slices that contain a label indicating that + they may be bootable. See [SLABEL (Slice Label)] for more details about labels. + + R: : Will restart the system. Note that this does not reset hardware devices in the same way that power-on or pressing the reset button would. +W: + +: Runs the [SYSCONF (System Configuration)] utility allowing RomWBW + configuration stored in Non Volatile memory to be changed. + + I: : Allows the user to select the interface connected to the console, and optionally the Baud rate. This could be used to allow the system to be operated from a second console. + V: : Enables the display of invalid RomWBW HBIOS API calls. This option is very unlikely to be used by a user and is used for development purposes. + +N: + +: Boot into CP/M via an RCBus Wiznet MT011 network module if configured. + Section 10 of the $doc_user$ provides complete instructions for setting + up a CP/NET based network under RomWBW including network booting. + + And, finally, the system may be booted by specifying the unit number, and optional slice, separated by a period('.'), of where the disk operating system software is located - eg 2, 4.1, 5.3 @@ -127,7 +167,7 @@ system software is located - eg 2, 4.1, 5.3 Alternatively, a RomWBW ROM application may be started by pressing the appropriate key from the applications menu, shown in the following section. -## List ROM Applications +#### List ROM Applications If the user presses the L key at the Boot Loader prompt then the system will display the list of ROM applications that are built into RomWBW. If a command @@ -137,16 +177,19 @@ first displaying the menu. The ROM applications available from the boot prompt are: ``` -M: Monitor -C: CP/M 2.2 -Z: Z-System -B: BASIC -T: Tasty BASIC -F: Forth -P: Play a Game -N: Network Boot -X: XModem Flash Updater -U: User App +Boot [H=Help]: L + +ROM Applications: + + M: Monitor + Z: Z-System + C: CP/M 2.2 + F: Forth + B: BASIC + T: Tasty BASIC + P: Play a Game + X: XModem Flash Updater + U: User App ``` Each of these will now be described in greater detail. @@ -168,11 +211,11 @@ language and there is no ability to save to persistent storage (disks). The available memory area for programming is `0100h-EDFFh`. The following areas are reserved: -Memory Area | Function -------------|----------------------------------- -`0000-00FFh`| Jump and restart (RST) vectors -`EE00-FDFFh`| Monitor -`FE00-FFFFh`| HBIOS proxy +| Memory Area | Function | +|----------------|---------------------------------| +| `0000-00FFh` | Jump and restart (RST) vectors | +| `EE00-FDFFh` | Monitor | +| `FE00-FFFFh` | HBIOS proxy | The monitor uses a prompt in the format of `xx>` where xx is the RomWBW bank id number. For example, the prompt may look like this @@ -198,7 +241,7 @@ allow selecting alternate banks. There now follows a more detailed guide to using the RomWBW Monitor program: -### Command Summary +### Monitor Commands **`?`** - Will display a summary of the available commands. @@ -222,13 +265,13 @@ T xxxx - X-modem transfer to memory location xxxx X - Exit monitor ``` -### Cold Boot +#### Cold Boot **`B`** - Performs a cold boot of the RomWBW system. A complete re-initialization of the system is performed and the system returns to the Boot Loader prompt. -### Dump Memory +#### Dump Memory **`D xxxx [yyyy]`** - Dump memory from hex location xxxx to yyyy on the screen as lines of 16 hexadecimal bytes with their @@ -261,7 +304,7 @@ Example: `D 100 1FF` 01F0: 01 C5 01 F0 F8 CF E5 26 00 0E 0A CD 39 02 7D 3C .Å.ðøÏå&...Í9.}< ``` -### Fill Memory +#### Fill Memory **`F xxxx yyyy zz`** - Fill memory from hex xxxx to yyyy with a single value of zz over the full range. The Dump command @@ -269,7 +312,7 @@ can be used to confirm that the fill completed as expected. A good way to zero out memory areas before writing machine data for debug purposes. -### Halt System +#### Halt System **`H`** - Halt system. A Z80 HALT instruction is executed. The system remains in the halt state until the system is @@ -277,20 +320,20 @@ physically rebooted. Interrupts will not restart the system. On systems that support a HALT status LED, the LED will be illuminated. -### Input from Port +#### Input from Port **`I xxxx`** - Input data from port xxxx and display to the screen. This command is used to read values from hardware I/O ports and display the contents in hexadecimal. -### Keyboard Echo +#### Keyboard Echo **`K`** - Echo any key-presses from the terminal. Press 'ESC' key to quit. This facility provides that any key stroke sent to the computer will be echoed back to the terminal. File down loads will be echoed as well while this facility is ‘on’. -### Load Hex +#### Load Hex **`L`** - Load a Intel Hex data via the terminal program. The load address is defined in the hex file of the @@ -304,21 +347,21 @@ Keep in mind that this will be transient unless the system supports battery backed memory. Saving to memory drive is not supported. -### Move Memory +#### Move Memory **`M xxxx yyyy zzzz`** - Move hex memory block xxxx to yyyy to memory starting at hex location zzzz. Care should be taken to insure that there is enough memory at the destination so that code does not get over-written or memory wrapped around. -### Output to Port +#### Output to Port **`O xxxx yy`** - Output data byte xx to port xxxx. This command is used to send hexadecimal values to hardware I/O ports to verify their operation and is the companion to the I operation. Use clip leaded LEDs to confirm the data written. -### Program Memory +#### Program Memory **`P xxxx`** - Program memory location xxxx. This routine will allow you to program a hexadecimal value 'into memory starting @@ -333,7 +376,7 @@ remote computer. An excellent online resource for looking up opcodes for entry can be found here: . -### Run Program +#### Run Program **`R xxxx [[yy] [zzzz]]`** - Run program at location xxxx. If optional arguments yy and zzzz are entered they are loaded into the @@ -342,7 +385,7 @@ Monitor is saved on the stack so the program can return to the monitor. On return to the monitor, the contents of the A, HL, DE and BC registers are displayed. -### Set Bank +#### Set Bank **`S xx`** - Set the physical memory bank to the RomWBW Bank Id indicated by xx. Memory addresses @@ -367,12 +410,12 @@ Section 4 of the $doc_sys$ provides detail on how Bank Ids map to the physical memory of the system and also how specific banks are utilized by RomWBW. -### Undo Bank +#### Undo Bank **`U`** - Change the bank in memory back to the previously selected bank. This command should be used in conjunction with the S command. -### X-Modem Transfer +#### X-Modem Transfer **`T xxxx`** - Receive an X-modem file transfer and load it into memory starting at location xxxx. @@ -380,116 +423,10 @@ memory starting at location xxxx. 128 byte blocks and checksum mode is the only supported protocol. -### Exit Monitor +#### Exit Monitor **`X`** - Exit the monitor program back to the main boot menu. -## RomWBW System Configuration - -System Configuration (`SYSCONF`) is a utility that allows system configuration to -be set, dynamically and stored in NVRAM provided by an RTC chip. - -(`SYSCONF`) is both a ROM application ('W' Menu option), and a CP/M utility. -Noting however the CP/M utility is not included on an disk image, it is found in -the `Binary/Applications` folder of the RomWBW distribution. - -The $doc_user$ has additional information on the use of NVRAM to set your -system configuration. - -### Basic Operation - -The application is an interactive application; it does not have a command line syntax. -Instead commands are executed from within the application in a command line structure. - -When you first start the (`SYSCONF`) utility it will display the current switches -followed by a command listing. - -When you first run the (`SYSCONF`) utility the NVRAM will be uninitialised, and can -be initialised using the (R)eset command, which writes default values to NVRAM. - -Updates are done immediately to NVRAM as you enter them, i.e. there is no confirm -changes step. If you make any incorrect changes, you simply need to enter a new -command to set the Switch value correctly. - -Once a change has been made it is available, however it may not take effect until -the next system reboot. This is dependent on the Switch itself. - -If no NVRAM is provided by your hardware, then running this application will just -report the missing hardware and exit immediately. - -To exit from the application use the (Q)uit command. - -### Commands and Syntax - -The following are the accepted commands, unless otherwise specified a "Space" -character is used to delimit parameters in the command. - -| Command | Argument(s) | Description | -|------------|------------------|-----------------------------------------------| -| (P)rint | -none- | Display a list of the current switch value(s) | -| (S)et | {SW} {val},... | Sets an Switch {SW} with specific values(s) | -| (R)eset | -none- | Reset all setting to default | -| (H)elp | {SW} | Provides help on the syntax (values) | -| (Q)uit | -none- | Exit the application | - -**Where** - -| Argument | Description | -|-----------|----------------------------------------------------------------------| -| {SW} | Switch ID, typically this is 2 character name to identify the switch | -| {val},... | a "Comma" separated list of values to set into the switch | - -### Switch Options - -#### Auto Boot (AB) - -This switch will define if the system will perform auto boot at the RomWBW boot prompt. -Enabling this will not prevent a user from typing a boot command, so long as the timeout is not -exceeded. When configured this replaces the (`AUTO_CMD`) variable -defined in build configuration. - -Making changes to auto boot has no affect until the next reboot. - -**Arguments** - -| Type | Arguments | Description | -|----------|------------|--------------------------------------------------------| -| Enable | 'E' | Auto Boot. eg. "E,10" will auto boot, after 10 seconds | -| | Timout | Timeout in seconds in the range 0-15, 0 = immediate | -| Disabled | 'D' | No Auto Boot. e.g. "D" will disable autoboot | - -**Examples** - -| Command | Description | -|-----------------------|---------------------------------------------------| -| S AB E,10 | Enable Auto Boot with 10 second delay | -| S AB D | Disable Auto Boot | - -#### Boot Options (BO) - -This switch will define the boot command to be executed when auto boot is -enabled. When configured this replaces the (`AUTO_CMD`) variable -defined in the ROM build configuration. - -Making changes to boot options has no affect until the next reboot. - -**Arguments** - -| Type | Arguments | Description | -|------|------------------|----------------------------------------------------------| -| Disk | 'D' | Disk Boot. eg. "D,2,14" will boot, disk unit 2, slice 14 | -| | Disk Unit Number | Unit number in the range 0-127 | -| | Disk Slice | Slice in the range 0-255, use 0 for floppy boot | -| ROM | 'R' | ROM App. e.g. "R,M" will boot the Monitor App | -| | Rom App Name | single character used on the Menu to identify the app | - -**Examples** - -| Command | Description | -|-------------|----------------------------------------------------------| -| S BO D,2,14 | Set the default boot from Disk; Unit 2, Slice 14 | -| S BO R,M | Set the default boot to be the (M)onitor Rom Application | - ## CP/M 2.2 This option will boot the CP/M 2.2 disk operating system @@ -624,15 +561,15 @@ above. ### Structure of Forth source files -File | Description ---------------|----------------------------- -camel80.azm | Code Primitives - camel80d.azm | CPU Dependencies - camel80h.azm | High Level words - camel80r.azm | RomWBW additions -glosshi.txt | Glossary of high level words -glosslo.txt | Glossary of low level words -glossr.txt | Glossary of RomWBW additions +| File | Description | +|--------------|------------------------------| +| camel80.azm | Code Primitives | +| camel80d.azm | CPU Dependencies | +| camel80h.azm | High Level words | +| camel80r.azm | RomWBW additions | +| glosshi.txt | Glossary of high level words | +| glosslo.txt | Glossary of low level words | +| glossr.txt | Glossary of RomWBW additions | ### RomWBW Additions @@ -648,19 +585,17 @@ Extensions and changes to this implementation compared to the original distribut - James Bowman's double precision words have been added from his RC2014 version: . -Word | Syntax | Description ---------|----------------------------|--------------------------------- -D+ | d1 d2 -- d1+d2 | Add double numbers -2>R | d -- | 2 to R -2R> | d -- | fetch 2 from R -M*/ | d1 n2 u3 -- d=(d1*n2)/u3 | double precision mult. div -SVC | hl de bc n -- hl de bc af | Execute a RomWBW function -P! | n p -- | Write a byte to a I/O port -P@ | p -- n | Read a byte from and I/O port - -## Play a Game +| Word | Syntax | Description | +|------|----------------------------|-------------------------------| +| D+ | d1 d2 -- d1+d2 | Add double numbers | +| 2>R | d -- | 2 to R | +| 2R> | d -- | fetch 2 from R | +| M*/ | d1 n2 u3 -- d=(d1*n2)/u3 | double precision mult. div | +| SVC | hl de bc n -- hl de bc af | Execute a RomWBW function | +| P! | n p -- | Write a byte to a I/O port | +| P@ | p -- n | Read a byte from and I/O port | -### 2048 +## Play a Game (2048) 2048 is a puzzle game that can be both mindless and challenging. It appears deceptively simple but failure can creep up on you suddenly. @@ -735,44 +670,40 @@ This is how I lost this game: Press Q at any time to bring up the option to Quit or Restart the game. -## Network Boot - -If your RomWBW system is equipped with an RCBus MT011 module, it is -possible to boot into CP/M 2.2 directly from a CP/NET network server. -This means that the operating system will be loaded directly from the -network server and all of your drive letters will be provided by the -network server. - -This function requires substantial knowledge of CP/NET and it's -implementation within RomWBW. Section 10 of the $doc_user$ provides -complete instructions for setting up a CP/NET based network under RomWBW -including a section on network booting. - ## Xmodem Flash Updater -The RomWBW Xmodem flash updater provides the capability to update RomWBW from the boot loader using an x-modem file transfer. It offers similar capabilities to Will Sowerbutts FLASH4 utility except that the flashing process occurs during the file transfer. +The RomWBW Xmodem flash updater provides the capability to update RomWBW +from the boot loader using an x-modem file transfer. It offers similar +capabilities to Will Sowerbutts FLASH4 utility except that the flashing +process occurs during the file transfer. These are the key differences between the two methods are: -Xmodem Flash Updater | FLASH.COM (aka FLASH4) ---------------------------------|----------------- -Available from the boot loader | Well proven and tested -Xmodem transfer is integrated | Wider range of supported chips and hardware -Integrated checksum utilities | Wider range of supported platforms -Capability to copy a ROM image | Only reprograms sectors that have changed -More convenient one step process | Ability save and verify ROM images -No intermediate storage required | Progress display while flashing -. | Displays chip identification information -. | Faster file transfer - -The major disadvantages of the Updater is that it is new and relatively untested. There is the risk that a failed transfer will result in a partially flashed and unbootable ROM. There are some limitations on serial transfer speeds. - -The updater utility was initially intended to support the Retrobrew SBC-V2-005 platform using Atmel 39SF040 flash chips but has now been extended to be more generic in operation. +| Xmodem Flash Updater | FLASH.COM (aka FLASH4) | +|----------------------------------|----------------------------------------------| +| Available from the boot loader | Well proven and tested | +| Xmodem transfer is integrated | Wider range of supported chips and hardware | +| Integrated checksum utilities | Wider range of supported platforms | +| Capability to copy a ROM image | Only reprograms sectors that have changed | +| More convenient one step process | Ability save and verify ROM images | +| No intermediate storage required | Progress display while flashing | +| . | Displays chip identification information | +| . | Faster file transfer | + +The major disadvantages of the Updater is that it is new and relatively +untested. There is the risk that a failed transfer will result in a +partially flashed and unbootable ROM. There are some limitations on +serial transfer speeds. + +The updater utility was initially intended to support the Retrobrew SBC-V2-005 +platform using Atmel 39SF040 flash chips but has now been extended to be +more generic in operation. Supported flash chips are 39SF040, 29F040, AT49F040, AT29C040, M29F040 , MX29F040, A29010B, A29040B -The Atmel 39SF040 chip is recommended as it can erase and write 4Kb sectors. Other chips require the whole chip to be erased. +The Atmel 39SF040 chip is recommended as it can erase and write 4Kb sectors. +Other chips require the whole chip to be erased. ### Usage @@ -784,24 +715,40 @@ In most cases, completing a ROM update is a simple as: 4. Initiating an X-modem transfer of your ROM image on your console device 5. Selecting option R - Reboot -If your console device is not able to transfer a ROM image i.e. your console is a VDU then you will have to use the console options to identify which character-input/output device is to be used as the serial device for transfer. +If your console device is not able to transfer a ROM image i.e. your console +is a VDU then you will have to use the console options to identify which +character-input/output device is to be used as the serial device for transfer. -When your console is the serial device used for the transfer, no progress information is displayed as this would disrupt the x-modem file transfer. If you use an alternate character-input/output devices as the serial device for the transfer then progress information will be displayed on the console device. +When your console is the serial device used for the transfer, no progress +information is displayed as this would disrupt the x-modem file transfer. +If you use an alternate character-input/output devices as the serial device +for the transfer then progress information will be displayed on the console device. -Due to different platform processor speeds, serials speeds and flow control capabilities the default console or serial device speed may need to be reduced for a successful transfer and flash to occur. The **Set Console Interface/Baud code** option at the Boot Loader can be used to change the speed if required. Additionally, the Updater has options to set to and revert from a recommended speed. +Due to different platform processor speeds, serials speeds and flow +control capabilities the default console or serial device speed may +need to be reduced for a successful transfer and flash to occur. +The **Set Console Interface/Baud code** option at the Boot Loader can +be used to change the speed if required. Additionally, the Updater has +options to set to and revert from a recommended speed. See the RomWBW Applications guide for additional information on performing upgrades. ### Console Options + Option ( C ) - Set Console Device Option ( S ) - Set Serial Device -By default the updater assumes that the current console is a serial device and that the ROM file to be flashed will also be transferred across this device, so the Console and Serial device are both the same. +By default the updater assumes that the current console is a serial device +and that the ROM file to be flashed will also be transferred across this +device, so the Console and Serial device are both the same. -Either device can be can be change to another character-input/output device but the updater will always expect to receive the x-modem transfer on the **Serial Device** +Either device can be can be change to another character-input/output +device but the updater will always expect to receive the x-modem +transfer on the **Serial Device** -The advantage of transferring on a different device to the console is that progress information can be displayed during the transfer. +The advantage of transferring on a different device to the console +is that progress information can be displayed during the transfer. Option ( > ) - Set Recommended Baud Rate @@ -870,21 +817,32 @@ load CP/M and perform the normal x-modem / flash process to recover. Option ( 1 ) and ( 2 ) - Calculate and display CRC32 of 1st or 2nd 512k ROM. Option ( 3 ) - Calculate and display CRC32 of a 1024k (2x512Kb) ROM. -Can be used to verify if a ROM image has been transferred and flashed correctly. Refer to the Tera Term section below for details on configuring the automatic display of a files CRC after it has been transferred. +Can be used to verify if a ROM image has been transferred and flashed +correctly. Refer to the Tera Term section below for details on +configuring the automatic display of a files CRC after it has been +transferred. -In Windows, right clicking on a file should also give you a context menu option CRC SHA which will allow you to select a CRC32 calculation to be done on the selected file. +In Windows, right clicking on a file should also give you a context +menu option CRC SHA which will allow you to select a CRC32 calculation +to be done on the selected file. ### Tera Term macro configuration -Macros are a useful tool for automatic common tasks. There are a number of instances where using macros to facilitate the update process could be worthwhile if you are: +Macros are a useful tool for automatic common tasks. There are a +number of instances where using macros to facilitate the update +process could be worthwhile if you are: * Following the RomWBW development builds. * Doing lots of configuration changes. * Doing development on RomWBW drivers -Macros can be used to automate sending ROM updates or images and for my own purposed I have set up a separate macro for transferring each of the standard build ROM, my own custom configuration ROM and update ROM. +Macros can be used to automate sending ROM updates or images and +for my own purposed I have set up a separate macro for transferring +each of the standard build ROM, my own custom configuration ROM +and update ROM. -An example macro file to send an *.upd file, using checksum mode and display the crc32 value of the transmitted file: +An example macro file to send an *.upd file, using checksum mode +and display the crc32 value of the transmitted file: ``` Xmodem send, checksum, display crc32 @@ -896,39 +854,45 @@ messagebox inputstr 'crc32' ### Serial speed guidelines -As identified in the introduction, there are limitations on serial speed depending on processor speed and flow control settings. Listed below are some of the results identified during testing. - -Configuration | Processor Speed | Maximum Serial Speed ------------------------|-----------------|--------------------- -UART no flow control | 2MHz | 9600 -UART no flow control | 4MHz | 19200 -UART no flow control | 5MHz | 19200 -UART no flow control | 8MHz | 38400 -UART no flow control | 10MHz | 38400 -USB-fifo 2MHz+ | | n/a -ASCI no flow control | 18.432MHz | 9600 -ASCI with flow control | 18.432MHz | 38400 +As identified in the introduction, there are limitations on serial +speed depending on processor speed and flow control settings. +Listed below are some of the results identified during testing. + +| Configuration | Processor Speed | Maximum Serial Speed | +|------------------------|-----------------|----------------------| +| UART no flow control | 2MHz | 9600 | +| UART no flow control | 4MHz | 19200 | +| UART no flow control | 5MHz | 19200 | +| UART no flow control | 8MHz | 38400 | +| UART no flow control | 10MHz | 38400 | +| USB-fifo | 2MHz+ | n/a | +| ASCI no flow control | 18.432MHz | 9600 | +| ASCI with flow control | 18.432MHz | 38400 | The **Set Recommend Baud Rate** option in the Updater menu follows the following guidelines. -Processor Speed | Baud Rate -----------------|---------- -1MHz | 4800 -2-3MHz | 9600 -4-7MHz | 19200 -8-20MHz | 38400 +| Processor Speed | Baud Rate | +|-----------------|-----------| +| 1MHz | 4800 | +| 2-3MHz | 9600 | +| 4-7MHz | 19200 | +| 8-20MHz | 38400 | These can be customized in the updater.asm source code in the CLKTBL table if desired. Feedback to the RomWBW developers on these guidelines would be appreciated. ### Notes -All testing was done with Tera Term x-modem, Forcing checksum mode using macros was found to give the most reliable transfer. -Partial writes can be completed with 39SF040 chips. Other chips require entire flash to be erased before being written. -An SBC V2-005 MegaFlash or Z80 MBC required for 1mb flash support. The Updater assumes both chips are same type -Failure handling has not been tested. -Timing broadly calibrated on a Z80 SBC-v2 -Unabios not supported +Notes +* All testing was done with Tera Term x-modem, Forcing checksum mode + using macros was found to give the most reliable transfer. +* Partial writes can be completed with 39SF040 chips. Other chips + require entire flash to be erased before being written. +* An SBC V2-005 MegaFlash or Z80 MBC required for 1mb flash support. + The Updater assumes both chips are same type +* Failure handling has not been tested. +* Timing broadly calibrated on a Z80 SBC-v2 +* Unabios not supported ## User Application @@ -2192,6 +2156,146 @@ discover ports that are 'write-only'. `\clearpage`{=latex} +## SYSCONF (System Configuration) + +| SYSCONF | | +| --------------------|---| +| ROM-based |Yes| +| Disk-based |Yes| + +System Configuration (`SYSCONF`) is a utility that allows system configuration to +be set, dynamically and stored in NVRAM provided by an RTC chip. + +(`SYSCONF`) is both a ROM utility ('W' Menu option), and a CP/M application. +Noting however the CP/M application is not included on an disk image, it is found in +the `Binary/Applications` folder of the RomWBW distribution. + +The section "Setting NVRAM Options" in the $doc_user$ has additional information +on the use of NVRAM to set your system configuration. + +#### Syntax + +The application is an interactive application; it does not have a command line syntax. +Instead commands are executed from within the application in a command line structure. +`SYSCONF` command takes no arguments. + +| `SYSCONF` + +#### Usage + +When you first start the (`SYSCONF`) utility it will display the current switches +followed by a command listing. e.g. + +``` +RomWBW System Config Utility + +Current Configuration: + [BO] / Boot Options: ROM (App = "H") + [AB] / Auto Boot: Disabled + +Commands: + (P)rint - Display Current settings + (S)et {SW} {val}[,{val}[,{val}]]- Set a switch value(s) + (R)eset - Init NVRAM to Defaults + (H)elp [{SW}] - This help menu, or help on a switch + e(X)it - Exit Configuration + +$ +``` + +When you run (`SYSCONF`) for the first time the NVRAM will be uninitialised, and can +be initialised using the (R)eset command, which writes default values to NVRAM. + +Updates are done immediately to NVRAM as you enter them, i.e. there is no confirm +changes step. If you make any incorrect changes, you simply need to enter a new +command to set the Switch value correctly. + +Once a change has been made it is available, however it may not take effect until +the next system reboot. This is dependent on the Switch itself. + +If no NVRAM is provided by your hardware, then running this application will just +report the missing hardware and exit immediately. + +To exit from the application use the (Q)uit command. + +#### Commands and Syntax + +The following are the accepted commands, unless otherwise specified a "Space" +character is used to delimit parameters in the command. + +| Command | Argument(s) | Description | +|-----------|------------------|-----------------------------------------------| +| (P)rint | -none- | Display a list of the current switch value(s) | +| (S)et | {SW} {val},... | Sets an Switch {SW} with specific values(s) | +| (R)eset | -none- | Reset all setting to default | +| (H)elp | {SW} | Provides help on the syntax (values) | +| e(X)it | -none- | Exit the application | + +**Where** + +| Argument | Description | +|-----------|----------------------------------------------------------------------| +| {SW} | Switch ID, typically this is 2 character name to identify the switch | +| {val},... | a "Comma" separated list of values to set into the switch | + +#### Switch Options + +#### Auto Boot (AB) + +This switch will define if the system will perform auto boot at the RomWBW boot prompt. +Enabling this will not prevent a user from typing a boot command, so long as the timeout is not +exceeded. When configured this replaces the (`AUTO_CMD`) variable +defined in build configuration. + +Making changes to auto boot has no affect until the next reboot. + +**Arguments** + +| Type | Arguments | Description | +|----------|------------|--------------------------------------------------------| +| Enable | 'E' | Auto Boot. eg. "E,10" will auto boot, after 10 seconds | +| | Timout | Timeout in seconds in the range 0-15, 0 = immediate | +| Disabled | 'D' | No Auto Boot. e.g. "D" will disable autoboot | + +**Examples** + +| Command | Description | +|-----------------------|---------------------------------------------------| +| S AB E,10 | Enable Auto Boot with 10 second delay | +| S AB D | Disable Auto Boot | + +#### Boot Options (BO) + +This switch will define the boot command to be executed when auto boot is +enabled. When configured this replaces the (`AUTO_CMD`) variable +defined in the ROM build configuration. + +Making changes to boot options has no affect until the next reboot. + +**Arguments** + +| Type | Arguments | Description | +|------|------------------|----------------------------------------------------------| +| Disk | 'D' | Disk Boot. eg. "D,2,14" will boot, disk unit 2, slice 14 | +| | Disk Unit Number | Unit number in the range 0-127 | +| | Disk Slice | Slice in the range 0-255, use 0 for floppy boot | +| ROM | 'R' | ROM App. e.g. "R,M" will boot the Monitor App | +| | Rom App Name | single character used on the Menu to identify the app | + +**Examples** + +| Command | Description | +|-------------|----------------------------------------------------------| +| S BO D,2,14 | Set the default boot from Disk; Unit 2, Slice 14 | +| S BO R,M | Set the default boot to be the (M)onitor Rom Application | + +#### Etymology + +The `SYSCONF` utility is an original product specific to RomWBW, source code is included. +`SYSCONF` was contributed by Mark Pruden. + +`\clearpage`{=latex} + ## SYSCOPY (System Copy) | SYSCOPY | | @@ -2438,10 +2542,11 @@ whether support for it is included in the RomWBW HBIOS configuration | `-MSX` | Force MSX port addresses A0H/A1H (no PSG detection) | | `-RC` | Force RCBus port addresses D8H/D0H (no PSG detection) | | `--HBIOS` | Utilise HBIOS' sound driver | -| `+T1` | Play tune an octave higher | -| `+T2` | Play tune two octaves higher | -| `-T1` | Play tune an octave lower | -| `-T2` | Play tune two octaves lower | +| `-DELAY` | Force delay mode (don't use hardware timer) | +| `+T1` | Play tune an octave higher | +| `+T2` | Play tune two octaves higher | +| `-T1` | Play tune an octave lower | +| `-T2` | Play tune two octaves lower | The +t and -t options apply only to HBIOS mode operation. The `-MSX`, `-RC`, and `--HBIOS` options are mutually exclusive. See Notes below. @@ -2465,7 +2570,7 @@ an error message. Some hardware (notably Why-Em-Ulator) cannot be detected due limitations of the emulation. In such cases, you can force the use of the two -most common port addresses using the `-msx` or `-rc` options. +most common port addresses using the `-MSX` or `-RC` options. On Z180 systems, I/O wait states are added when writing to the sound chip to avoid exceeding its speed limitations. On Z80 systems, you @@ -2473,9 +2578,13 @@ will need to ensure that the CPU clock speed of your system does not exceed the timing limitations of your sound chip. The application probes for an active system timer and uses it to -accurately pace the sound file output. If no system timer is +accurately pace the sound file playback. If no system timer is available, a delay loop is calculated instead. The delay loop will not -be as accurate as the system timer. +be as accurate as the system timer. If the `-DELAY` options is +specified on the command line, then the delay loop will be used +regardless of whether the system has a hardware timer. This is useful +if the hardware timer does not run at the 50Hz desired for sound +playback. There are two modes of operation. A direct hardware interface for the AY-3-8910 or YM2149 chips, or a compatibility layer thru HBIOS supporting diff --git a/Source/Doc/Basic.h b/Source/Doc/Basic.h index bea16f6f..33ecb620 100644 --- a/Source/Doc/Basic.h +++ b/Source/Doc/Basic.h @@ -14,7 +14,14 @@ $define{doc_sys}{[RomWBW System Guide]($doc_root$/RomWBW System Guide.pdf)}$ $define{doc_apps}{[RomWBW Applications]($doc_root$/RomWBW Applications.pdf)}$ $define{doc_catalog}{[RomWBW Disk Catalog]($doc_root$/RomWBW Disk Catalog.pdf)}$ $define{doc_hardware}{[RomWBW Hardware]($doc_root$/RomWBW Hardware.pdf)}$ - +$ifdef{GFM}$ + $define{doc_intro}{[RomWBW Introduction](Introduction.md)}$ + $define{doc_user}{[RomWBW User Guide](UserGuide.md)}$ + $define{doc_sys}{[RomWBW System Guide](SystemGuide.md)}$ + $define{doc_apps}{[RomWBW Applications](Applications.md)}$ + $define{doc_catalog}{[RomWBW Disk Catalog](Catalog.md)}$ + $define{doc_hardware}{[RomWBW Hardware](Hardware.md)}$ +$endif$ --- title: $doc_product$ $doc_title$ subtitle: $doc_ver$ diff --git a/Source/Doc/Catalog.md b/Source/Doc/Catalog.md index 34889ac5..3ca4f099 100644 --- a/Source/Doc/Catalog.md +++ b/Source/Doc/Catalog.md @@ -70,11 +70,12 @@ disks should now be fully described. CP/M 3. Applications have been patched according to the DRI patch list. -- **ZPM3**: Digital Research CP/M-80 2.2 Distribution Files +- **ZPM3**: ZPM3 Distribution Files - Documentation: *CPM Manual.pdf* + Documentation: *ZPM3.txt* - These files are from Simeon Cran's ZPM3 operating system distribution. + These files are from Simeon Cran's official distribution of ZPM3. + All known patches have been applied. `\clearpage`{=latex} @@ -573,7 +574,7 @@ This is a generic ZPM3 adaptation for RomWBW. The following files came from from Microcode Consulting. The official distribution files can be found on the Microcode Consulting website at -[https://www.microcodeconsulting.com/z80/qpm.htm]. +. Also included in this image are debugz, and linkz frm the same company. This disk includes the standard DRI CP/M 2.2 files in addition to the @@ -651,7 +652,7 @@ look a little strange depending on the terminal emulation you are using. User area 4 contains a full implementation of the CP/NET 1.2 client provided by Doug Miller. Please refer to -[https://github.com/durgadas311/cpnet-z80] for more information, + for more information, complete documentation and the latest source code. Please refer to the RomWBW User Guide for instructions on installing @@ -666,12 +667,12 @@ The following are found in | **File** | **CP/NET Version** | **OS** | **Hardware** | |-----------------|---------------------|-----------------|-------------------------| -| CPN12MT.LBR | CP/NET 1.2 | CP/M 2.2 | RCBus w/ MT011 | -| CPN3MT.LBR | CP/NET 3 | CP/M 3 | RCBus w/ MT011 | -| CPN12DUO.LBR | CP/NET 1.2 | CP/M 2.2 | Duodyne w/ Disk I/O | -| CPN3DUO.LBR | CP/NET 3 | CP/M 3 | Duodyne w/ Disk I/O | -| CPN12SER.LBR | CP/NET 1.2 | CP/M 2.2 | RomWBW Serial Port | -| CPN3SER.LBR | CP/NET 3 | CP/M 3 | RomWBW Serial Port | +| `CPN12MT.LBR` | CP/NET 1.2 | CP/M 2.2 | RCBus w/ MT011 | +| `CPN3MT.LBR` | CP/NET 3 | CP/M 3 | RCBus w/ MT011 | +| `CPN12DUO.LBR` | CP/NET 1.2 | CP/M 2.2 | Duodyne w/ Disk I/O | +| `CPN3DUO.LBR` | CP/NET 3 | CP/M 3 | Duodyne w/ Disk I/O | +| `CPN12SER.LBR` | CP/NET 1.2 | CP/M 2.2 | RomWBW Serial Port | +| `CPN3SER.LBR` | CP/NET 3 | CP/M 3 | RomWBW Serial Port | ## General Purpose Applications @@ -927,12 +928,12 @@ The following files are found in | **File** | **Description** | |----------------|-----------------------------------------------------------| -| HDIR.COM | | -| R.COM | transfer files between the simulator and host file system | -| RSETSIMH.COM | -- | -| TIMER.COM | -- | -| URL.COM | -- | -| W.COM | transfer files between the simulator and host file system | +| `HDIR.COM` | | +| `R.COM` | transfer files between the simulator and host file system | +| `RSETSIMH.COM` | -- | +| `TIMER.COM` | -- | +| `URL.COM` | -- | +| `W.COM` | transfer files between the simulator and host file system | ## Testing Applications @@ -979,7 +980,7 @@ The following files are found in | `ZEXDOC.COM` | Z80 Instruction Set Exerciser | And The following CPU Tests - Which are probably originally from this source. -[https://github.com/raxoft/z80test] + | **File** | **Description** | |----------------|---------------------------------------------------------------| @@ -1002,7 +1003,7 @@ including MS-DOS, Apple II DOS 3.3 and PRoDOS, Commodore 64, Macintosh and Amiga. This disk contains the CP/M version of that compiler. A cross-compiler for MS-DOS or Windows XP is also available. -For full documentation, see [https://www.aztecmuseum.ca] +For full documentation, see The user manual is available in the Doc/Language directory Aztec_C_1.06_User_Manual_Mar84.pdf @@ -1048,38 +1049,79 @@ NOTE : The above is incomplete The Cowgol 2.0 compiler and related tools. These files were provided by Ladislau Szilagyi and were sourced -from his GitHub repository at [https://github.com/Laci1953/Cowgol_on_CP_M]. +from his GitHub repository at . The primary distribution site for Cowgol 2.0 is at -[https://github.com/davidgiven/cowgol]. +. The user manual is available in the Doc/Language directory -Cowgol Language.pdf +Cowgol Language.pdf. The following files are found in * /Source/Images/d_cowgol -| **File** | **Description** | -|--------------|--------------------------------------------| -| ADVENT.COW | Adventure game program source | -| ADVENT.SUB | Submit file to build ADVENT | -| ADVENT?.TXT | Adventure game program resource | -| ADVMAIN.COW | Adventure game program source | -| RAND.AS | Assembler Library File | -| COWBE.COM | | -| COWFE.COM | RomWBW specific (Memory Manage) version | -| COWLINK.COM | | -| DYNMSORT.COW | demonstrates a sort algorithm | -| DYNMSORT.SUB | Submit file to build DYNMSORT | -| HEXDUMP.COW | a simple hex dump utility, purely a Cowgol | -| HEXDUMP.SUB | Submit file to build HEXDUMP | -| HMERGES.C | C Library File | -| XRND.AS | Assembler Library File | -| - | - | - -NOTE : The above is incomplete - -## Microsoft Fortran 80 (Fortran) +| **File** | **Description** | +|----------------|--------------------------------------------| +| `$EXEC.COM` | HiTech C batch processor which launches the Cowgol toolchain executables | +| `ADVENT.COW` | Adventure game program source | +| `ADVENT.SUB` | SUBMIT file to build Adventure game | +| `ADVENT?.TXT` | Adventure game program resources | +| `ADVMAIN.COW` | Adventure game program source | +| `ADVTRAV.COW` | Adventure game component source | +| `ARGV.COH` | Cowgol include file providing command line argument processing | +| `C.LIB` | HI-TECH C runtime library | +| `CGEN.COM` | HiTech C compiler pass 2 | +| `COMMFILE.COH` | Include file providing file I/O | +| `COMMON.COH` | Include file providing common functions | +| `COWBE.COM` | Cowgol back end which builds the cowgol object files (optimized) | +| `COWFE.COM` | Cowgol front end which parses the source file (optimized) | +| `COWFIX.COM` | Interface to Z80AS -- performs code optimizations | +| `COWGOL.COH` | Include file providing standard Cowgol functions | +| `COWGOL.COM` | Interprets the command line and generates $EXEC run requests (a variant of HiTech C.COM) | +| `COWGOL.COO` | Cowgol object file with ??? | +| `COWGOL.LIB` | ??? | +| `COWGOLC.COH` | Cowgol include file providing ??? | +| `COWLINK.COM` | Cowgol linker which binds all the cowgol object files and outputs a Z80 assembler file (optimized) | +| `CPP.COM` | HiTech C pre-processor, modified to accept // style comments | +| `DYNMSORT.COW` | Sort algorithm sample program source | +| `DYNMSORT.SUB` | SUBMIT file to build DYNMSORT sample application | +| `FACT.COW` | Factorial computation sample program source | +| `FILE.COH` | Include file providing CP/M file processing support | +| `FILEIO.COH` | Include file providing CP/M file processing support | +| `HEXDUMP.COW` | Hex file dump sample source | +| `HEXDUMP.SUB` | SUBMIT file to build HEXDUMP sample program | +| `LIBBASIC.COH` | Include file providing ??? | +| `LIBBIOS.COH` | Include file providing ??? | +| `LIBCONIO.COH` | Include file providing console I/O | +| `LIBFP.COH` | Include file providing floating point support | +| `LIBR.COM` | HiTech object file librarian | +| `LIBSTR.COH` | Include file providing string functions | +| `LINK.COM` | HiTech linker which builds the final executable from object and library files | +| `MALLOC.COH` | Include file providing dynamic memory management functions | +| `MERGES.C` | Merge sort sample function C language source | +| `MISC.COH` | Include file providing miscellaneous functions | +| `MISC.COO` | Miscellaneous functions object file | +| `MISC.COW` | Miscellaneous functions source file | +| `OPTIM.COM` | HiTech C compiler optimizer | +| `P1.COM` | HiTech C compiler first pass | +| `RAND.AS` | Pseudo-random number generator source in assembly language | +| `RANFILE.COH` | Include file providing random file access functions | +| `RANFILE.COO` | Random file access functions object file | +| `RANFILE.COW` | Random file access functions source file | +| `README.TXT` | Cowgol disk image release notes | +| `SEQFILE.COH` | Include file providing sequential file access functions | +| `SEQFILE.COO` | Sequential file access functions object file | +| `SEQFILE.COW` | Sequential file access functions source file | +| `STDCOW.COH` | Include file providing standard library functions | +| `STRING.COH` | Include file providing string functions | +| `STRING.COO` | String functions object file | +| `STRING.COW` | String functions source file | +| `STRINGS.COH` | Include file implementing string functions | +| `TESTAS.COW` | Assembly language interface sample program source | +| `TESTAS.SUB` | SUBMIT file to build TESTAS sample program | +| `Z80AS.COM` | Z80 assembler which assembles the output of COWFIX and other Z80 source files (see ) | + +## Microsoft Fortran 80 | Floppy Disk Image: **fd_fortran.img** | Hard Disk Image: **hd_fortran.img** @@ -1114,12 +1156,12 @@ Zork 1 through 3, Planetfall and Hitchhiker's Guide to the Galaxy. Nemesis and Dungeon Master is a Rogue-like game released in 1981. It is playable on a text terminal using ASCII graphics to represent the dungeon. Only a few thousand copies of the game were ever made, making it very rare. See -[http://crpgaddict.blogspot.com/2019/03/game-322-nemesis-1981.html] + Colossal Cave Adventure is a CP/M port of the 1976 classic game originally written by Will Crowther for the PDP-10 mainframe. See -[https://en.wikipedia.org/wiki/Colossal_Cave_Adventure] and -[https://if50.substack.com/p/1976-adventure] + and + The following files are found in @@ -1136,31 +1178,195 @@ NOTE : The above is incomplete | Floppy Disk Image: **fd_hitechc.img** | Hard Disk Image: **hd_hitechc.img** -The HI-TECH C Compiler is a set of software which +The HI-TECH C Compiler is a set of software which translates programs written in the C language to executable machine code programs. Versions are available which compile programs for operation under the host operating system, or which produce programs for execution in embedded systems without an operating system. -This is the Mar 21, 2023 update 17 released by Tony Nicholson who currently -maintains HI-TECH C at [https://github.com/agn453/HI-TECH-Z80-C] +This is the Jun 2, 2025 update 19 released by Tony Nicholson who +currently maintains HI-TECH C at +. The manual is available in the Doc/Language directory, -HI-TECH Z80 C Compiler Manual.txt +HI-TECH Z80 C Compiler Manual.txt. A textual description of all error +and warning messages is found in the same directory, HI-TECH Z80 C +Compiler Messages.txt. A good blog post about the HI-TECH C Compiler is available at -[https://techtinkering.com/2008/10/22/installing-the-hi-tech-z80-c-compiler-for-cpm] +. + +User area 1 contains another complete copy of the HI-TECH C Compiler. +It is identical to the copy in user area 0 except for the following files +which were enhanced by Ladislau Szilagyi from his GitHub Repository at +. The files +take advantage of additional banked memory using the RomWBW HBIOS API. +As such, they require RomWBW to operate. They should be compatible with +all CP/M and compatible operations systems provided in RomWBW. + +The enhanced files are: + +- `CGEN.COM` +- `CPP.COM` +- `OPTIM.COM` +- `P1.COM` +- `ZAS.COM` + +A thread discussing this enhanced version of HI-TECH C is found at +. The following files are found in * /Source/Images/d_hitechc -| **File** | **Description** | -|----------|-----------------| -| -- | -- | +| **File** | **Description** | +|----------------|--------------------------------------------| +| `$EXEC.COM` | Compiler execution manager | +| `ASSERT.H` | Language include file | +| `C.COM` | Compiler invocation application (updated) | +| `C309.COM` | Compiler invocation application (original) | +| `CGEN.COM` | The code generator - produces assembler code | +| `CONIO.H` | Language include file (see manual) | +| `CPM.H` | Language include file (see manual) | +| `CPP.COM` | Pre-processor - handles macros and conditional compilation | +| `CREF.COM` | Produces cross-reference listings of C or assembler programs | +| `CRTCPM.OBJ` | Startup Object File (standard) | +| `CTYPE.H` | Language include file (see manual) | +| `DEBUG.COM` | C Debugger (Z80) | +| `DRTCPM.OBJ` | Startup Object File (???) | +| `EXEC.H` | Language include file (see manual) | +| `FLOAT.H` | Language include file (see manual) | +| `HITECH.H` | Language include file (see manual) | +| `LIBC.LIB` | Standard C Runtime Library | +| `LIBF.LIB` | Floating Point Library | +| `LIBOVR.LIB` | Overlay Library | +| `LIBR.COM` | Creates and maintains libraries of object modules | +| `LIMITS.H` | Language include file (see manual) | +| `LINQ.COM` | Link editor - links object files with libraries | +| `MATH.H` | Language include file (see manual) | +| `NRTCPM.OBJ` | Startup Object File (minimal getargs) | +| `OBJTOHEX.COM` | Converts the output of LINK into the appropriate executable file format (e.g., .EXE or .PRG or .HEX) | +| `OPTIM.COM` | Code improver - may optionally be omitted, reducing compilation time at a cost of larger, slower code produced | +| `OPTIONS` | Compiler usage help file | +| `OVERLAY.H` | Language include file | +| `P1.COM` | The syntax and semantic analysis pass - writes intermediate code for the code generator to read | +| `RRTCPM.OBJ` | Startup Object File (self relocating) | +| `SETJMP.H` | Language include file (see manual) | +| `SIGNAL.H` | Language include file (see manual) | +| `STAT.H` | Language include file (see manual) | +| `STDARG.H` | Language include file (see manual) | +| `STDDEF.H` | Language include file (see manual) | +| `STDINT.H` | Language include file (see manual) | +| `STDIO.H` | Language include file (see manual) | +| `STDLIB.H` | Language include file (see manual) | +| `STRING.H` | Language include file (see manual) | +| `SYMTOAS.COM` | Convert symbol file to assembler | +| `SYS.H` | Language include file (see manual) | +| `TIME.H` | Language include file (see manual) | +| `UNIXIO.H` | Language include file (see manual) | +| `ZAS.COM` | The assembler - in fact a general purpose macro assembler | + +## Infocom (Text Adventure Games) + +| Hard Disk Image: **hd_infocom.img** + +A collection of all Official releases of the interactive fiction games +produced by Infocom in the 1980's -NOTE : The above is incomplete +The following files are found in + +* /Source/Images/d_infocom + +| **File** | **Description** | +|--------------|----------------------------------------------------| +| amfv.z4 | A Mind Forever Voyaging (*) | +| arthur.z6 | Arthur - The Quest for Excalibur (*) | +| ballyhoo.z3 | Ballyhoo | +| beyond.z5 | Beyond Zork (*) | +| border.z5 | Border Zone (*) | +| bureau.z4 | Bureaucracy (*) | +| cutthr.z3 | Cutthroats | +| deadline.z3 | Deadline | +| enchant.z3 | Enchanter | +| h2g2.z3 | The Hitchhiker's Guide to the Galaxy | +| hollyw.z3 | Hollywood Hijinx | +| infidel.z3 | Infidel | +| journey.z6 | Journey (*) | +| leather.z3 | Leather Goddesses of Phobos | +| lurking.z3 | The Lurking Horror | +| moonmist.z3 | Moonmist | +| nordbert.z4 | Nord and Bert Couldn't Make Head or Tail of It (*) | +| planet.z3 | Planetfall | +| plunder.z3 | Plundered Hearts | +| readme.txt | Documentation about the Infocom games | +| seastalk.z3 | Seastalker | +| sherlock.z5 | Sherlock (*) | +| shogun.z6 | Shogun (*) | +| sorcerer.z3 | Sorcerer | +| spellb.z3 | Spellbreaker | +| starcros.z3 | Starcross | +| stationf.z3 | Stationfall | +| suspect.z3 | Suspect | +| suspend.z3 | Suspended | +| trinity.z4 | Trinity (*) | +| wishb.z3 | Wishbringer | +| witness.z3 | Witness | +| zork0.z6 | Zork Zero (*) | +| zork1.z3 | Zork I | +| zork2.z3 | Zork II | +| zork3.z3 | Zork III | +| zorknote.txt | Documentation about terminal config of COM files | + +The above games have been curated from here . +Full game documentation can be found here + +The game files are a virtual machine code commonly known as Z-Machine, they +are portable and will run on any machine that has a Z-Machine interpreter. + +* All the Z3 games come with the official CP/M interpreter (the `COM` file) + version C last updated by Inforcom on 5th Feb 1985. You can simply run the + game by running it from the `COM` program +* All latter games Z4, Z5,.. and above, (Marked as * in the listing above) + are more sophisticated and require a better interpreter. i.e. VEZZA. + +#### VEZZA (User Area 15) + +Vezza is a modern Infocom/Inform/Z-machine text adventure interpreter for 8 bit +z80 based computers. What makes it modern is that it is written in hand-crafted +z80 assembler for maximum speed, and can load not only the classics such as +Zork 1,2 and 3 but also the later games. + +It can run Z1 up to Z8 inform format interactive fiction game files. To run +a game with Vezza just type Vezza followed by the game you want to run. e.g. + +`VEZZA ZORK0.Z6` + +**Note:** One of the bigger constraints is available RAM. An OS such as ZPM +since it uses banked RAM does have a good amount of available RAM and was +used to test these games work. + +This tool is free but the developer accepts your support by letting +you pay what you think is fair for the tool. If you find this useful +consider donating at: + + + +You should (test and) choose one that works on you configuration, +and best to copy and rename it as vezza.com + +| **File** | **Description** | +|--------------|-------------------------------------------------------------------| +| vezza-B.com | 80x24, VT52 + Banked CP/M 3 | +| vezza-FG.com | 80x25, VT100/ANSI (16 color) + CP/M 3 | +| vezza-C2.com | 80x24, VT100 - CP/M 2.2 large memory, no timed input | +| vezza-CC.com | 80x24, VT100 (256 colour) - CP/M 2.2 large memory, no timed input | +| vezza-AV.com | 80x24, VT100 (16 colour) - CP/M 2.2 high RAM. | +| vezza-AX.com | 80x25, VT100/ANSI (16 colour) - CP/M 2.2 high RAM. | +| vezza-RW.com | 80x24, VT100 - CP/M 2.2 | + +The above is a subset of available builds. The full repository including +documentation is available at ## MSX ROMS @@ -1170,7 +1376,7 @@ NOTE : The above is incomplete The collection of MSX ROMs (2 disks) as provided by Les Bird. These ROMs are "run" by using the appropriate variant of Les' MSX8 ROM loader. You can download the -loader binaries from [https://github.com/lesbird/MSX8]. You will need +loader binaries from . You will need appropriate hardware to run the loader. Please review the file ROMLIST.TXT for information on the current @@ -1206,25 +1412,25 @@ The manual can be found in the Docs/Language directory, Turbo_Pascal_Version_3.0_Reference_Manual_1986.pdf A good overview of using Turbo Pascal in CP/M is available at -[https://techtinkering.com/2013/03/05/turbo-pascal-a-great-choice-for-programming-under-cpm] + The following files are found in * /Source/Images/d_tpascal -| **File** | **Description** | -|--------------|--------------------------------| -| ART.TXT | Part of the Example program | -| SA.PAS | Example Program | -| TINST.COM | Installation and Configuration | -| TINST.DTA | Part of TINST | -| TINST.MSG | Part of TINST | -| TURBO.COM | The main Turbo Pascal program | -| TURBO.MSG | Part of TURBO tascal | -| TURBO.OVR | Part of TURBO tascal | -| TURBOMSG.OVR | Part of TURBO tascal | +| **File** | **Description** | +|----------------|--------------------------------| +| `ART.TXT` | Part of the Example program | +| `SA.PAS` | Example Program | +| `TINST.COM` | Installation and Configuration | +| `TINST.DTA` | Part of TINST | +| `TINST.MSG` | Part of TINST | +| `TURBO.COM` | The main Turbo Pascal program | +| `TURBO.MSG` | Part of TURBO Pascal | +| `TURBO.OVR` | Part of TURBO Pascal | +| `TURBOMSG.OVR` | Part of TURBO Pascal | -## WordStar 4 +## WordStar 4 (Word processor) | Floppy Disk Image: **fd_ws4.img** | Hard Disk Image: **hd_ws4.img** @@ -1358,10 +1564,10 @@ The manual(s) are available in the Doc/Language directory, * Z80DIS User Manual (1985).pdf A run through of using the assembler is available at -[https://8bitlabs.ca/Posts/2023/05/20/learning-z80-asm] + And another shorter, but shows linker usage guide -[https://pollmyfinger.wordpress.com/2022/01/10/modular-retro-z80-assembly-language-programming-using-slr-systems-z80asm-and-srlnk/] + The following files are found in @@ -1369,53 +1575,53 @@ The following files are found in User Area 0 - Assembler -| **File** | **Description** | -|-------------|---------------------------------------------| -| 180FIG.COM | Configuration utility for SLR180.COM | -| 8080.MAC | ? | -| CONFIG.COM | Configuration utility for Z80ASM.COM | -| CONFIGP.COM | Configuration utility for Z80ASMP.COM | -| DUMP.* | Sample Program | -| MAKESYM.COM | Symbol File .SYM file generation | -| MAKESYM.DOC | Documentation for MAKESYM.COM | -| SLR180.COM | HD64180 (Z180) Relocating Macro Assembler | -| SLR180.DOC | Release Notes for SLR180.COM | -| SLRMAC.COM | 8080 Relocating Macro Assembler | -| SYNTAX.HLP | Documentation basic usage for all SLR Tools | -| SYNTAX.TXT | Documentation basic usage for all SLR Tools | -| TEST.* | Sample Program | -| Z80ASM.COM | Z80 Relocating Macro Assembler | -| Z80ASMP.COM | Z80 Relocating Macro Assembler (PLUS) | -| Z80ASM.DOC | Release Notes for Z80ASM.COM | +| **File** | **Description** | +|---------------|---------------------------------------------| +| `180FIG.COM` | Configuration utility for SLR180.COM | +| `8080.MAC` | ? | +| `CONFIG.COM` | Configuration utility for Z80ASM.COM | +| `CONFIGP.COM` | Configuration utility for Z80ASMP.COM | +| `DUMP.*` | Sample Program | +| `MAKESYM.COM` | Symbol File .SYM file generation | +| `MAKESYM.DOC` | Documentation for MAKESYM.COM | +| `SLR180.COM` | HD64180 (Z180) Relocating Macro Assembler | +| `SLR180.DOC` | Release Notes for SLR180.COM | +| `SLRMAC.COM` | 8080 Relocating Macro Assembler | +| `SYNTAX.HLP` | Documentation basic usage for all SLR Tools | +| `SYNTAX.TXT` | Documentation basic usage for all SLR Tools | +| `TEST.\*` | Sample Program | +| `Z80ASM.COM` | Z80 Relocating Macro Assembler | +| `Z80ASMP.COM` | Z80 Relocating Macro Assembler (PLUS) | +| `Z80ASM.DOC` | Release Notes for Z80ASM.COM | User Area 1 - Linker and Library Management -| **File** | **Description** | -|--------------|-----------------------------------------------| -| LNKFIG.COM | Configuration utility for SLRNK.COM | -| NZLNKFIX.ZEX | ? | -| SLRIB.COM | SuperLibrarian, library manager | -| SLRNK.COM | SuperLinker, the main linker tool | -| SLRNKP.COM | SuperLinker (PLUS) | -| SLRNK.DOC | Release Notes for SLRNK.COM | -| SLRNKFIX.ZEX | ? | -| SYNTAX.HLP | Documentation basic usage for all SLR Tools | -| SYNTAX.TXT | Documentation basic usage for all SLR Tools | -| SYSSLR.REL | SYSLIB (older) Library compatible with SLR | -| VSLR.REL | VLIB (older) Library compatible with SLR | -| Z3SLR.REL | Z3LIB (older) Library compatible with SLR | +| **File** | **Description** | +|----------------|-----------------------------------------------| +| `LNKFIG.COM` | Configuration utility for SLRNK.COM | +| `NZLNKFIX.ZEX` | ? | +| `SLRIB.COM` | SuperLibrarian, library manager | +| `SLRNK.COM` | SuperLinker, the main linker tool | +| `SLRNKP.COM` | SuperLinker (PLUS) | +| `SLRNK.DOC` | Release Notes for SLRNK.COM | +| `SLRNKFIX.ZEX` | ? | +| `SYNTAX.HLP` | Documentation basic usage for all SLR Tools | +| `SYNTAX.TXT` | Documentation basic usage for all SLR Tools | +| `SYSSLR.REL` | SYSLIB (older) Library compatible with SLR | +| `VSLR.REL` | VLIB (older) Library compatible with SLR | +| `Z3SLR.REL` | Z3LIB (older) Library compatible with SLR | User Area 2 - Disassembler -| **File** | **Description** | -|--------------|----------------------------------| -| README.22 | Documentation for Z80DIS | -| Z80DIS.000 | Overlay File for Z80DIS.COM | -| Z80DIS.001 | Overlay File for Z80DIS.COM | -| Z80DIS.002 | Overlay File for Z80DIS.COM | -| Z80DIS.COM | Z80DIS Disassembler main program | -| Z80DIS22.DOC | Main Documentation for Z80DIS | -| ZDINSTAL.COM | Instal and Config for Z80DIS.COM | -| ZDINSTAL.DTA | Overlay file for ZDINSTAL.COM | -| ZDINSTAL.MSG | Overlay file for ZDINSTAL.COM | +| **File** | **Description** | +|----------------|----------------------------------| +| `README.22` | Documentation for Z80DIS | +| `Z80DIS.000` | Overlay File for Z80DIS.COM | +| `Z80DIS.001` | Overlay File for Z80DIS.COM | +| `Z80DIS.002` | Overlay File for Z80DIS.COM | +| `Z80DIS.COM` | Z80DIS Disassembler main program | +| `Z80DIS22.DOC` | Main Documentation for Z80DIS | +| `ZDINSTAL.COM` | Instal and Config for Z80DIS.COM | +| `ZDINSTAL.DTA` | Overlay file for ZDINSTAL.COM | +| `ZDINSTAL.MSG` | Overlay file for ZDINSTAL.COM | diff --git a/Source/Doc/Hardware.md b/Source/Doc/Hardware.md index 520779dc..d67f9c3f 100644 --- a/Source/Doc/Hardware.md +++ b/Source/Doc/Hardware.md @@ -111,26 +111,26 @@ Others | **Description** | **Bus** | **ROM Image File** | **Baud Rate** | |-------------------------------------------------------------|----------|-----------------------------|--------------:| -| [Dyno Z180 SBC]^6^ | Dyno | DYNO_std.rom | 38400 | -| [EP Mini-ITX Z180]^11^ | UEXT | EPITX_std.rom | 115200 | -| [eZ80 for RCBus Module]^13^, 512K RAM/ROM | RCBus | RCEZ80_std.rom | 115200 | -| [Genesis Z180 System]^12^ | STD | GMZ180_std.rom | 115200 | -| [Heath H8 Z80 System]^10^ | H8 | HEATH_std.rom | 115200 | -| [NABU w/ RomWBW Option Board]^10^ | NABU | NABU_std.rom | 115200 | -| [S100 Computers Z180 SBC]^9^ | S100 | S100_std.rom | 57600 | -| [S100 Computers FPGA Z80 SBC]^9^ | S100 | FZ80_std.rom | 9600 | -| [UNA Hardware BIOS]^3^ | - | UNA_std.rom | - | -| [Z80-Retro SBC]^8^ | - | Z80RETRO_std.rom | 38400 | -| [Z180 Mark IV SBC]^3^ | ECB | MK4_std.rom | 38400 | - -| ^3^Designed by John Coffman -| ^6^Designed by Steve Garcia -| ^8^Designed by Peter Wilson -| ^9^Designed by John Monahan -| ^10^Designed by Les Bird -| ^11^Designed by Alan Cox -| ^12^Designed by Doug Jackson -| ^13^Designed by Dean Netherton +| [Dyno Z180 SBC]^2^ | Dyno | DYNO_std.rom | 38400 | +| [EP Mini-ITX Z180]^6^ | UEXT | EPITX_std.rom | 115200 | +| [eZ80 for RCBus Module]^8^, 512K RAM/ROM | RCBus | RCEZ80_std.rom | 115200 | +| [Genesis Z180 System]^7^ | STD | GMZ180_std.rom | 115200 | +| [Heath H8 Z80 System]^5^ | H8 | HEATH_std.rom | 115200 | +| [NABU w/ RomWBW Option Board]^5^ | NABU | NABU_std.rom | 115200 | +| [S100 Computers Z180 SBC]^4^ | S100 | S100_std.rom | 57600 | +| [S100 Computers FPGA Z80 SBC]^4^ | S100 | FZ80_std.rom | 9600 | +| [UNA Hardware BIOS]^1^ | - | UNA_std.rom | - | +| [Z80-Retro SBC]^3^ | - | Z80RETRO_std.rom | 38400 | +| [Z180 Mark IV SBC]^1^ | ECB | MK4_std.rom | 38400 | + +| ^1^Designed by John Coffman +| ^2^Designed by Steve Garcia +| ^3^Designed by Peter Wilson +| ^4^Designed by John Monahan +| ^5^Designed by Les Bird +| ^6^Designed by Alan Cox +| ^7^Designed by Doug Jackson +| ^8^Designed by Dean Netherton `\clearpage`{=latex} @@ -141,6 +141,11 @@ devices and peripherals that are on-board or frequently used with each platform. If the device or peripheral is not detected at boot, the ROM will simply bypass support appropriately. +Each ROM will support a single memory manager. This is determined +by the build configuration and is not dynamically selected. The use +of the term Memory Manager is generally synonymous with Memory +Management Unit (MMU). + In some cases, support for multiple hardware components with potentially conflicting resource usage are handled by a single ROM image. It is up to the user to ensure that no conflicting hardware is in use. @@ -2274,6 +2279,7 @@ the active platform and configuration. | VDU | MC6845 Family Video Display Controller (*) | | VGA | HD6445CP4-based Video Display Controller | | VRC | VGARC Video Display Controller | +| XOSERA | XOSERA FPGA-based Video Display Controller | Note: @@ -2312,6 +2318,7 @@ Note: | DSRTC | Maxim DS1302 Real-Time Clock w/ NVRAM | | EZ80RTC | eZ80 Real-Time Clock | | INTRTC | Interrupt-based Real Time Clock | +| PCRTC | MC146818/DS1285/DS12885 PC style | | PCF | PCF8584-based I2C Real-Time Clock | | RP5C01 | Ricoh RPC01A Real-Time Clock w/ NVRAM | | SIMRTC | SIMH Simulator Real-Time Clock | diff --git a/Source/Doc/Introduction.md b/Source/Doc/Introduction.md index 0aa09e08..f11143ea 100644 --- a/Source/Doc/Introduction.md +++ b/Source/Doc/Introduction.md @@ -1,410 +1,425 @@ -$define{doc_title}{Introduction}$ -$include{"Book.h"}$ - -# Overview - -RomWBW software provides a complete, commercial quality -implementation of CP/M (and workalike) operating systems and -applications for modern Z80/180/280 retro-computing hardware systems. - -A wide variety of platforms are supported including those -produced by these developer communities: - -* [RetroBrew Computers](https://www.retrobrewcomputers.org) - () -* [RC2014](https://rc2014.co.uk) (), \ - [RC2014-Z80](https://groups.google.com/g/rc2014-z80) - () -* [Retro Computing](https://groups.google.com/g/retro-comp) - () -* [Small Computer Central](https://smallcomputercentral.com/) - () - -A complete list of the currently supported platforms is found in -$doc_hardware$ . - -`\clearpage`{=latex} - -# Description - -## Primary Features - -By design, RomWBW isolates all of the hardware specific functions in -the ROM chip itself. The ROM provides a hardware abstraction layer -such that all of the operating systems and applications on a disk -will run on any RomWBW-based system. To put it simply, you can take -a disk (or CF/SD/USB Card) and move it between systems transparently. - -Supported hardware features of RomWBW include: - -* Z80 Family CPUs including Z80, Z180, and Z280 -* Banked memory services for several banking designs -* Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip, Iomega -* Serial drivers including UART (16550-like), ASCI, ACIA, SIO -* Video drivers including TMS9918, SY6545, MOS8563, HD6445 -* Keyboard (PS/2) drivers via VT8242 or PPI interfaces -* Real time clock drivers including DS1302, BQ4845 -* Support for CP/NET networking using Wiznet, MT011 or Serial -* Built-in VT-100 terminal emulation support - -A dynamic disk drive letter assignment mechanism allows mapping -operating system drive letters to any available disk media. -Additionally, mass storage devices (IDE Disk, CF Card, SD Card, etc.) -support the use of multiple slices (up to 256 per device). Each slice -contains a complete CP/M filesystem and can be mapped independently to -any drive letter. This overcomes the inherent size limitations in legacy -OSes and allows up to 2GB of addressable storage on a single device, -with up to 128MB accessible at any one time. - -## Included Software - -Multiple disk images are provided in the distribution. Most disk -images contain a complete, bootable, ready-to-run implementation of a -specific operating system. A "combo" disk image contains multiple -slices, each with a full operating system implementation. If you use -this disk image, you can easily pick whichever operating system you -want to boot without changing media. - -Some of the included software: - -* Operating Systems (CP/M 2.2, ZSDOS, NZ-COM, CP/M 3, ZPM3, Z3PLUS, QPM ) -* Support for other operating systems, p-System, FreeRTOS, and FUZIX. -* Programming Tools (Z80ASM, Turbo Pascal, Forth, Cowgol) -* C Compiler's including Aztec-C, and HI-TECH C -* Microsoft Basic Compiler, and Microsoft Fortran -* Some games such as Colossal Cave, Zork, etc -* Wordstar Word processing software - -Some of the provided software can be launched directly from the -ROM firmware itself: - -* System Monitor -* Operating Systems (CP/M 2.2, ZSDOS) -* ROM BASIC (Nascom BASIC and Tasty BASIC) -* ROM Forth - -A tool is provided that allows you to access a FAT-12/16/32 filesystem. -The FAT filesystem may be coresident on the same disk media as RomWBW -slices or on stand-alone media. This makes exchanging files with modern -OSes such as Windows, MacOS, and Linux very easy. - -`\clearpage`{=latex} - -## ROM Distribution - -The [RomWBW Repository](https://github.com/wwarthen/RomWBW) -() on GitHub is the official -distribution location for all project source and documentation. - -RomWBW is distributed as both source code and pre-built ROM and disk -images. - -The pre-built ROM images distributed with RomWBW are based on -the default system configurations as determined by the hardware -provider/designer. The pre-built ROM firmware images are generally -suitable for most users. - -The fully-built distribution releases are available on the -[RomWBW Releases Page](https://github.com/wwarthen/RomWBW/releases) -() of the repository. - -On this page, you will normally see a Development Snapshot as well as -recent stable releases. Unless you have a specific reason, I suggest you -stick to the most recent stable release. - -The asset named RomWBW-vX.X.X-Package.zip includes all pre-built ROM -and Disk images as well as full source code. The other assets contain -only source code and do not have the pre-built ROM or disk images. - -#### Distribution Directory Layout - -The RomWBW distribution is a compressed zip archive file organized in -a set of directories. Each of these directories has its own -ReadMe.txt file describing the contents in detail. In summary, these -directories are: - -| **Directory** | **Description** | -|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| **Binary** | The final output files of the build process are placed here. Most importantly, the ROM images with the file names ending in ".rom" and disk images ending in .img. | -| **Doc** | Contains various detailed documentation, both RomWBW specifically as well as the operating systems and applications. | -| **Source** | Contains the source code files used to build the software and ROM images. | -| **Tools** | Contains the programs that are used by the build process or that may be useful in setting up your system. | - -`\clearpage`{=latex} - -#### Building from Source - -It is also very easy to modify and build custom ROM -images that fully tailor the firmware to your specific preferences. -All tools required to build custom ROM firmware under Windows are -included -- no need to install assemblers, etc. The firmware can also -be built using Linux or MacOS after confirming a few standard tools -have been installed. - -## Installation & Operation - -In general, installation of RomWBW on your platform is very simple. You -just need to program your ROM with the correct ROM image from the RomWBW -distribution. Subsequently, you can write disk images on your disk -drives (IDE disk, CF Card, SD Card, etc.) which then provides even more -functionality. - -Complete instructions for installation and operation of RomWBW are found -in the $doc_user$. It is also a good idea to review the [Release -Notes](https://github.com/wwarthen/RomWBW/blob/master/RELEASE_NOTES.md) -for helpful release-specific information. - -## Documentation - -There are several documents that form the core of the RomWBW documentation: - -* $doc_user$ is the main user guide for RomWBW, it covers the major topics - of how to install, manage and use RomWBW, and includes additional guidance - to the use of some of the operating systems supported by RomWBW - -* $doc_hardware$ contains a description of all the hardware platforms, - and devices supported by RomWBW. - -* $doc_apps$ is a reference for the ROM-hosted and OS-hosted applications - created or customized to enhance the operation of RomWBW. - -* $doc_catalog$ is a reference for the contents of the disk images - provided with RomWBW, with a description of many of the files on each image - -* $doc_sys$ discusses much of the internal design and construction - of RomWBW. It includes a reference for the RomWBW HBIOS API - functions. - -Each of the operating systems and ROM applications included with RomWBW -are sophisticated tools in their own right. It is not reasonable to -fully document their usage. However, you will find complete manuals -in PDF format in the Doc directory of the distribution. The intention -of this documentation is to describe the operation of RomWBW and the ways in -which it enhances the operation of the included applications and -operating systems. - -Since RomWBW is purely a software product for many different platforms, -the documentation does **not** cover hardware construction, -configuration, or troubleshooting -- please see your hardware provider -for this information. - -# Support - -## Getting Assistance - -The best way to get assistance with RomWBW or any aspect of the -RetroBrew Computers projects is via one of the community forums: - -* [RetroBrew Computers Forum](https://www.retrobrewcomputers.org/forum/) -* [RC2014 Google Group](https://groups.google.com/forum/#!forum/rc2014-z80) -* [retro-comp Google Group](https://groups.google.com/forum/#!forum/retro-comp) - -Submission of issues and bugs are welcome at the -[RomWBW GitHub Repository](https://github.com/wwarthen/RomWBW). - -Also feel free to email $doc_author$ at [$doc_authmail$](mailto:$doc_authmail$). -I am happy to provide support adapting RomWBW to new or modified systems - -# Contributions - -All source code and distributions are maintained on GitHub. -Contributions of all kinds to RomWBW are very welcome. - -## Acknowledgments - -I want to acknowledge that a great deal of the code and inspiration -for RomWBW has been provided by or derived from the work of others -in the RetroBrew Computers Community. I sincerely appreciate all of -their contributions. The list below is probably missing many names -- -please let me know if I missed you! - -* Andrew Lynch started it all when he created the N8VEM Z80 SBC - which became the first platform RomWBW supported. Some of his - original code can still be found in RomWBW. - -* Dan Werner wrote much of the code from which RomWBW was originally - derived and he has always been a great source of knowledge and - advice. - -* Douglas Goodall contributed code, time, testing, and advice in "the - early days". He created an entire suite of application programs to - enhance the use of RomWBW. Unfortunately, they have become unusable - due to internal changes within RomWBW. As of RomWBW 2.6, these - applications are no longer provided. - -* Sergey Kiselev created several hardware platforms for RomWBW - including the very popular Zeta. - -* David Giles created support for the Z180 CSIO which is now included - SD Card driver. - -* Phil Summers contributed the Forth and BASIC adaptations in ROM, the - AY-3-8910 sound driver, DMA support, and a long list of general code - and documentation enhancements. - -* Ed Brindley contributed some of the code that supports the RCBus - platform. - -* Spencer Owen created the RC2014 series of hobbyist kit computers - which has exponentially increased RomWBW usage. Some of his kits - include RomWBW. - -* Stephen Cousins has likewise created a series of hobbyist kit - computers at Small Computer Central and is distributing RomWBW - with many of them. - -* Alan Cox has contributed some driver code and has provided a great - deal of advice. - -* The CP/NET client files were developed by Douglas Miller. - -* Phillip Stevens contributed support for FreeRTOS. - -* Curt Mayer contributed the original Linux / MacOS build process. - -* UNA BIOS and FDISK80 are the products of John Coffman. - -* FLASH4 is a product of Will Sowerbutts. - -* CLRDIR is a product of Max Scane. - -* Tasty Basic is a product of Dimitri Theulings. - -* Dean Netherton contributed eZ80 CPU support, the sound driver - interface, and the SN76489 sound driver. - -* The RomWBW Disk Catalog document was produced by Mykl Orders. - -* Rob Prouse has created many of the supplemental disk images - including Aztec C, HiTech C, SLR Z80ASM, Turbo Pascal, Microsoft - BASIC Compiler, Microsoft Fortran Compiler, and a Games - compendium. - -* Martin R has provided substantial help reviewing and improving the - User Guide and Applications documents. - -* Mark Pruden has made a wide variety of contributions including: - - significant content in the Disk Catalog and User Guide - - creation of the Introduction and Hardware documents - - Z3PLUS operating system disk image - - COPYSL utility - - SLABEL utility - - a feature for RomWBW configuration by NVRAM - - the /B bulk mode of disk assignment to the ASSIGN utility - -* Jacques Pelletier has contributed the DS1501 RTC driver code. - -* Jose Collado has contributed enhancements to the TMS driver - including compatibility with standard TMS register configuration. - -* Kevin Boone has contributed a generic HBIOS date/time utility (WDATE). - -* Matt Carroll has contributed a fix to XM.COM that corrects the - port specification when doing a send. - -* Dean Jenkins enhanced the build process to accommodate the - Raspberry Pi 4. - -* Tom Plano has contributed a new utility (HTALK) to allow talking - directly to HBIOS COM ports. - -* Lars Nelson has contributed several generic utilities such as - a universal (OS agnostic) UNARC application. - -* Dylan Hall added support for specifying a secondary console. - -* Bill Shen has contributed boot loaders for several of his - systems. - -* Laszlo Szolnoki has contributed an EF9345 video display - controller driver. - -* Ladislau Szilagyi has contributed an enhanced version of - CP/M Cowgol that leverages RomWBW memory banking. - -* Les Bird has contributed support for the NABU w/ Option Board - -`\clearpage`{=latex} - -## Related Projects - -Outside of the hardware platforms adapted to RomWBW, there are a variety -of projects that either target RomWBW specifically or provide -a RomWBW-specific variation. These efforts are greatly appreciated -and are listed below. Please contact the author if there are any other -such projects that are not listed. - -#### Z88DK - -Z88DK is a software powerful development kit for Z80 computers -supporting both C and assembly language. This kit now provides -specific library support for RomWBW HBIOS. The Z88DK project is -hosted at . - -#### Paleo Editor - -Steve Garcia has created a Windows-hosted IDE that is tailored to -development of RomWBW. The project can be found at -. - -#### Z80 fig-FORTH - -Dimitri Theulings' implementation of fig-FORTH for the Z80 has a -RomWBW-specific variant. The project is hosted at -. - -#### Assembly Language Programming for the RC2014 Zed - -Bruce Hall has written a very nice document that describes how to -develop assembly language applications on RomWBW. It begins with the -setup and configuration of a new RC2014 Zed system running RomWBW. -It describes not only generic CP/M application development, but also -RomWBW HBIOS programming and bare metal programming. The latest copy -of this document is hosted at -[http://w8bh.net/Assembly for RC2014Z.pdf](http://w8bh.net/Assembly%20for%20RC2014Z.pdf). - -# Licensing - -## License Terms - -RomWBW is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RomWBW is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with RomWBW. If not, see . - -Portions of RomWBW were created by, contributed by, or derived from -the work of others. It is believed that these works are being used -in accordance with the intentions and/or licensing of their creators. - -If anyone feels their work is being used outside of its intended -licensing, please notify: - -> $doc_author$ \ -> [$doc_authmail$](mailto:$doc_authmail$) - -RomWBW is an aggregate work. It is composed of many individual, -standalone programs that are distributed as a whole to function as -a cohesive system. Each program may have its own licensing which -may be different from other programs within the aggregate. - -In some cases, a single program (e.g., CP/M Operating System) is -composed of multiple components with different licenses. It is -believed that in all such cases the licenses are compatible with -GPL version 3. - -RomWBW encourages code contributions from others. Contributors -may assert their own copyright in their contributions by -annotating the contributed source code appropriately. Contributors -are further encouraged to submit their contributions via the RomWBW -source code control system to ensure their contributions are clearly -documented. - -All contributions to RomWBW are subject to this license. +$define{doc_title}{Introduction}$ +$include{"Book.h"}$ + +# Overview + +RomWBW software provides a complete, commercial quality +implementation of CP/M (and work-alike) operating systems and +applications for modern Z80/180/280 retro-computing hardware systems. + +A wide variety of platforms are supported including those +produced by these developer communities: + +* [RetroBrew Computers](https://www.retrobrewcomputers.org) + () +* [RC2014](https://rc2014.co.uk) (), \ + [RC2014-Z80](https://groups.google.com/g/rc2014-z80) + () +* [Retro Computing](https://groups.google.com/g/retro-comp) + () +* [Small Computer Central](https://smallcomputercentral.com/) + () + +A complete list of the currently supported platforms is found in +$doc_hardware$ . + +`\clearpage`{=latex} + +# Description + +## Primary Features + +By design, RomWBW isolates all of the hardware specific functions in +the ROM chip itself. The ROM provides a hardware abstraction layer +such that all of the operating systems and applications on a disk +will run on any RomWBW-based system. To put it simply, you can take +a disk (or CF/SD/USB Card) and move it between systems transparently. + +Supported hardware features of RomWBW include: + +* Z80 Family CPUs including Z80, Z180, and Z280 +* Banked memory services for several banking designs +* Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip, Iomega +* Serial drivers including UART (16550-like), ASCI, ACIA, SIO +* Video drivers including TMS9918, SY6545, MOS8563, HD6445, Xosera +* Keyboard (PS/2) drivers via VT8242 or PPI interfaces +* Real time clock drivers including DS1302, BQ4845 +* Support for CP/NET networking using Wiznet, MT011 or Serial +* Built-in VT-100 terminal emulation support + +A dynamic disk drive letter assignment mechanism allows mapping +operating system drive letters to any available disk media. +Additionally, mass storage devices (IDE Disk, CF Card, SD Card, etc.) +support the use of multiple slices (up to 256 per device). Each slice +contains a complete CP/M filesystem and can be mapped independently to +any drive letter. This overcomes the inherent size limitations in legacy +OSes and allows up to 2GB of addressable storage on a single device, +with up to 128MB accessible at any one time. + +## Included Software + +Multiple disk images are provided in the distribution. Most disk +images contain a complete, bootable, ready-to-run implementation of a +specific operating system. A "combo" disk image contains multiple +slices, each with a full operating system implementation. If you use +this disk image, you can easily pick whichever operating system you +want to boot without changing media. + +Some of the included software: + +* Operating Systems (CP/M 2.2, ZSDOS, NZ-COM, CP/M 3, ZPM3, Z3PLUS, QPM ) +* Support for other operating systems, p-System, FreeRTOS, and FUZIX. +* Programming Tools (Z80ASM, Turbo Pascal, Forth, Cowgol) +* C Compiler's including Aztec-C, and HI-TECH C +* Microsoft Basic Compiler, and Microsoft Fortran +* Some games such as Colossal Cave, Zork, etc +* Wordstar Word processing software + +Some of the provided software can be launched directly from the +ROM firmware itself: + +* System Monitor +* Operating Systems (CP/M 2.2, ZSDOS) +* ROM BASIC (Nascom BASIC and Tasty BASIC) +* ROM Forth + +A tool is provided that allows you to access a FAT-12/16/32 filesystem. +The FAT filesystem may be coresident on the same disk media as RomWBW +slices or on stand-alone media. This makes exchanging files with modern +OSes such as Windows, MacOS, and Linux very easy. + +`\clearpage`{=latex} + +## ROM Distribution + +The [RomWBW Repository](https://github.com/wwarthen/RomWBW) +() on GitHub is the official +distribution location for all project source and documentation. + +RomWBW is distributed as both source code and pre-built ROM and disk +images. + +The pre-built ROM images distributed with RomWBW are based on +the default system configurations as determined by the hardware +provider/designer. The pre-built ROM firmware images are generally +suitable for most users. + +The fully-built distribution releases are available on the +[RomWBW Releases Page](https://github.com/wwarthen/RomWBW/releases) +() of the repository. + +On this page, you will normally see a Development Snapshot as well as +recent stable releases. Unless you have a specific reason, I suggest you +stick to the most recent stable release. + +The asset named RomWBW-vX.X.X-Package.zip includes all pre-built ROM +and Disk images as well as full source code. The other assets contain +only source code and do not have the pre-built ROM or disk images. + +#### Distribution Directory Layout + +The RomWBW distribution is a compressed zip archive file organized in +a set of directories. Each of these directories has its own +ReadMe.txt file describing the contents in detail. In summary, these +directories are: + +| **Directory** | **Description** | +|--------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Binary** | The final output files of the build process are placed here. Most importantly, the ROM images with the file names ending in ".rom" and disk images ending in .img. | +| **Doc** | Contains various detailed documentation, both RomWBW specifically as well as the operating systems and applications. | +| **Source** | Contains the source code files used to build the software and ROM images. | +| **Tools** | Contains the programs that are used by the build process or that may be useful in setting up your system. | + +`\clearpage`{=latex} + +#### Building from Source + +It is also very easy to modify and build custom ROM +images that fully tailor the firmware to your specific preferences. +All tools required to build custom ROM firmware under Windows are +included -- no need to install assemblers, etc. The firmware can also +be built using Linux or MacOS after confirming a few standard tools +have been installed. + +## Installation & Operation + +In general, installation of RomWBW on your platform is very simple. You +just need to program your ROM with the correct ROM image from the RomWBW +distribution. Subsequently, you can write disk images on your disk +drives (IDE disk, CF Card, SD Card, etc.) which then provides even more +functionality. + +Complete instructions for installation and operation of RomWBW are found +in the $doc_user$. It is also a good idea to review the [Release +Notes](https://github.com/wwarthen/RomWBW/blob/master/RELEASE_NOTES.md) +for helpful release-specific information. + +## Documentation + +There are several documents that form the core of the RomWBW documentation: + +* $doc_user$ is the main user guide for RomWBW, it covers the major topics + of how to install, manage and use RomWBW, and includes additional guidance + to the use of some of the operating systems supported by RomWBW + +* $doc_hardware$ contains a description of all the hardware platforms, + and devices supported by RomWBW. + +* $doc_apps$ is a reference for the ROM-hosted and OS-hosted applications + created or customized to enhance the operation of RomWBW. + +* $doc_catalog$ is a reference for the contents of the disk images + provided with RomWBW, with a description of many of the files on each image + +* $doc_sys$ discusses much of the internal design and construction + of RomWBW. It includes a reference for the RomWBW HBIOS API + functions. + +An online HTML version of this documentation is hosted at +. + +Each of the operating systems and ROM applications included with RomWBW +are sophisticated tools in their own right. It is not reasonable to +fully document their usage. However, you will find complete manuals +in PDF format in the Doc directory of the distribution. The intention +of this documentation is to describe the operation of RomWBW and the ways in +which it enhances the operation of the included applications and +operating systems. + +Since RomWBW is purely a software product for many different platforms, +the documentation does **not** cover hardware construction, +configuration, or troubleshooting -- please see your hardware provider +for this information. + +# Support + +## Getting Assistance + +The best way to get assistance with RomWBW or any aspect of the +RetroBrew Computers projects is via one of the community forums: + +* [RetroBrew Computers Forum](https://www.retrobrewcomputers.org/forum/) +* [RC2014 Google Group](https://groups.google.com/forum/#!forum/rc2014-z80) +* [retro-comp Google Group](https://groups.google.com/forum/#!forum/retro-comp) + +Submission of issues and bugs are welcome at the +[RomWBW GitHub Repository](https://github.com/wwarthen/RomWBW). + +Also feel free to email $doc_author$ at [$doc_authmail$](mailto:$doc_authmail$). +I am happy to provide support adapting RomWBW to new or modified systems + +# Contributions + +All source code and distributions are maintained on GitHub. +Contributions of all kinds to RomWBW are very welcome. + +## Acknowledgments + +I want to acknowledge that a great deal of the code and inspiration +for RomWBW has been provided by or derived from the work of others +in the RetroBrew Computers Community. I sincerely appreciate all of +their contributions. The list below is probably missing many names -- +please let me know if I missed you! + +* Andrew Lynch started it all when he created the N8VEM Z80 SBC + which became the first platform RomWBW supported. Some of his + original code can still be found in RomWBW. + +* Dan Werner wrote much of the code from which RomWBW was originally + derived and he has always been a great source of knowledge and + advice. + +* Douglas Goodall contributed code, time, testing, and advice in "the + early days". He created an entire suite of application programs to + enhance the use of RomWBW. Unfortunately, they have become unusable + due to internal changes within RomWBW. As of RomWBW 2.6, these + applications are no longer provided. + +* Sergey Kiselev created several hardware platforms for RomWBW + including the very popular Zeta. + +* David Giles created support for the Z180 CSIO which is now included + SD Card driver. + +* Phil Summers contributed the Forth and BASIC adaptations in ROM, the + AY-3-8910 sound driver, DMA support, and a long list of general code + and documentation enhancements. + +* Ed Brindley contributed some of the code that supports the RCBus + platform. + +* Spencer Owen created the RC2014 series of hobbyist kit computers + which has exponentially increased RomWBW usage. Some of his kits + include RomWBW. + +* Stephen Cousins has likewise created a series of hobbyist kit + computers at Small Computer Central and is distributing RomWBW + with many of them. + +* Alan Cox has contributed some driver code and has provided a great + deal of advice. + +* The CP/NET client files were developed by Douglas Miller. + +* Phillip Stevens contributed support for FreeRTOS. + +* Curt Mayer contributed the original Linux / MacOS build process. + +* UNA BIOS and FDISK80 are the products of John Coffman. + +* FLASH4 is a product of Will Sowerbutts. + +* CLRDIR is a product of Max Scane. + +* Tasty Basic is a product of Dimitri Theulings. + +* Dean Netherton contributed multiple components: + - eZ80 CPU support + - Sound driver infrastructure + - SN76489 sound driver + - Native USB driver (keyboard, floppy, mass storage) + +* The RomWBW Disk Catalog document was produced by Mykl Orders. + +* Rob Prouse has created many of the supplemental disk images + including Aztec C, HiTech C, SLR Z80ASM, Turbo Pascal, Microsoft + BASIC Compiler, Microsoft Fortran Compiler, and a Games + compendium. + +* Martin R has provided substantial help reviewing and improving the + User Guide and Applications documents. + +* Mark Pruden has made a wide variety of contributions including: + - significant content in the Disk Catalog and User Guide + - creation of the Introduction and Hardware documents + - Z3PLUS operating system disk image + - Infocom text adventure game disk image + - COPYSL, and SLABEL utilities + - Display of bootable slices via "S" command during startup + - Optimisations of HBIOS and CBIOS to reduce overall code size + - a feature for RomWBW configuration by NVRAM + - the /B bulk mode of disk assignment to the ASSIGN utility + +* Jacques Pelletier has contributed the DS1501 RTC driver code. + +* Jose Collado has contributed enhancements to the TMS driver + including compatibility with standard TMS register configuration. + +* Kevin Boone has contributed a generic HBIOS date/time utility (WDATE). + +* Matt Carroll has contributed a fix to XM.COM that corrects the + port specification when doing a send. + +* Dean Jenkins enhanced the build process to accommodate the + Raspberry Pi 4. + +* Tom Plano has contributed a new utility (HTALK) to allow talking + directly to HBIOS COM ports. + +* Lars Nelson has contributed several generic utilities such as + a universal (OS agnostic) UNARC application. + +* Dylan Hall added support for specifying a secondary console. + +* Bill Shen has contributed boot loaders for several of his + systems. + +* Laszlo Szolnoki has contributed an EF9345 video display + controller driver. + +* Ladislau Szilagyi has contributed an enhanced version of + CP/M Cowgol that leverages RomWBW memory banking. + +* Les Bird has contributed support for the NABU w/ Option Board + +* Rob Gowin created an online documentation site via MkDocs, and + contributed a driver for the Xosera FPGA-based video + controller. + +* Jörg Linder has contributed disassembled and nicely commented + source for ZSDOS2 and the BPBIOS utilities. + +`\clearpage`{=latex} + +## Related Projects + +Outside of the hardware platforms adapted to RomWBW, there are a variety +of projects that either target RomWBW specifically or provide +a RomWBW-specific variation. These efforts are greatly appreciated +and are listed below. Please contact the author if there are any other +such projects that are not listed. + +#### Z88DK + +Z88DK is a software powerful development kit for Z80 computers +supporting both C and assembly language. This kit now provides +specific library support for RomWBW HBIOS. The Z88DK project is +hosted at . + +#### Paleo Editor + +Steve Garcia has created a Windows-hosted IDE that is tailored to +development of RomWBW. The project can be found at +. + +#### Z80 fig-FORTH + +Dimitri Theulings' implementation of fig-FORTH for the Z80 has a +RomWBW-specific variant. The project is hosted at +. + +#### Assembly Language Programming for the RC2014 Zed + +Bruce Hall has written a very nice document that describes how to +develop assembly language applications on RomWBW. It begins with the +setup and configuration of a new RC2014 Zed system running RomWBW. +It describes not only generic CP/M application development, but also +RomWBW HBIOS programming and bare metal programming. The latest copy +of this document is hosted at +[http://w8bh.net/Assembly for RC2014Z.pdf](http://w8bh.net/Assembly%20for%20RC2014Z.pdf). + +# Licensing + +## License Terms + +RomWBW is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +RomWBW is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with RomWBW. If not, see . + +Portions of RomWBW were created by, contributed by, or derived from +the work of others. It is believed that these works are being used +in accordance with the intentions and/or licensing of their creators. + +If anyone feels their work is being used outside of its intended +licensing, please notify: + +> $doc_author$ \ +> [$doc_authmail$](mailto:$doc_authmail$) + +RomWBW is an aggregate work. It is composed of many individual, +standalone programs that are distributed as a whole to function as +a cohesive system. Each program may have its own licensing which +may be different from other programs within the aggregate. + +In some cases, a single program (e.g., CP/M Operating System) is +composed of multiple components with different licenses. It is +believed that in all such cases the licenses are compatible with +GPL version 3. + +RomWBW encourages code contributions from others. Contributors +may assert their own copyright in their contributions by +annotating the contributed source code appropriately. Contributors +are further encouraged to submit their contributions via the RomWBW +source code control system to ensure their contributions are clearly +documented. + +All contributions to RomWBW are subject to this license. diff --git a/Source/Doc/Makefile b/Source/Doc/Makefile index 8abe81f6..53d46942 100644 --- a/Source/Doc/Makefile +++ b/Source/Doc/Makefile @@ -18,6 +18,10 @@ include $(TOOLS)/Makefile.inc all :: deploy +clean :: + rm -rf mkdocs + rm -rf site + %.tmp : %.md gpp -o $@ -U "$$" "$$" "{" "}{" "}$$" "{" "}" "@@@" "" -M "$$" "$$" "{" "}{" "}$$" "{" "}" $< @@ -31,11 +35,16 @@ all :: deploy pandoc $< -f markdown -t dokuwiki -s -o $@ --default-image-extension=pdf %.gfm : %.tmp - pandoc $< -f markdown -t gfm-yaml_metadata_block -s -o $@ --default-image-extension=pdf + pandoc $< -f markdown -t gfm-yaml_metadata_block -s -o $@ --default-image-extension=svg %.txt : %.tmp pandoc $< -f markdown -t plain -s -o $@ --default-image-extension=pdf +mkdocs/%.md : %.md + -mkdir -p mkdocs + gpp -DGFM -U "$$" "$$" "{" "}{" "}$$" "{" "}" "@@@" "" -M "$$" "$$" "{" "}{" "}$$" "{" "}" $< \ + | pandoc -f markdown -t gfm-yaml_metadata_block -s -o $@ --default-image-extension=svg + deploy : cp Introduction.gfm "../../ReadMe.md" cp Introduction.txt "../../ReadMe.txt" @@ -45,3 +54,10 @@ deploy : cp Applications.pdf "../../Doc/RomWBW Applications.pdf" cp Catalog.pdf "../../Doc/RomWBW Disk Catalog.pdf" cp Hardware.pdf "../../Doc/RomWBW Hardware.pdf" + +deploy_mkdocs : mkdocs/Introduction.md mkdocs/UserGuide.md mkdocs/SystemGuide.md mkdocs/Applications.md \ + mkdocs/Catalog.md mkdocs/Hardware.md + mkdir -p mkdocs/UserGuide/Graphics mkdocs/SystemGuide/Graphics + cp mkdocs/Introduction.md mkdocs/README.md + cp Graphics/*.svg mkdocs/UserGuide/Graphics + cp Graphics/*.svg mkdocs/SystemGuide/Graphics diff --git a/Source/Doc/ReadMe.md b/Source/Doc/ReadMe.md deleted file mode 100644 index 5a3ec790..00000000 --- a/Source/Doc/ReadMe.md +++ /dev/null @@ -1,296 +0,0 @@ -$define{doc_title}{ReadMe}$ -$include{"Basic.h"}$ - -# Overview - -RomWBW software provides a complete, commercial quality -implementation of CP/M (and workalike) operating systems and -applications for modern Z80/180/280 retro-computing hardware systems. - -A wide variety of platforms are supported including those -produced by these developer communities: - -* [RetroBrew Computers](https://www.retrobrewcomputers.org) - () -* [RC2014](https://rc2014.co.uk) (), \ - [RC2014-Z80](https://groups.google.com/g/rc2014-z80) - () -* [Retro Computing](https://groups.google.com/g/retro-comp) - () -* [Small Computer Central](https://smallcomputercentral.com/) - () - -A complete list of the currently supported platforms is found in the -[Installation] section. - -Supported hardware features of RomWBW include: - -* Z80 Family CPUs including Z80, Z180, and Z280 -* Banked memory services for several banking designs -* Disk drivers for RAM, ROM, Floppy, IDE ATA/ATAPI, CF, SD, USB, Zip, Iomega -* Serial drivers including UART (16550-like), ASCI, ACIA, SIO -* Video drivers including TMS9918, SY6545, MOS8563, HD6445 -* Keyboard (PS/2) drivers via VT8242 or PPI interfaces -* Real time clock drivers including DS1302, BQ4845 -* Support for CP/NET networking using Wiznet, MT011 or Serial -* Built-in VT-100 terminal emulation support - -RomWBW is distributed as both source code and pre-built ROM and disk -images. Some of the provided software can be launched directly from the -ROM firmware itself: - -* System Monitor -* Operating Systems (CP/M 2.2, ZSDOS) -* ROM BASIC (Nascom BASIC and Tasty BASIC) -* ROM Forth - -A dynamic disk drive letter assignment mechanism allows mapping -operating system drive letters to any available disk media. -Additionally, mass storage devices (IDE Disk, CF Card, SD Card, etc.) -support the use of multiple slices (up to 256 per device). Each slice -contains a complete CP/M filesystem and can be mapped independently to -any drive letter. This overcomes the inherent size limitations in legacy -OSes and allows up to 2GB of accessible storage on a single device, -with up to 128MB accessible at any one time. - -The pre-built ROM firmware images are generally suitable for most -users. However, it is also very easy to modify and build custom ROM -images that fully tailor the firmware to your specific preferences. -All tools required to build custom ROM firmware under Windows are -included -- no need to install assemblers, etc. The firmware can also -be built using Linux or MacOS after confirming a few standard tools -have been installed. - -Multiple disk images are provided in the distribution. Most disk -images contain a complete, bootable, ready-to-run implementation of a -specific operating system. A "combo" disk image contains multiple -slices, each with a full operating system implementation. If you use -this disk image, you can easily pick whichever operating system you -want to boot without changing media. - -By design, RomWBW isolates all of the hardware specific functions in -the ROM chip itself. The ROM provides a hardware abstraction layer -such that all of the operating systems and applications on a disk -will run on any RomWBW-based system. To put it simply, you can take -a disk (or CF/SD/USB Card) and move it between systems transparently. - -A tool is provided that allows you to access a FAT-12/16/32 filesystem. -The FAT filesystem may be coresident on the same disk media as RomWBW -slices or on stand-alone media. This makes exchanging files with modern -OSes such as Windows, MacOS, and Linux very easy. - -# Acquiring RomWBW - -The [RomWBW Repository](https://github.com/wwarthen/RomWBW) -() on GitHub is the official -distribution location for all project source and documentation. -The fully-built distribution releases are available on the -[RomWBW Releases Page](https://github.com/wwarthen/RomWBW/releases) -() of the repository. -On this page, you will normally see a Development Snapshot as well as -recent stable releases. Unless you have a specific reason, I suggest you -stick to the most recent stable release. - -The asset named RomWBW-vX.X.X-Package.zip includes all pre-built ROM -and Disk images as well as full source code. The other assets contain -only source code and do not have the pre-built ROM or disk images. - -All source code and distributions are maintained on GitHub. Code -contributions are very welcome. - -# Installation & Operation - -In general, installation of RomWBW on your platform is very simple. You -just need to program your ROM with the correct ROM image from the RomWBW -distribution. Subsequently, you can write disk images on your disk -drives (IDE disk, CF Card, SD Card, etc.) which then provides even more -functionality. - -Complete instructions for installation and operation of RomWBW are -found in the $doc_user$. It is also a good idea to review the -[Release Notes](https://github.com/wwarthen/RomWBW/blob/master/RELEASE_NOTES.md) -for helpful release-specific information. - -## Documentation - -Documentation for $doc_product$ includes: - -* $doc_intro$ -* $doc_user$ -* $doc_sys$ -* $doc_apps$ -* $doc_catalog$ -* $doc_hardware$ - -# Acknowledgments - -I want to acknowledge that a great deal of the code and inspiration -for RomWBW has been provided by or derived from the work of others -in the RetroBrew Computers Community. I sincerely appreciate all of -their contributions. The list below is probably missing many names -- -please let me know if I missed you! - -* Andrew Lynch started it all when he created the N8VEM Z80 SBC - which became the first platform RomWBW supported. Some of his - original code can still be found in RomWBW. - -* Dan Werner wrote much of the code from which RomWBW was originally - derived and he has always been a great source of knowledge and - advice. - -* Douglas Goodall contributed code, time, testing, and advice in "the - early days". He created an entire suite of application programs to - enhance the use of RomWBW. Unfortunately, they have become unusable - due to internal changes within RomWBW. As of RomWBW 2.6, these - applications are no longer provided. - -* Sergey Kiselev created several hardware platforms for RomWBW - including the very popular Zeta. - -* David Giles created support for the Z180 CSIO which is now included - SD Card driver. - -* Phil Summers contributed the Forth and BASIC adaptations in ROM, the - AY-3-8910 sound driver, DMA support, and a long list of general code - and documentation enhancements. - -* Ed Brindley contributed some of the code that supports the RCBus - platform. - -* Spencer Owen created the RC2014 series of hobbyist kit computers - which has exponentially increased RomWBW usage. Some of his kits - include RomWBW. - -* Stephen Cousins has likewise created a series of hobbyist kit - computers at Small Computer Central and is distributing RomWBW - with many of them. - -* Alan Cox has contributed some driver code and has provided a great - deal of advice. - -* The CP/NET client files were developed by Douglas Miller. - -* Phillip Stevens contributed support for FreeRTOS. - -* Curt Mayer contributed the original Linux / MacOS build process. - -* UNA BIOS and FDISK80 are the products of John Coffman. - -* FLASH4 is a product of Will Sowerbutts. - -* CLRDIR is a product of Max Scane. - -* Tasty Basic is a product of Dimitri Theulings. - -* Dean Netherton contributed eZ80 CPU support, the sound driver - interface, and the SN76489 sound driver. - -* The RomWBW Disk Catalog document was produced by Mykl Orders. - -* Rob Prouse has created many of the supplemental disk images - including Aztec C, HiTech C, SLR Z80ASM, Turbo Pascal, Microsoft - BASIC Compiler, Microsoft Fortran Compiler, and a Games - compendium. - -* Martin R has provided substantial help reviewing and improving the - User Guide and Applications documents. - -* Mark Pruden has made a wide variety of contributions including: - - significant content in the Disk Catalog and User Guide - - creation of the Introduction and Hardware documents - - Z3PLUS operating system disk image - - COPYSL and SLABEL utility - - a feature for RomWBW configuration by NVRAM - - the /B bulk mode of disk assignment to the ASSIGN utility - -* Jacques Pelletier has contributed the DS1501 RTC driver code. - -* Jose Collado has contributed enhancements to the TMS driver - including compatibility with standard TMS register configuration. - -* Kevin Boone has contributed a generic HBIOS date/time utility (WDATE). - -* Matt Carroll has contributed a fix to XM.COM that corrects the - port specification when doing a send. - -* Dean Jenkins enhanced the build process to accommodate the - Raspberry Pi 4. - -* Tom Plano has contributed a new utility (HTALK) to allow talking - directly to HBIOS COM ports. - -* Lars Nelson has contributed several generic utilities such as - a universal (OS agnostic) UNARC application. - -* Dylan Hall added support for specifying a secondary console. - -* Bill Shen has contributed boot loaders for several of his - systems. - -* Laszlo Szolnoki has contributed an EF9345 video display - controller driver. - -* Ladislau Szilagyi has contributed an enhanced version of - CP/M Cowgol that leverages RomWBW memory banking. - -* Les Bird has contributed support for the NABU w/ Option Board - -Contributions of all kinds to RomWBW are very welcome. - -# Licensing - -RomWBW is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RomWBW is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with RomWBW. If not, see . - -Portions of RomWBW were created by, contributed by, or derived from -the work of others. It is believed that these works are being used -in accordance with the intentions and/or licensing of their creators. - -If anyone feels their work is being used outside of its intended -licensing, please notify: - -> $doc_author$ \ -> [$doc_authmail$](mailto:$doc_authmail$) - -RomWBW is an aggregate work. It is composed of many individual, -standalone programs that are distributed as a whole to function as -a cohesive system. Each program may have its own licensing which -may be different from other programs within the aggregate. - -In some cases, a single program (e.g., CP/M Operating System) is -composed of multiple components with different licenses. It is -believed that in all such cases the licenses are compatible with -GPL version 3. - -RomWBW encourages code contributions from others. Contributors -may assert their own copyright in their contributions by -annotating the contributed source code appropriately. Contributors -are further encouraged to submit their contributions via the RomWBW -source code control system to ensure their contributions are clearly -documented. - -All contributions to RomWBW are subject to this license. - -# Getting Assistance - -The best way to get assistance with RomWBW or any aspect of the -RetroBrew Computers projects is via one of the community forums: - -* [RetroBrew Computers Forum](https://www.retrobrewcomputers.org/forum/) -* [RC2014 Google Group](https://groups.google.com/forum/#!forum/rc2014-z80) -* [retro-comp Google Group](https://groups.google.com/forum/#!forum/retro-comp) - -Submission of issues and bugs are welcome at the -[RomWBW GitHub Repository](https://github.com/wwarthen/RomWBW). - -Also feel free to email $doc_author$ at [$doc_authmail$](mailto:$doc_authmail$). diff --git a/Source/Doc/SystemGuide.md b/Source/Doc/SystemGuide.md index 40799d6e..872de57d 100644 --- a/Source/Doc/SystemGuide.md +++ b/Source/Doc/SystemGuide.md @@ -142,6 +142,14 @@ currently selected. The upper 32KB is "fixed". This area of memory is never swapped out and is used to contain software and operating systems that must remain in the Z80 address space. +Throughout this document, this mechanism of selecting banks of memory +into the lower 32K is referred to as memory management. Achieving +this functionality requires some type of hardware which is generally +referred to as the system's Memory Management Unit (MMU). RomWBW +supports a variety of MMUs -- but they all perform the same function +of swapping in/out banks of memory in the lower 32K of CPU address +space. + Figure 4.1 depicts the memory layout for a system running the CP/M operating system. Applications residing in TPA invoke BDOS services of CP/M, BDOS invokes the custom CBIOS APIs, and finally CBIOS @@ -290,6 +298,62 @@ Common Bank: It is a fixed mapping that is never changed in normal RomWBW operation hence the name "Common". +## Memory Managers + +The following hardware memory managers are supported by RomWBW. The +operation of these memory managers is not documented here -- please +refer to the documentation of your hardware provider for that. + +Z2: + +: Memory memory manager introduced by Sergey Kiselv in the Zeta 2 SBC. +Popular in many RCBus systems. + +Z180: + +: Memory manager built into the Z180 CPU + +Z280: + +: Memory manager built into the Z280 CPU + +ZRC: + +: Memory manager onboard the ZRC series of computers by Bill Shen. + +SBC: + +: Memory manager onboard the N8VEM SBC series of computers by +Andrew Lynch. + +MBC: + +: Memory manager onboard the Nhyodyne computer system by Andrew Lynch. + +N8: + +: Memory manager onboard the N8 SBC computer by Andrew Lynch. + +EZ512: + +: Memory manager onboard the EaZy80-512 Z80 CPU Module by Bill Shen. + +RPH: + +: Memory manager onboard the Rhyophyre computer system by Andrew Lynch. + +The memory manager used is determined by the configuration choices +that are part of a RomWBW build process. A given ROM can only have a +single memory manager -- it is not selected dynamically. + +The configuration variable `MEMMGR` sets the memory mannager used by +the ROM build. It must be set to one of the above memory manager +types. For example, for the Z2 memory manager, `MEMMGR` should be set +to `MM_Z2`. + +Note that the term memory manager (MM) and memory management unit (MMU) +are used interchangeably in the documentation and code. + # Disk Layout ## Floppy Disk Layout @@ -1024,6 +1088,7 @@ below enumerates their values. | DIODEV_SYQ | 0x0C | Syquest Sparq Disk | syq.asm | | DIODEV_CHUSB | 0x0D | CH375/376 USB Disk | ch.asm | | DIODEV_CHSD | 0x0E | CH375/376 SD Card | ch.asm | +| DIODEV_USB | 0x0F | CH376 Native USB Device | ch376.asm | A fixed set of media types are defined. The currently defined media types identifiers are listed below. Each driver will support one or @@ -1352,6 +1417,7 @@ unit. The table below enumerates these values. | RTCDEV_DS7 | 0x04 | Maxim DS1307 PCF I2C RTC w/ NVRAM | ds7rtc.asm | | RTCDEV_RP5 | 0x05 | Ricoh RPC01A Real-Time Clock w/ NVRAM | rp5rtc.asm | | RTCDEV_EZ80 | 0x07 | eZ80 on-chip RTC | ez80rtc.asm | +| RTCDEV_PC | 0x08 | MC146818/DS1285/DS12885 RTC w/ NVRAM | pcrtc.asm | The time functions to get and set the time (RTCGTM and RTCSTM) require a 6 byte date/time buffer in the following format. Each byte is BCD @@ -1700,14 +1766,17 @@ All video units are assigned a Device Type ID which indicates the specific hardware device driver that handles the unit. The table below enumerates their values. -| **Device Type** | **ID** | **Description** | **Driver** | -|-----------------|-------:|------------------------------------------|------------| -| VDADEV_VDU | 0x00 | MC6845 Family Video Display Controller | vdu.asm | -| VDADEV_CVDU | 0x01 | MC8563-based Video Display Controller | cvdu.asm | -| VDADEV_GDC | 0x02 | uPD7220 Video Display Controller | gdc.asm | -| VDADEV_TMS | 0x03 | TMS9918/38/58 Video Display Controller | tms.asm | -| VDADEV_VGA | 0x04 | HD6445CP4-based Video Display Controller | vga.asm | -| VDADEV_VRC | 0x05 | VGARC | vrc.asm | +| **Device Type** | **ID** | **Description** | **Driver** | +|-----------------|-------:|--------------------------------------------|------------| +| VDADEV_VDU | 0x00 | MC6845 Family Video Display Controller | vdu.asm | +| VDADEV_CVDU | 0x01 | MC8563-based Video Display Controller | cvdu.asm | +| VDADEV_GDC | 0x02 | uPD7220 Video Display Controller | gdc.asm | +| VDADEV_TMS | 0x03 | TMS9918/38/58 Video Display Controller | tms.asm | +| VDADEV_VGA | 0x04 | HD6445CP4-based Video Display Controller | vga.asm | +| VDADEV_VRC | 0x05 | VGARC | vrc.asm | +| VDADEV_EF | 0x06 | EF9345 | ef.asm | +| VDADEV_FV | 0x07 | S100 FPGA VGA | fv.asm | +| VDADEV_XOSERA | 0x08 | Xosera FPGA-based Video Display Controller | xosera.asm | Depending on the capabilities of the hardware, the use of colors and attributes may or may not be supported. If the hardware does not support @@ -2208,16 +2277,16 @@ using values that correspond to musical notes. The frequency will be applied when the next SNDPLAY function is invoked. The returned Status (A) is a standard HBIOS result code. -The Note (HL) values correspond to quarter notes. Increasing/decreasing -the value by 4 results in a full note increment/decrement. +The Note (HL) values correspond to eighth tones. Increasing/decreasing +the value by 8 results in a full tone increment/decrement. Increasing/decreasing the value by 48 results in a full octave increment/decrement. The value 0 corresponds to Bb/A# in octave 0. The sound chip resolution and its oscillator limit the range and accuracy of the notes played. The typical range of the AY-3-8910 is six octaves: Bb2/A#2 to A7, where each value is a unique tone. Values above -and below can still be played but each quarter tone step may not result -in a note change. +and below can still be played but each eighth tone step may not result +in a tone change. The following table shows the mapping of the Note (HL) value to the corresponding octave and note. @@ -2436,9 +2505,8 @@ If the Unit specified is not a hard disk the Media ID will be returned and the slice parameter ignored. If there is no media in device, or the slice number is invaid (Parameter Out Of Range) the function will return an error status. -**NOTE: -This function was placed in HBIOS to be shared between the diffeent CP/M -varients supported by RomWBW. It is not strictly a BIOS function, +**NOTE:** This function was placed in HBIOS to be shared between the different CP/M +variants supported by RomWBW. It is not strictly a BIOS function, and may be moved in future. `\clearpage`{=latex} diff --git a/Source/Doc/UserGuide.md b/Source/Doc/UserGuide.md index 485df903..09d8ff07 100644 --- a/Source/Doc/UserGuide.md +++ b/Source/Doc/UserGuide.md @@ -340,14 +340,16 @@ enter the command followed by ***\***. For example, typing `H` will display a short command summary: ``` -Boot [H=Help]: h +Boot [H=Help]: H L - List ROM Applications D - Device Inventory + S - Slice Inventory R - Reboot System W - RomWBW Configure I [] - Set Console Interface/Baud Rate V [] - View/Set HBIOS Diagnostic Verbosity + N - Network Boot [.] - Boot Disk Unit/Slice ``` @@ -366,7 +368,6 @@ ROM Applications: B: BASIC T: Tasty BASIC P: Play a Game - N: Network Boot X: XModem Flash Updater U: User App ``` @@ -410,7 +411,6 @@ prompt: | BASIC | Microsoft ROM BASIC | | Tasty BASIC | Dimitri Theuling's Tiny BASIC implementation | | Play | A simple video game (requires ANSI terminal emulation) | -| Network Boot | Boot system via Wiznet MT011 device | | Flash Update | Upload and flash a new ROMWBW image using xmodem | | User App | User written application placeholder | @@ -992,10 +992,10 @@ whether you boot your OS from ROM or from the disk media itself. ## Drive Letter Assignment -In legacy CP/M operating systems only 16 drive letters (A:-P:) available - to be assigned to disks Drive letters were generally mapped to disk +In CP/M operating systems only 16 drive letters (A:-P:) available +to be assigned to disks Drive letters were generally mapped to disk drives in a completely fixed way. For example, drive A: would **always** - refer to the first floppy disk drive. +refer to the first floppy disk drive. RomWBW implements a much more flexible drive letter assignment mechanism so that any drive letter can dynamically be assigned to any disk device, @@ -1188,8 +1188,8 @@ media, you can use the CP/M 2.2 `STAT` command to display information including the number of "32 Byte Directory Entries" for a drive letter on the corresponding hard disk. -- If it indicates 512, your disk layout is legacy (hd512). -- If it indicates 1024, your disk layout is modern (hd1k). +- If it indicates 512, your disk layout is Classic (hd512). +- If it indicates 1024, your disk layout is Modern (hd1k). Here is an example of checking the disk layout. @@ -1335,14 +1335,14 @@ system. Two hard disk layout schemes exist: * Modern (hd1k) -* Legacy (hd512) +* Classic (hd512) You **cannot** mix disk layouts on a single disk device, however It is perfectly fine for one system to have multiple hard disks with different layouts -- each physical disk device is handled separately. -If you are setting up a new disk, the modern (hd1k) layout is +If you are setting up a new disk, the Modern (hd1k) layout is recommended for the following reasons: * Larger number of directory entries per filesystem @@ -1350,8 +1350,8 @@ recommended for the following reasons: * Reduces chances of data corruption * Each slice occupies exactly 8MB (an exact power of 2) in size -Both the legacy and modern disk layouts continue to be fully supported -by RomWBW. There are no plans to deprecate the legacy layout. +Both the classic and modern disk layouts continue to be fully supported +by RomWBW. There are no plans to deprecate the classic layout. #### Modern Layout @@ -1368,14 +1368,14 @@ RomWBW does not support extended partitions -- only a single primary partition can be used. The existence of a partition table entry for RomWBW on -a hard disk makes it behave in the modern mode. Removing the RomWBW -partition entry from a modern hard disk layout +a hard disk makes it behaves in the modern disk layout mode. +Removing the RomWBW partition entry from a modern hard disk layout will cause the existing data to be unavailable and/or corrupted The CP/M filesystem in the slices of the modern disk layout contain 1024 directory entries. -#### Legacy Layout +#### Classic Layout Originally, RomWBW always used the very start of the hard disk media for the location of the slices. In this layout, slice 0 referred to @@ -1384,15 +1384,16 @@ chunk of ~8MB on the disk, and so on. The number of slices is limited to the size of the disk media -- if you attempted to read/write to a slice that would exceed the disk size, you would see I/O errors. -The legacy format takes steps to allow a partition table to still be +The classic disk layout takes steps to allow a partition table to still be used for other types of filesystems such as DOS/FAT. It just does not use a partition table entry to determine the start of the RomWBW slices. -The lack of a RomWBW partition table entry will cause legacy behaviour. -Adding a partition table entry on an existing legacy RomWBW hard disk +The lack of a RomWBW partition table entry will cause the classic disk +layout to be used. +Adding a partition table entry on an existing classic RomWBW hard disk will cause the existing data to be unavailable and/or corrupted. -The CP/M filesystem in the slices of the legacy disk layout +The CP/M filesystem in the slices of the classic disk layout contain 512 directory entries. ### Hard Disk Slices @@ -1466,9 +1467,9 @@ system. The exact number of CP/M filesystem slices that will fit on your specific physical hard disk can be determined as follows: -- For modern (hd1k) disk layouts, it is 1024KB + (slices * 8192KB). +- For Modern (hd1k) disk layouts, it is 1024KB + (slices * 8192KB). Or equivalent to say 1MB + (slices * 8MB). -- For legacy (hd512) disk layouts, it is slices * 8,320KB. +- For Classic (hd512) disk layouts, it is slices * 8,320KB. **WARNING**: In this document KB means 1024 bytes and MB means 1048576 bytes (frequently expressed as KiB and MiB in modern terminology). @@ -1611,7 +1612,7 @@ This does not mean to imply it is the only possible way. First you need to understand -* The disk layout approach (either hd1k or the legacy hd512). +* The disk layout approach (either the Modern hd1k or the Classic hd512). See [Hard Disk Layouts] section if you are not sure. hd1k should be the preferred layout. * The number of 8MB slices that you want to allocate, preferred is 64 slices. @@ -1640,7 +1641,7 @@ The disk unit number was assigned at boot See [Device Unit Assignments] Refer to $doc_apps$ for more information on use of the `FDISK80` utility. -If you want to use the legacy hd512 layout skip down to the [Legacy (hd512)] section +If you want to use the Classic (hd512) layout skip down to the [Classic (hd512)] section #### Modern (hd1k) @@ -1702,14 +1703,14 @@ At this point, it is best to restart your system to make sure that the operating system is aware of the partition table updates. Start CP/M 2.2 or Z-System from ROM again. -#### Legacy (hd512) +#### Classic (hd512) At this point, use the `I` command to initialize (reset) the partition table to an empty state. To use the hd512 layout, use `W` to write the empty table to the disk and exit. Remember that the lack of a partition for RomWBW implies the -legacy (hd512) layout. +Classic (hd512) layout. At this point, it is best to restart your system to make sure that the operating system is aware of the partition table updates. Start @@ -1806,6 +1807,7 @@ The following table shows the disk images available. | xxx_fortran.img | Microsoft Fortran-80 Compiler | No | | xxx_games.img | Games Disk for CP/M | No | | xxx_hitechc.img | HI-TECH Z80 CP/M C compiler | No | +| xxx_infocom.img | Infocom Games Disk | No | | xxx_msxroms1.img | MSX ROMs Disk 1 | No | | xxx_msxroms2.img | MSX ROMs Disk 2 | No | | xxx_nzcom.img | NZCOM ZCPR 3.4 Operating System | Yes | @@ -1820,8 +1822,8 @@ You will find 3 sets of these .img files in the distribution. The "xxx" portion of the filename will be: * "fd_" for a floppy image. -* "hd1k_" for a modern layout hard disk image. -* "hd512_" for a legacy layout hard disk image. +* "hd1k_" for a Modern layout hard disk image. +* "hd512_" for a Classic layout hard disk image. In the case of xxx_dos65.img, only an hd512 variant is provided. This is a constraint of the DOS65 distribution. @@ -1895,7 +1897,7 @@ These partition sizes and locations were chosen to: The standard partition table table entries are: +---------------------------------+-------------------------------+-------------------------------+ -| | **--- Modern (hd1k) ---** | **--- Legacy (hd512) ---** | +| | **--- Modern (hd1k) ---** | **--- Classic (hd512) ---** | | +---------------+---------------+---------------+---------------+ | | Byte(s) | Sector(s) | Byte(s) | Sector(s) | +=================================+==============:+==============:+==============:+==============:+ @@ -1998,7 +2000,52 @@ that there are more disk (slice) images than the 6 that are included in the Combo Disk Images. These supplemental disk images are identified by looking for the files that start with hd1k_ or hd512_. -#### Adding Slices to Combo Image +There are two approaches you can use to create custom hard disk +images with multiple slices. + +- You can add/modify a configuration file and run the RomWBW + build process. This requires running the RomWBW build process, but + will cause your custom hard disk images to be created with every + build. + +- You can manually combine the individual images using `COPY` (Windows) + or `cat` (Linux/MacOS). This does not require running the RomWBW + build process, but will require manually recreating your custom + hard disk images when you upgrade to new releases of RomWBW. + +The following sections provide more detail on each approach. + +#### Building Custom Hard Disk Images + +The RomWBW build process builds the disk images defined in the +`Source/Images` directory. The resultant images are placed in the `Binary` +directory and are ready to copy to your media. + +These aggregate disk images are defined using .def files. You will see there +is a combo.def file in the Images directory that defines the slices for the +Combo disk image. You can create your own .def files as desired to +automatically create custom aggregate disk images. When the RomWBW +build process is run, it will automatically look for all .def files +in the `Source/Images` directory and create aggregate disk images for +each using the same base name as the .def file. + +There is an example of this in the `Images` directory called +`all.def.example`. You can remove the ".example" suffix so that the +file is called `all.def`. Now, if you run the RomWBW build process, it +will automatically generate `hd512_all.img` and `hd1k_all.img` files in +the `/Binary` directory. This example creates an aggregate disk image +with all of the possible slices. + +You could also modify the contents of the Combo disk image by simply +modifying the `combo.def` configuration file. However, it is recommended +that you leave the Combo image alone and simply define your own. + +NOTE: All of the `hd1k_xxx.img` aggregate disk image files created in +this way (including the Combo disk image) will already be prefixed with +`hd1k_prefix.dat`, so you do not need to add the prefix file. They are +ready to write to your media. + +#### Combining Hard Disk Images Manually You can add slices to the Combo Disk Images simply by tacking slices onto the end. For example, if you want to add a slice @@ -2017,7 +2064,7 @@ Linus/MaxOS: Note that you **must** be sure to use either the hd1k_ or hd512_ prefixed files together. You cannot mix them. -#### Creating a new Custom Image +#### Creating a new Custom Image Manually If you want to create a completely custom hard disk image that is not based on the existing combo image, you can generate a disk image entirely @@ -3163,7 +3210,7 @@ floppy disk and hard disk images. | TUNE | Play .PT2, .PT3, .MYM audio files. | | INTTEST | Test interrupt vector hooking. | -# Real Time Clock +# Real Time Clock & Date/Time Stamping RomWBW supports a variety of real time clock hardware. If your system has this hardware, then it will be able to maintain the diff --git a/Source/Doc/mkdocs.yml b/Source/Doc/mkdocs.yml new file mode 100644 index 00000000..c6d32454 --- /dev/null +++ b/Source/Doc/mkdocs.yml @@ -0,0 +1,16 @@ +site_name: RomWBW Documentation V3.6 +repo_url: https://github.com/wwarthen/RomWBW +edit_uri: "" +docs_dir: mkdocs +nav: + - Introduction: Introduction.md + - User Guide: UserGuide.md + - System Guide: SystemGuide.md + - Applications: Applications.md + - Catalog: Catalog.md + - Hardware: Hardware.md +theme: + name: mkdocs + color_mode: auto + user_color_mode_toggle: true + navigation_depth: 3 diff --git a/Source/Fonts/Build.cmd b/Source/Fonts/Build.cmd index 9032d1bb..6f379618 100644 --- a/Source/Fonts/Build.cmd +++ b/Source/Fonts/Build.cmd @@ -8,19 +8,14 @@ set PATH=%TOOLS%\lzsa;%TOOLS%\fonttool;%PATH% echo. echo Preparing compressed font files... -lzsa -f2 -r font8x8u.bin font8x8c.bin || exit /b -lzsa -f2 -r font8x11u.bin font8x11c.bin || exit /b -lzsa -f2 -r font8x16u.bin font8x16c.bin || exit /b -lzsa -f2 -r fontcgau.bin fontcgac.bin || exit /b -lzsa -f2 -r fontvgarcu.bin fontvgarcc.bin || exit /b +for %%f in (font6x8 font8x8 font8x11 font8x16) do call :genfont %%f -fonttool font8x8u.bin > font8x8u.asm || exit /b -fonttool font8x11u.bin > font8x11u.asm || exit /b -fonttool font8x16u.bin > font8x16u.asm || exit /b -fonttool font8x8c.bin > font8x8c.asm || exit /b -fonttool font8x11c.bin > font8x11c.asm || exit /b -fonttool font8x16c.bin > font8x16c.asm || exit /b -fonttool fontcgau.bin > fontcgau.asm || exit /b -fonttool fontcgac.bin > fontcgac.asm || exit /b -fonttool fontvgarcu.bin > fontvgarcu.asm || exit /b -fonttool fontvgarcc.bin > fontvgarcc.asm || exit /b +goto :eof + +:genfont +echo Processing font %1... +lzsa -f2 -r %1u.bin %1c.bin || exit /b +fonttool %1u.bin >%1u.asm || exit /b +fonttool %1c.bin >%1c.asm || exit /b + +goto :eof diff --git a/Source/Fonts/Makefile b/Source/Fonts/Makefile index 75b4e705..c1f3d95a 100644 --- a/Source/Fonts/Makefile +++ b/Source/Fonts/Makefile @@ -1,8 +1,8 @@ OBJECTS = \ - font8x8u.asm font8x11u.asm font8x16u.asm fontcgau.asm fontvgarcu.asm \ - font8x8c.asm font8x11c.asm font8x16c.asm fontcgac.asm fontvgarcc.asm + font6x8u.asm font8x8u.asm font8x11u.asm font8x16u.asm \ + font6x8c.asm font8x8c.asm font8x11c.asm font8x16c.asm -OTHERS = font8x8c.bin font8x11c.bin font8x16c.bin fontcgac.bin fontvgarcc.bin +OTHERS = font6x8c.bin font8x8c.bin font8x11c.bin font8x16c.bin TOOLS = ../../Tools @@ -14,6 +14,9 @@ include $(TOOLS)/Makefile.inc %.rel: %.asm %.bin: %.asm +font6x8c.bin: font6x8u.bin + $(BINDIR)/lzsa -f2 -r $< $@ + font8x8c.bin: font8x8u.bin $(BINDIR)/lzsa -f2 -r $< $@ @@ -23,11 +26,5 @@ font8x11c.bin: font8x11u.bin font8x16c.bin: font8x16u.bin $(BINDIR)/lzsa -f2 -r $< $@ -fontcgac.bin: fontcgau.bin - $(BINDIR)/lzsa -f2 -r $< $@ - -fontvgarcc.bin: fontvgarcu.bin - $(BINDIR)/lzsa -f2 -r $< $@ - %.asm: %.bin $(BINDIR)/bin2asm $< > $@ diff --git a/Source/Fonts/font6x8.png b/Source/Fonts/font6x8.png new file mode 100644 index 00000000..2c1c3208 Binary files /dev/null and b/Source/Fonts/font6x8.png differ diff --git a/Source/Fonts/font6x8u.bin b/Source/Fonts/font6x8u.bin new file mode 100644 index 00000000..ea0579d0 Binary files /dev/null and b/Source/Fonts/font6x8u.bin differ diff --git a/Source/Fonts/font8x16.png b/Source/Fonts/font8x16.png index 36131b53..ceb5bcd3 100644 Binary files a/Source/Fonts/font8x16.png and b/Source/Fonts/font8x16.png differ diff --git a/Source/Fonts/font8x16u.bin b/Source/Fonts/font8x16u.bin index c7ed1f51..1e360b26 100644 Binary files a/Source/Fonts/font8x16u.bin and b/Source/Fonts/font8x16u.bin differ diff --git a/Source/Fonts/font8x8.png b/Source/Fonts/font8x8.png index 7ddd1189..df1ab917 100644 Binary files a/Source/Fonts/font8x8.png and b/Source/Fonts/font8x8.png differ diff --git a/Source/Fonts/font8x8u.bin b/Source/Fonts/font8x8u.bin index 17f16d25..0abea4ef 100644 Binary files a/Source/Fonts/font8x8u.bin and b/Source/Fonts/font8x8u.bin differ diff --git a/Source/Fonts/fontcga.png b/Source/Fonts/fontcga.png deleted file mode 100644 index 3addedd6..00000000 Binary files a/Source/Fonts/fontcga.png and /dev/null differ diff --git a/Source/Fonts/fontcgau.bin b/Source/Fonts/fontcgau.bin deleted file mode 100644 index 8f20e538..00000000 Binary files a/Source/Fonts/fontcgau.bin and /dev/null differ diff --git a/Source/Fonts/fonts.txt b/Source/Fonts/fonts.txt index 4075bd73..8f4d8feb 100644 --- a/Source/Fonts/fonts.txt +++ b/Source/Fonts/fonts.txt @@ -1,12 +1,5 @@ Font files for ROMWBW. -8x8: 8x8 cell, mostly IBM CGA, first 16 differ, thin font -8x11: 8x11 cell, possibly VT-100? -8x16: 8x16 cell, IBM MDA -CGA: 8x16 cell, IBM CGA, normal (thick) CGA font, rows 8-15 are unused padding - -There are multiple fonts associated with ROMWBW supported hardware: - Board Driver Chip -------- -------- -------- ECB-SCG tms.asm 9918 @@ -15,23 +8,36 @@ There are multiple fonts associated with ROMWBW supported hardware: ECB-VGA3 vga.asm 6445 MBC-VDC cvdu.asm 8568 MBC-VDP tms.asm 9938/9958 - -Name Font Storage Size Board & Display Mode --------------------------------------------------------------------------------------------- -font8x8u.bin 6x8 8x8 2048 ECB-SCG, ECB-VGA3 (80x60), MBC-VDP -font8x11u.bin 8x11 8x11 2816 ECB-VGA3 (80x43) -font8x16u.bin 8x14 8x16 4096 ECB-CVDU (80x25), ECB-VGA3 (80x24, 80x25, 80x30), MBC-VDC -fontcgau.bin 8x8 8x16 4096 ECB-CVDU (80x25), MBC-VDC + RCBUS-VRC vrc.asm PLD + RCBUS-TMS tms.asm 99x8 + +Name Glyph Cell Size Comp Board & Display Mode +------------------------------------------------------------------------------------------------ +font6x8 6x8 8x8 2048 1094 ECB-SCG, MBC-VDP +font8x8 6x8 8x8 2048 1259 ECB-CVDU (CGA), MBC-VDC (CGA), ECB-VGA3 (80x60) +font8x11 8x11 8x11 2816 1252 ECB-VGA3 (80x43) +font8x16 8x14 8x16 4096 1466 ECB-CVDU (EGA), MBC-VDC (EGA), ECB-VGA3 (80x24, 80x25, 80x30) + ----- ----- + 11008 5071 Notes: -- The CGA font is roughly equivalent to the 8x8 font, but padded out to 8x16. Scan lines - 8-15 are unused. The CVDU driver (8563 chip) always uses fonts defined in an 8x16 cell. - When the CVDU is configured for use with a CGA monitor, an 8x8 character cell is used, - but the font definition must still be 8x16. The CGA font is used for this. +- Compression of the 6x8 font is disabled because the TMS driver must + reload the font when CP/M is warm booted. There is no memory area + where the decompression can safely be done at this point. + +- The 856x GDPs always use 16 bytes per font character. The CVDU + driver inserts dummy bytes as needed to utilize the 8x8 font when + selected. + +- The 8x11 font is not typically used and only supported by one + board. It is probably not worth the space of storing it and will + probably be eliminated in the future. + +- All fonts are in code page 437 except 8x11. For inclusion in HBIOS the .bin format files must be converted to assembler .asm format. -This is acheived using the fonttool utility and is completed automatically as part of the build process. +This is achieved using the fonttool utility and is completed automatically as part of the build process. i.e. fonts files are converted to .asm format and then copied to the HBIOS directory. To replace a font, simply copy it to the Fonts directory using the same naming convention above, @@ -61,7 +67,3 @@ Implementation example (older version): https://cpcrulez.fr/applications_tools_cruncher_LZSA2_Z80.htm x86 lzsa compressor application: http://www.pouet.net/prod.php?which=81573 - - - - diff --git a/Source/Fonts/fontvgarc.png b/Source/Fonts/fontvgarc.png deleted file mode 100644 index 5b9ad747..00000000 Binary files a/Source/Fonts/fontvgarc.png and /dev/null differ diff --git a/Source/Fonts/fontvgarcu.bin b/Source/Fonts/fontvgarcu.bin deleted file mode 100644 index 91b53d17..00000000 Binary files a/Source/Fonts/fontvgarcu.bin and /dev/null differ diff --git a/Source/HBIOS/Build.cmd b/Source/HBIOS/Build.cmd index 505aa599..9eafe11b 100644 --- a/Source/HBIOS/Build.cmd +++ b/Source/HBIOS/Build.cmd @@ -17,8 +17,8 @@ set CPMDIR80=%TOOLS%/cpm/ :: :: This PowerShell script validates the build variables passed in. If -:: necessary, the user is prmopted to pick the variables. It then creates -:: an include file that is imbedded in the HBIOS assembly (build.inc). +:: necessary, the user is prompted to pick the variables. It then creates +:: an include file that is embedded in the HBIOS assembly (build.inc). :: It also creates a batch command file that sets environment variables :: for use by the remainder of this batch file (build_env.cmd). :: @@ -71,7 +71,7 @@ if %Platform%==DUO ( ) :: -:: Bring the previously build font files into this directory +:: Bring the previously build font files into this directory :: copy ..\Fonts\font*.asm . || exit /b @@ -91,45 +91,53 @@ tasm -t%CPUType% -g3 -dAPPBOOT hbios.asm hbios_app.bin hbios_app.lst || exit /b call :asm dbgmon || exit /b call :asm romldr || exit /b +call :asm invntdev || exit /b +call :asm invntslc || exit /b call :asm eastaegg || exit /b call :asm nascom || exit /b :: call :asm tastybasic || exit /b call :asm game || exit /b call :asm usrrom || exit /b call :asm updater || exit /b -call :asm imgpad2 || exit /b +call :asm romfonts || exit /b :: Sysconf builds as both BIN and COM files + tasm -t%CPUType% -g3 -fFF -dROMWBW sysconf.asm sysconf.bin sysconf_bin.lst || exit /b tasm -t%CPUType% -g3 -fFF -dCPM sysconf.asm sysconf.com sysconf_com.lst || exit /b -:: -:: Create additional ROM bank images by assembling components into -:: 32K chunks which can be concatenated later. Note that -:: osimg_small is a special case because it is 20K in size. This -:: image is subsequently used to generate the .com loadable file. -:: - -copy /b romldr.bin + dbgmon.bin + ..\zsdos\zsys_wbw.bin + ..\cpm22\cpm_wbw.bin osimg.bin || exit /b -copy /b ..\Forth\camel80.bin + nascom.bin + ..\tastybasic\src\tastybasic.bin + game.bin + eastaegg.bin + %NETBOOT% + updater.bin + sysconf.bin + usrrom.bin osimg1.bin || exit /b +:: Create platform specific hardware monitor if %Platform%==S100 ( - zxcc slr180 -s100mon/fh + zxcc slr180 -s100mon/fh || exit /b zxcc mload25 -s100mon || exit /b - copy /b s100mon.com osimg2.bin || exit /b + set HwMon=s100mon.com ) else ( - copy /b imgpad2.bin osimg2.bin || exit /b + call :asm hwmon || exit /b + set HwMon=hwmon.bin ) -copy /b romldr.bin + dbgmon.bin + ..\zsdos\zsys_wbw.bin osimg_small.bin || exit /b +:: +:: Create additional ROM bank images by assembling components into +:: 32K chunks which can be concatenated later. Note that +:: appboot is a special case because it is 20K in size. This +:: image is subsequently used to generate the .com loadable file. +:: + +copy /b romldr.bin + dbgmon.bin + ..\zsdos\zsys_wbw.bin + ..\cpm22\cpm_wbw.bin rom1.bin || exit /b +copy /b ..\Forth\camel80.bin + nascom.bin + ..\tastybasic\src\tastybasic.bin + game.bin + eastaegg.bin + %NETBOOT% + updater.bin + sysconf.bin + usrrom.bin rom2.bin || exit /b +copy /b %HwMon% + invntdev.bin + invntslc.bin + romfonts.bin rom3.bin +copy /b romldr.bin + dbgmon.bin + ..\zsdos\zsys_wbw.bin appboot.bin || exit /b :: :: Inject one byte checksum at the last byte of all 4 ROM bank image files. -:: This means that computing a checksum over any of the 32K osimg banks -:: should yield a result of zero. +:: This means that computing a checksum over any of the 32K rom banks +:: should yield a result of zero. Any bank image file that is not +:: 32K will be automatically normalized to 32K by the srec_cat +:: formula (extended or truncated)!!! :: -for %%f in (hbios_rom.bin osimg.bin osimg1.bin osimg2.bin) do ( +for %%f in (hbios_rom.bin rom1.bin rom2.bin rom3.bin) do ( "%TOOLS%\srecord\srec_cat.exe" %%f -Binary -Crop 0 0x7FFF -Checksum_Negative_Big_Endian 0x7FFF 1 1 -o %%f -Binary || exit /b ) @@ -150,13 +158,13 @@ for %%f in (hbios_rom.bin osimg.bin osimg1.bin osimg2.bin) do ( :: if %ROMSize% gtr 0 ( - copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin + ..\RomDsk\rom%ROMDiskSize%_wbw.dat %ROMName%.rom || exit /b - copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin %ROMName%.upd || exit /b - copy /b hbios_app.bin + osimg_small.bin %ROMName%.com || exit /b + copy /b hbios_rom.bin + rom1.bin + rom2.bin + rom3.bin + ..\RomDsk\rom%ROMDiskSize%_wbw.dat %ROMName%.rom || exit /b + copy /b hbios_rom.bin + rom1.bin + rom2.bin + rom3.bin %ROMName%.upd || exit /b + copy /b hbios_app.bin + appboot.bin %ROMName%.com || exit /b ) else ( - copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin + ..\RomDsk\rom%RAMDiskSize%_wbw.dat %ROMName%.rom || exit /b - copy /b hbios_rom.bin + osimg.bin + osimg1.bin + osimg2.bin %ROMName%.upd || exit /b - copy /b hbios_app.bin + osimg_small.bin %ROMName%.com || exit /b + copy /b hbios_rom.bin + rom1.bin + rom2.bin + rom3.bin + ..\RomDsk\rom%RAMDiskSize%_wbw.dat %ROMName%.rom || exit /b + copy /b hbios_rom.bin + rom1.bin + rom2.bin + rom3.bin %ROMName%.upd || exit /b + copy /b hbios_app.bin + appboot.bin %ROMName%.com || exit /b ) :: @@ -187,14 +195,14 @@ call :asm dbgmon || exit /b call :asm romldr || exit /b :: Create the OS bank -copy /b romldr.bin + dbgmon.bin + ..\zsdos\zsys_una.bin + ..\cpm22\cpm_una.bin osimg.bin || exit /b +copy /b romldr.bin + dbgmon.bin + ..\zsdos\zsys_una.bin + ..\cpm22\cpm_una.bin rom2.bin || exit /b :: Copy OS Bank and ROM Disk image files to output -copy /b osimg.bin ..\..\Binary\UNA_WBW_SYS.bin || exit /b +copy /b rom2.bin ..\..\Binary\UNA_WBW_SYS.bin || exit /b copy /b ..\RomDsk\rom%ROMDiskSize%_una.dat ..\..\Binary\UNA_WBW_ROM%ROMDiskSize%.bin || exit /b :: Create the final ROM image -copy /b ..\UBIOS\UNA-BIOS.BIN + osimg.bin + ..\UBIOS\FSFAT.BIN + ..\RomDsk\rom%ROMDiskSize%_una.dat %ROMName%.rom || exit /b +copy /b ..\UBIOS\UNA-BIOS.BIN + rom2.bin + ..\UBIOS\FSFAT.BIN + ..\RomDsk\rom%ROMDiskSize%_una.dat %ROMName%.rom || exit /b :: Copy to output copy %ROMName%.rom ..\..\Binary || exit /b diff --git a/Source/HBIOS/Config/RCEZ80_std.asm b/Source/HBIOS/Config/RCEZ80_std.asm index f51f0d03..12411306 100644 --- a/Source/HBIOS/Config/RCEZ80_std.asm +++ b/Source/HBIOS/Config/RCEZ80_std.asm @@ -55,7 +55,7 @@ CRTACT .SET FALSE ; ACTIVATE CRT (VDU,CVDU,PROPIO,ETC) AT STARTUP VDAEMU_SERKBD .SET $FF ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD ;; TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM) -TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU] +TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY] TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958 TMSTIMENABLE .SET FALSE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1) VRCENABLE .SET FALSE ; VRC: ENABLE VGARC VIDEO/KBD DRIVER (VRC.ASM) @@ -71,6 +71,14 @@ PPIDEENABLE .SET TRUE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM) SDENABLE .SET FALSE ; SD: ENABLE SD CARD DISK DRIVER (SD.ASM) SDMODE .SET SDMODE_PIO ; SD: DRIVER MODE: SDMODE_[JUHA|N8|CSIO|PPI|UART|DSD|MK4|SC|MT|USR|PIO|Z80R|EPITX|FZ80|GM|EZ512|K80W] SDCNT .SET 1 ; SD: NUMBER OF SD CARD DEVICES (1-2), FOR DSD/SC/MT ONLY +; +CHENABLE .SET TRUE ; CH: ENABLE CH375/376 USB SUPPORT +CHNATIVEENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER +CHSCSIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE) +CHUFIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE) +CHNATIVEEZ80 .SET TRUE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE +CHNATIVEFORCE .SET FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED +; PRPENABLE .SET FALSE ; PRP: ENABLE ECB PROPELLER IO BOARD DRIVER (PRP.ASM) ; LPTENABLE .SET FALSE ; LPT: ENABLE CENTRONICS PRINTER DRIVER (LPT.ASM) @@ -82,3 +90,5 @@ SN76489ENABLE .SET FALSE ; SN: ENABLE SN76489 SOUND DRIVER AY38910ENABLE .SET FALSE ; AY: ENABLE AY-3-8910 / YM2149 SOUND DRIVER AYMODE .SET AYMODE_RCZ80 ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC|DUO|NABU] AY_FORCE .SET FALSE ; AY: BYPASS AUTO-DETECT, FORCED PRESENT + +EZ80TIMER .SET EZ80TMR_FIRM ; EZ80: TIMER TICK MODEL: EZ80TMR_[INT|FIRM] diff --git a/Source/HBIOS/Config/RCZ80_std.asm b/Source/HBIOS/Config/RCZ80_std.asm index 80e756b3..f8cce67c 100644 --- a/Source/HBIOS/Config/RCZ80_std.asm +++ b/Source/HBIOS/Config/RCZ80_std.asm @@ -72,7 +72,7 @@ ACIAENABLE .SET TRUE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) SIOENABLE .SET TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM) ; TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM) -TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU] +TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY] TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958 TMSTIMENABLE .SET FALSE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1) VRCENABLE .SET FALSE ; VRC: ENABLE VGARC VIDEO/KBD DRIVER (VRC.ASM) @@ -92,6 +92,10 @@ SDMODE .SET SDMODE_PIO ; SD: DRIVER MODE: SDMODE_[JUHA|N8|CSIO|PPI|UART|DSD|MK4 SDCNT .SET 1 ; SD: NUMBER OF SD CARD DEVICES (1-2), FOR DSD/SC/MT ONLY ; CHENABLE .SET TRUE ; CH: ENABLE CH375/376 USB SUPPORT +CHNATIVEENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER +CHSCSIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE) +CHUFIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE) +CHNATIVEFORCE .SET FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED ; PRPENABLE .SET FALSE ; PRP: ENABLE ECB PROPELLER IO BOARD DRIVER (PRP.ASM) ; diff --git a/Source/HBIOS/Config/RCZ80_xosera.asm b/Source/HBIOS/Config/RCZ80_xosera.asm new file mode 100644 index 00000000..ac31346c --- /dev/null +++ b/Source/HBIOS/Config/RCZ80_xosera.asm @@ -0,0 +1,61 @@ +; +;================================================================================================== +; ROMWBW CUSTOM USER BUILD SETTINGS EXAMPLE FOR RCBUS Z80 +;================================================================================================== +; +; THIS FILE IS AN EXAMPLE OF A CUSTOM USER SETTINGS FILE. THESE +; SETTINGS OVERRIDE THE DEFAULT SETTINGS OF THE INHERITED FILES AS +; DESIRED BY A USER. +; +; ROMWBW USES CASCADING CONFIGURATION FILES AS INDICATED BELOW: +; +; cfg_MASTER.asm - MASTER: CONFIGURATION FILE DEFINES ALL POSSIBLE ROMWBW SETTINGS +; | +; +-> cfg_.asm - PLATFORM: DEFAULT SETTINGS FOR SPECIFIC PLATFORM +; | +; +-> Config/_std.asm - BUILD: SETTINGS FOR EACH OFFICIAL DIST BUILD +; | +; +-> Config/_.asm - USER: CUSTOM USER BUILD SETTINGS +; +; THE TOP (MASTER CONFIGURATION) FILE DEFINES ALL POSSIBLE ROMWBW +; CONFIGURATION SETTINGS. EACH FILE BELOW THE MASTER CONFIGURATION FILE +; INHERITS THE CUMULATIVE SETTINGS OF THE FILES ABOVE IT AND MAY +; OVERRIDE THESE SETTINGS AS DESIRED. +; +; OTHER THAN THE TOP MASTER FILE, EACH FILE MUST "#INCLUDE" ITS PARENT +; FILE (SEE #INCLUDE STATEMENT BELOW). THE TOP TWO FILES SHOULD NOT BE +; MODIFIED. +; +; THIS FILE EXEMPLIFIES THE IDEAL WAY TO CREATE A USER SPECIFIC BUILD +; CONFIGURATION. NOTICE THAT IT INCLUDES THE DEFAULT BUILD SETTINGS +; FILE AND OVERRIDES SOME DESIRED SETTINGS. +; +; BY CREATING A CUSTOM USER SETTINGS FILE, YOU ARE LESS LIKELY TO BE +; IMPACTED BY FUTURE CHANGES BECAUSE YOU WILL BE INHERITING MOST +; OF YOUR SETTINGS WHICH WILL BE UPDATED BY AUTHORS AS ROMWBW EVOLVES. +; +; PLEASE REFER TO THE CUSTOM BUILD INSTRUCTIONS (README.TXT) IN THE +; SOURCE DIRECTORY (TWO DIRECTORIES ABOVE THIS ONE). +; +; *** WARNING: ASIDE FROM THE MASTER CONFIGURATION FILE, YOU MUST USE +; ".SET" TO OVERRIDE SETTINGS. THE ASSEMBLER WILL ERROR IF YOU ATTEMPT +; TO USE ".EQU" BECAUSE IT WON'T LET YOU REDEFINE A SETTING WITH ".EQU". +; +; THIS FILE ENABLES THE XOSERA DRIVER WITH A BASE ADDRESS Of $A0 AND +; DISPLAY SIZE OF 80 COLUMNS X 30 ROWS. +; +#INCLUDE "Config/RCZ80_std.asm" ; INHERIT FROM OFFICIAL BUILD SETTINGS +; +XOSENABLE .SET TRUE ; XOSERA: ENABLE XOSERA VIDEO DRIVERS (XOSERA.ASM) +XOS_BASE .SET $A0 ; XOSERA: I/O BASE ADDRESS (REQUIRES 32 BYTES) +XOSSIZ .SET V80X30 ; XOSERA: DISPLAY FORMAT [V80X30|V80X60] +; +AUTOCON .SET FALSE ; ENABLE CONSOLE TAKEOVER AT LOADER PROMPT +VDAEMU_SERKBD .SET $0 ; VDA EMULATION: SERIAL KBD UNIT #, OR $FF FOR HW KBD +; +; WHEN A XOSERA BOARD IN IS THE SYSTEM, LIMIT THE NUMBER OF UARTS THAT ARE PROBED +; TO TWO, BECAUSE THE PROBE TO DETECT A THIRD UART WRITES UNLUCKY VALUES TO +; XOSERA THAT CAUSE IT TO RECONFIGURE ITSELF AND LOCK UP THE BUS FOR A TIME. IF +; YOU NEED MORE THAN TWO UARTS, YOU WILL NEED TO MOVE XOSERA OUT OF THE $A0-$BF +; I/O ADDRESS REGION. +UARTCNT .SET 2 diff --git a/Source/HBIOS/Layout.txt b/Source/HBIOS/Layout.txt index 67b684a2..31923acf 100644 --- a/Source/HBIOS/Layout.txt +++ b/Source/HBIOS/Layout.txt @@ -3,66 +3,72 @@ Final Output Files ------------------ ROM Output File [512K] -> .rom - hbios_rom [32K] - OSIMG [32K] - OSIMG1 [32K] - OSIMG2 [32K] - romdisk - [384K] + HBIOS_ROM [32K] + ROM1 [32K] + ROM2 [32K] + ROM3 [32K] + ROMDISK [384K] (size varies with ROM in system) UPD Output File [128K] -> .upd - hbios_rom [32K] - OSIMG [32K] - OSIMG1 [32K] - OSIMG2 [32K] + HBIOS_ROM [32K] + ROM1 [32K] + ROM2 [32K] + ROM3 [32K] COM Output File -> .com - hbios_app [varies] - OSIMG_SMALL [32K] + HBIOS_APP [<32K] (size varies, no padding] + APPBOOT [ 20K] ------------------------- Intermediate Output Files ------------------------- -OSIMG [32K] -> osimg.bin - romldr [4K] - dbgmon [4K] - ZSYS (zcpr/zsdos/cbios) [12K] - CPM (ccp/bdos/cbios) [12K] +ROM1 [32K] -> rom1.bin + romldr [ 4K] + dbgmon [ 4K] + ZSYS [12K] (zcpr/zsdos/cbios) + CPM [12K] (ccp/bdos/cbios) -OSIMG_SMALL [20K] -> osimg_small.bin - romldr [4K] - dbgmon [4K] - ZSYS (zcpr/zsdos/cbios) [12K] - -OSIMG1 [32K] -> osimg1.bin +ROM2 [32K] -> rom2.bin camel80 [5.75K] - nascom [8K] - tastybasic [2.5K] + nascom [8.00K] + tastybasic [2.50K] game [2.25K] - eastaegg [0.5K] - netboot [4K] + eastaegg [0.50K] + netboot [4.00K] updater.bin [3.25K] - sysconf.bin [2K] - usrrom.bin [3.75K (padded)] + sysconf.bin [2.00K] + usrrom.bin [3.75K] + +ROM3 [32K] -> rom3.bin + hwmon [ 8.00K] + invntdev [ 2.75K] + invntslc [ 0.50K] + fonts [ 8.00K] + slack [12.75K] -OSIMG2 [32K] -> osimg2.bin - s100mon [8.25kb (optional)] - (OR) not populated +APPBOOT [20K] -> appboot.bin + romldr [ 4K] + dbgmon [ 4K] + ZSYS [12K] (zcpr/zsdos/cbios) CPM [12K] -> cpm.bin - ccp [2K] - bdos [3.5K] - cbios [6.5K] + ccp [2.0K] + bdos [3.5K] + cbios [6.5K] ZSYS [12K] -> zsys.bin - zcpr [2K] - zsdos [3.5K] - cbios [6.5K] + zcpr [2.0K] + zsdos [3.5K] + cbios [6.5K] ----------------- Compilation Units ----------------- +NOTE: The following need to be reviewed. They are probably out +of date. + hbios.asm -> hbios_rom.bin, hbios_app.bin std.asm ver.inc @@ -76,7 +82,7 @@ hbios.asm -> hbios_rom.bin, hbios_app.bin bcd.asm dsky.asm -romldr.asm -> romldr.bin: loader? +romldr.asm -> romldr.bin std.asm ver.inc hbios.inc @@ -125,18 +131,16 @@ tastybasic.asm -> tastybasic.bin .asm plt_.inc - ======================================================================= HBIOS Loading Modes: ROMBOOT: Startup from ROM Bank BID_BOOT APPBOOT: Startup as CP/M application - IMGBOOT: Startup from RAM Bank BID_USR + IMGBOOT: Startup from RAM Bank BID_USR (deprecated) ======================================================================= - If not (APPBOOT), include page 0 - Base Hardware Init - - Iff (ROMBOOT), init BBR - Install Proxy - Set CURBNK: @@ -149,6 +153,6 @@ HBIOS Loading Modes: - Copy OS Image to USR Bank - If (ROM_MODE), copy BID_OS:0 --> BID_USR:0 - - Else, copy BID_USR: --> BID_USR:0 + - Else, copy BID_BIOS: --> BID_USR:0 - Chain to BID_USR:0 diff --git a/Source/HBIOS/Makefile b/Source/HBIOS/Makefile index 3e5cb57e..181cb0b2 100644 --- a/Source/HBIOS/Makefile +++ b/Source/HBIOS/Makefile @@ -1,11 +1,11 @@ MOREDIFF = game.bin hbios_rom.bin nascom.bin usrrom.bin \ - dbgmon.bin hbios_app.bin imgpad2.bin osimg1.bin osimg2.bin romldr.bin \ - eastaegg.bin hbios_img.bin osimg.bin game.bin updater.bin usrrom.bin + dbgmon.bin hbios_app.bin rom2.bin rom3.bin romldr.bin \ + eastaegg.bin hbios_img.bin rom1.bin game.bin updater.bin usrrom.bin DEST = ../../Binary TOOLS =../../Tools -OTHERS = *.img *.rom *.com *.upd *.bin *.hex cpm.sys zsys.sys Build.inc font*.asm *.dat hbios_env.sh netboot.mod +OTHERS = *.img *.rom *.com *.upd *.bin *.hex cpm.sys zsys.sys Build.inc font*.asm *.dat hbios_env.sh # DIFFMAKE = 1 @@ -23,8 +23,8 @@ endif include $(TOOLS)/Makefile.inc -FONTS := font8x11c.asm font8x11u.asm font8x16c.asm font8x16u.asm font8x8c.asm font8x8u.asm \ - fontcgac.asm fontcgau.asm fontvgarcc.asm fontvgarcu.asm +FONTS := font6x8c.asm font6x8u.asm font8x8c.asm font8x8u.asm \ + font8x11c.asm font8x11u.asm font8x16c.asm font8x16u.asm ifeq ($(CPUFAM),2) TASM=$(BINDIR)/uz80as -t hd64180 @@ -32,7 +32,7 @@ else ifeq ($(CPUFAM),3) TASM=$(BINDIR)/uz80as -t z280 endif -DEPS=prereq dbgmon.bin romldr.bin nascom.bin tastybasic.bin game.bin eastaegg.bin updater.bin sysconf.bin sysconf.com usrrom.bin imgpad2.bin +DEPS=prereq dbgmon.bin romldr.bin nascom.bin tastybasic.bin invntdev.bin invntslc.bin game.bin eastaegg.bin updater.bin sysconf.bin sysconf.com usrrom.bin romfonts.bin ifeq ($(ROM_PLATFORM),UNA) ROMDEPS=romldr.bin dbgmon.bin @@ -43,9 +43,19 @@ else endif ifeq ($(ROM_PLATFORM),S100) - ROMDEPS += s100mon.bin + HWMON=s100mon.bin +else + HWMON=hwmon.bin +endif + +ifeq ($(ROM_PLATFORM),DUO) + NETBOOT=netboot-duo.mod +else + NETBOOT=netboot-mt.mod endif +DEPS += $(HWMON) $(NETBOOT) + ROMNAME=${ROM_PLATFORM}_${ROM_CONFIG} # $(info DEPS=$(DEPS)) @@ -58,37 +68,28 @@ ROMNAME=${ROM_PLATFORM}_${ROM_CONFIG} # $(info TASM=$(TASM)) $(OBJECTS) : $(ROMDEPS) - @cat romldr.bin dbgmon.bin ../ZSDOS/zsys_$(BIOS).bin ../CPM22/cpm_$(BIOS).bin >osimg.bin - cat romldr.bin dbgmon.bin ../ZSDOS/zsys_$(BIOS).bin >osimg_small.bin - if [ $(ROM_PLATFORM) = DUO ] ; then \ - cat netboot-duo.mod >netboot.mod ; \ - else \ - cat netboot-mt.mod >netboot.mod ; \ - fi + @cat romldr.bin dbgmon.bin ../ZSDOS/zsys_$(BIOS).bin ../CPM22/cpm_$(BIOS).bin >rom1.bin + cat romldr.bin dbgmon.bin ../ZSDOS/zsys_$(BIOS).bin >appboot.bin if [ $(ROM_PLATFORM) != UNA ] ; then \ - cat camel80.bin nascom.bin tastybasic.bin game.bin eastaegg.bin netboot.mod updater.bin sysconf.bin usrrom.bin >osimg1.bin ; \ - if [ $(ROM_PLATFORM) = S100 ] ; then \ - cat s100mon.bin >osimg2.bin ; \ - else \ - cat imgpad2.bin >osimg2.bin ; \ - fi ; \ - for f in hbios_rom.bin osimg.bin osimg1.bin osimg2.bin ; do \ + cat camel80.bin nascom.bin tastybasic.bin game.bin eastaegg.bin $(NETBOOT) updater.bin sysconf.bin usrrom.bin >rom2.bin ; \ + cat $(HWMON) invntdev.bin invntslc.bin romfonts.bin >rom3.bin ; \ + for f in hbios_rom.bin rom1.bin rom2.bin rom3.bin ; do \ srec_cat $$f -Binary -Crop 0 0x7FFF -Checksum_Negative_Big_Endian 0x7FFF 1 1 -o $$f -Binary ; \ done \ fi if [ $(ROM_PLATFORM) = UNA ] ; then \ - cp osimg.bin $(DEST)/UNA_WBW_SYS.bin ; \ + cp rom1.bin $(DEST)/UNA_WBW_SYS.bin ; \ cp ../RomDsk/rom$(ROMDISKSIZE)_una.dat $(DEST)/UNA_WBW_ROM$(ROMDISKSIZE).bin ; \ - cat ../UBIOS/UNA-BIOS.BIN osimg.bin ../UBIOS/FSFAT.BIN ../RomDsk/rom$(ROMDISKSIZE)_una.dat >$(ROMNAME).rom ; \ + cat ../UBIOS/UNA-BIOS.BIN rom1.bin ../UBIOS/FSFAT.BIN ../RomDsk/rom$(ROMDISKSIZE)_una.dat >$(ROMNAME).rom ; \ else \ if [ $(ROMSIZE) -gt 0 ] ; then \ - cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin ../RomDsk/rom$(ROMDISKSIZE)_wbw.dat >$(ROMNAME).rom ; \ - cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin >$(ROMNAME).upd ; \ - cat hbios_app.bin osimg_small.bin > $(ROMNAME).com ; \ + cat hbios_rom.bin rom1.bin rom2.bin rom3.bin ../RomDsk/rom$(ROMDISKSIZE)_wbw.dat >$(ROMNAME).rom ; \ + cat hbios_rom.bin rom1.bin rom2.bin rom3.bin >$(ROMNAME).upd ; \ + cat hbios_app.bin appboot.bin > $(ROMNAME).com ; \ else \ - cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin ../RomDsk/rom$(RAMDISKSIZE)_wbw.dat >$(ROMNAME).rom ; \ - cat hbios_rom.bin osimg.bin osimg1.bin osimg2.bin >$(ROMNAME).upd ; \ - cat hbios_app.bin osimg_small.bin > $(ROMNAME).com ; \ + cat hbios_rom.bin rom1.bin rom2.bin rom3.bin ../RomDsk/rom$(RAMDISKSIZE)_wbw.dat >$(ROMNAME).rom ; \ + cat hbios_rom.bin rom1.bin rom2.bin rom3.bin >$(ROMNAME).upd ; \ + cat hbios_app.bin appboot.bin > $(ROMNAME).com ; \ fi \ fi @@ -132,8 +133,13 @@ hbios_env.sh: hbios_env.com romldr.bin: build.inc dbgmon.bin: build.inc nascom.bin: build.inc +invntdev.bin: build.inc +invntslc.bin: build.inc eastaegg.bin: build.inc updater.bin: build.inc +romfonts.bin: build.inc +hwmon.bin: build.inc +s100mon.bin: build.inc dumps: for i in $(MOREDIFF) ; do \ diff --git a/Source/HBIOS/acia.asm b/Source/HBIOS/acia.asm index dab9d31e..df2f2516 100644 --- a/Source/HBIOS/acia.asm +++ b/Source/HBIOS/acia.asm @@ -123,10 +123,8 @@ ACIA_INITUNIT: CALL ACIA_INITSAFE ; ; SET DEFAULT CONFIG - LD DE,-1 ; LEAVE CONFIG ALONE - ; CALL INITDEV TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL - ; THE INITDEV ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! - JP ACIA_INITDEVX ; IMPLEMENT IT AND RETURN + LD DE,-1 ; LEAVE CONFIG ALONE + JP ACIA_INITDEV ; IMPLEMENT IT AND RETURN ; ; ; @@ -366,15 +364,22 @@ ACIA_OST: ; ; ACIA_INITDEV: + ; INITDEV CAN BE CALLED PRIOR TO INTERRUPTS BEING ENABLED. WE + ; NEED TO LEAVE INTERRUPTS ALONE IN THIS SCENARIO + LD A,(INTSENAB) ; INTS ENABLED? + OR A ; TEST VALUE + JR Z,ACIA_INITDEV0 ; BYPASS DI/EI IF NOT ENABLED +; + ; INTERRUPTS DISABLED DURING INIT HB_DI ; AVOID CONFLICTS - CALL ACIA_INITDEVX ; DO THE REAL WORK + CALL ACIA_INITDEV0 ; DO THE REAL WORK HB_EI ; INTS BACK ON RET ; DONE ; ; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY ; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! ; -ACIA_INITDEVX: +ACIA_INITDEV0: ; #IF (ACIADEBUG) CALL NEWLINE diff --git a/Source/HBIOS/ansi.asm b/Source/HBIOS/ansi.asm index 8ca7e7f5..3bd77be0 100644 --- a/Source/HBIOS/ansi.asm +++ b/Source/HBIOS/ansi.asm @@ -1554,4 +1554,4 @@ ANSI_DEVNUM .DB $FF ; TERMINAL DEVICE NUMBER ; E Light Cyan ; F Bright White ;============================================================= -; \ No newline at end of file +; diff --git a/Source/HBIOS/asci.asm b/Source/HBIOS/asci.asm index 5f6c00dd..9bd45926 100644 --- a/Source/HBIOS/asci.asm +++ b/Source/HBIOS/asci.asm @@ -170,9 +170,7 @@ ASCI_INITUNIT: ; ; SET DEFAULT CONFIG LD DE,-1 ; LEAVE CONFIG ALONE - ; CALL INITDEV TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL - ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! - JP ASCI_INITDEVX ; IMPLEMENT IT AND RETURN + JP ASCI_INITDEV ; IMPLEMENT IT AND RETURN ; ; ; @@ -424,20 +422,20 @@ ASCI_OST: ; REQUIRED BY THE ASCI AND STORED IN A PORT/REGISTER INITIALIZATION TABLE, ; WHICH IS THEN LOADED INTO THE ASCI. ; -; NOTE THAT THERE ARE TWO ENTRY POINTS. INITDEV WILL DISABLE/ENABLE INTS -; AND INITDEVX WILL NOT. THIS IS DONE SO THAT THE PREINIT ROUTINE ABOVE -; CAN AVOID ENABLING/DISABLING INTS. -; ASCI_INITDEV: + ; INITDEV CAN BE CALLED PRIOR TO INTERRUPTS BEING ENABLED. WE + ; NEED TO LEAVE INTERRUPTS ALONE IN THIS SCENARIO + LD A,(INTSENAB) ; INTS ENABLED? + OR A ; TEST VALUE + JR Z,ASCI_INITDEV0 ; BYPASS DI/EI IF NOT ENABLED +; + ; INTERRUPTS DISABLED DURING INIT HB_DI ; DISABLE INTS - CALL ASCI_INITDEVX ; DO THE WORK + CALL ASCI_INITDEV0 ; DO THE WORK HB_EI ; INTS BACK ON RET ; DONE ; -ASCI_INITDEVX: -; -; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY -; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! +ASCI_INITDEV0: ; ; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR diff --git a/Source/HBIOS/audio.inc b/Source/HBIOS/audio.inc index fcb686c7..11021c49 100644 --- a/Source/HBIOS/audio.inc +++ b/Source/HBIOS/audio.inc @@ -45,8 +45,8 @@ AUD_SCALE .EQU 3 ; ON ENTRY, DE IS ADDRESS OF NOTE TABLE, HL IS NOTE TO PLAY ; NOTE VALUE 0 MEANS B0b/A0# IN OCTAVE 0 WHICH IS THE FIRST ENTRY ; OF THE NOTE TABLE. THE NOTE TABLE REPRESENTS THE FREQUENCIES -; FOR 1 FULL OCTAVE IN QUARTER NOTES. SINCE THERE ARE 12 NOTES -; IN AN OCTAVE, THE TABLE HAS 48 ENTRIES FOR ALL QUARTER NOTES. +; FOR 1 FULL OCTAVE IN EIGHTH TONES. SINCE THERE ARE 12 HALF TONES +; IN AN OCTAVE, THE TABLE HAS 48 ENTRIES FOR ALL EIGHTH TONES. ; ; ON EXIT, HL CONTAINS THE PERIOD VALUE TO PROGRAM INTO THE PSG ; DERIVED FROM THE NOTE TABLE SCALED TO THE REQUESTED OCTAVE. diff --git a/Source/HBIOS/ay38910.asm b/Source/HBIOS/ay38910.asm index 3e5cfdf9..228e01d0 100644 --- a/Source/HBIOS/ay38910.asm +++ b/Source/HBIOS/ay38910.asm @@ -556,10 +556,10 @@ AYT_REGWR .DB "\r\nOUT AY-3-8910 $" #ENDIF ; ;====================================================================== -; QUARTER TONE FREQUENCY TABLE +; EIGHTH TONE FREQUENCY TABLE ;====================================================================== ; -; THE FOLLOWING TABLE MAPS A FULL OCTAVE OF QUARTER-NOTES +; THE FOLLOWING TABLE MAPS A FULL OCTAVE OF EIGHTH-TONES ; STARTING AT A# IN OCTAVE 0 TO THE CORRESPONDING PERIOD ; VALUE TO USE ON THE PSG TO ACHIEVE THE DESIRED NOTE FREQUENCY. ; diff --git a/Source/HBIOS/cfg_DUO.asm b/Source/HBIOS/cfg_DUO.asm index c8d3c792..9f673e01 100644 --- a/Source/HBIOS/cfg_DUO.asm +++ b/Source/HBIOS/cfg_DUO.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $50 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -96,6 +97,8 @@ CTCOSC .SET (7372800/8) ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER PCFBASE .SET $56 ; PCF8584 BASE I/O ADDRESS +PCFCLK .SET PCFCLK_12 ; PCF CLOCK BASE: PCFCLK_[3|443|6|8|12] +PCFTRNS .SET PCFTRNS_90 ; PCF TRANSFER SPEED: PCFTRNS_[90|45|11|15] ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; @@ -372,6 +375,9 @@ AYMODE .SET AYMODE_DUO ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC| AY_FORCE .SET FALSE ; AY: BYPASS AUTO-DETECT, FORCED PRESENT ; SPKENABLE .SET TRUE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) +SPKPORT .SET RTCIO ; SPK: THE PORT WITH THE SPEAKER IO BIT +SPKSHADOW .SET HB_RTCVAL ; SPK: THE SHADOW VALUE FOR THE PORT THAT HAS TO BE MAINTAINED +SPKMASK .SET %00000100 ; SPK: THE BIT MASK TO ACTUALLY TOGGLE ; DMAENABLE .SET FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .SET $40 ; DMA: DMA BASE ADDRESS diff --git a/Source/HBIOS/cfg_DYNO.asm b/Source/HBIOS/cfg_DYNO.asm index 80b95152..2e490248 100644 --- a/Source/HBIOS/cfg_DYNO.asm +++ b/Source/HBIOS/cfg_DYNO.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -97,7 +98,6 @@ CTCBASE .SET $88 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_EPITX.asm b/Source/HBIOS/cfg_EPITX.asm index e6bd05e0..2c4ca360 100644 --- a/Source/HBIOS/cfg_EPITX.asm +++ b/Source/HBIOS/cfg_EPITX.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -92,7 +93,6 @@ CTCBASE .SET $88 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_EZZ80.asm b/Source/HBIOS/cfg_EZZ80.asm index 577d25b4..d018867c 100644 --- a/Source/HBIOS/cfg_EZZ80.asm +++ b/Source/HBIOS/cfg_EZZ80.asm @@ -71,6 +71,7 @@ INTMODE .SET 1 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -95,7 +96,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET CPUOSC ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_FZ80.asm b/Source/HBIOS/cfg_FZ80.asm index 8a14e828..20df2770 100644 --- a/Source/HBIOS/cfg_FZ80.asm +++ b/Source/HBIOS/cfg_FZ80.asm @@ -71,6 +71,7 @@ INTMODE .SET 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 0 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -95,7 +96,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET CPUOSC ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_GMZ180.asm b/Source/HBIOS/cfg_GMZ180.asm index 4671582e..a0d38d51 100644 --- a/Source/HBIOS/cfg_GMZ180.asm +++ b/Source/HBIOS/cfg_GMZ180.asm @@ -70,6 +70,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -91,7 +92,6 @@ CTCBASE .SET $88 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_HEATH.asm b/Source/HBIOS/cfg_HEATH.asm index 177e0247..241b9ac2 100644 --- a/Source/HBIOS/cfg_HEATH.asm +++ b/Source/HBIOS/cfg_HEATH.asm @@ -71,6 +71,7 @@ INTMODE .SET 1 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -95,7 +96,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET CPUOSC ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_MASTER.asm b/Source/HBIOS/cfg_MASTER.asm index 470a523e..8b3f35be 100644 --- a/Source/HBIOS/cfg_MASTER.asm +++ b/Source/HBIOS/cfg_MASTER.asm @@ -71,6 +71,7 @@ INTMODE .EQU 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .EQU 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .EQU 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .EQU TRUE ; LOAD FONTS FROM ROM APP_BNKS .EQU $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .EQU MM_NONE ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .EQU ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -128,8 +129,8 @@ CTCOSC .EQU 614400 ; CTC CLOCK FREQUENCY ; PCFENABLE .EQU FALSE ; ENABLE PCF8584 I2C CONTROLLER PCFBASE .EQU $F0 ; PCF8584 BASE I/O ADDRESS -PCFCLK .EQU 12 ; PCF CLOCK BASE -PCFTRNS .EQU 90 ; PCF TRANSFER SPEED +PCFCLK .EQU PCFCLK_12 ; PCF CLOCK BASE: PCFCLK_[3|443|6|8|12] +PCFTRNS .EQU PCFTRNS_90 ; PCF TRANSFER SPEED: PCFTRNS_[90|45|11|15] ; EIPCENABLE .EQU FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; @@ -202,6 +203,9 @@ DS7RTCMODE .EQU DS7RTCMODE_PCF ; DS7RTC: OPERATING MODE: DS7RTCMODE_[PCF] ; DS5RTCENABLE .EQU FALSE ; DS5RTC: ENABLE DS-1305 SPI CLOCK DRIVER (DS5RTC.ASM) ; +PCRTCENABLE .EQU FALSE ; PCRTC: DISABLE DS12885 etc. RTC +PCRTC_BASE .EQU $C0 ; Default port for PCRTC, like DSRTC. +; SSERENABLE .EQU FALSE ; SSER: ENABLE SIMPLE SERIAL DRIVER (SSER.ASM) SSERCFG .EQU SER_9600_8N1 ; SSER: SERIAL LINE CONFIG SSERSTATUS .EQU $FF ; SSER: STATUS PORT @@ -311,6 +315,9 @@ VRCENABLE .EQU FALSE ; VRC: ENABLE VGARC VIDEO/KBD DRIVER (VRC.ASM) SCONENABLE .EQU FALSE ; SCON: ENABLE S100 CONSOLE DRIVER (SCON.ASM) EFENABLE .EQU FALSE ; EF: ENABLE EF9345 VIDEO DRIVER (EF.ASM) FVENABLE .EQU FALSE ; FV: ENABLE FPGA VGA VIDEO DRIVER (FV.ASM) +XOSENABLE .EQU FALSE ; XOSERA: ENABLE XOSERA VIDEO DRIVERS (XOSERA.ASM) +XOS_BASE .EQU $20 ; XOSERA: I/O BASE ADDRESS (REQUIRES 32 BYTES) +XOSSIZ .EQU V80X30 ; XOSERA: DISPLAY FORMAT [V80X30|V80X60] ; MDENABLE .EQU TRUE ; MD: ENABLE MEMORY (ROM/RAM) DISK DRIVER (MD.ASM) MDROM .EQU TRUE ; MD: ENABLE ROM DISK @@ -456,6 +463,9 @@ AYMODE .EQU AYMODE_NONE ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC AY_FORCE .EQU FALSE ; AY: BYPASS AUTO-DETECT, FORCED PRESENT ; SPKENABLE .EQU FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) +SPKPORT .EQU RTCIO ; SPK: THE PORT WITH THE SPEAKER IO BIT +SPKSHADOW .EQU HB_RTCVAL ; SPK: THE SHADOW VALUE FOR THE PORT THAT HAS TO BE MAINTAINED +SPKMASK .EQU %00000100 ; SPK: THE BIT MASK TO ACTUALLY TOGGLE ; DMAENABLE .EQU FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .EQU $E0 ; DMA: DMA BASE ADDRESS @@ -478,20 +488,29 @@ EZ80IOBASE .EQU $FF ; EZ80 I/O BASE ADDRESS FOR EXTERNAL IO ; BUS TIMING FOR PAGED MEMORY ACCESS (CS3) EZ80_MEM_CYCLES .EQU 3 ; MEMORY BUS CYCLES (1-15) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CYCLES EZ80_MEM_MIN_NS .EQU 100 ; CALCULATE AT BOOT TIME THE REQUIRED W/S OR B/C, IF EZ80_WSMD_TYP = EZ80WSMD_CALC -EZ80_MEM_WS .EQU 5 ; MEMORY WAIT STATES (0-7) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_WAIT -EZ80_MEM_MIN_WS .EQU 0 ; MINIMUM WAIT STATES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC +EZ80_MEM_MIN_BC .EQU 1 ; MINIMUM BUS CYCLES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC ; ; BUS TIMING FOR EXTERNAL I/O ACCESS (CS2) EZ80_IO_CYCLES .EQU 4 ; IO BUS CYCLES (1-15) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CYCLES -EZ80_IO_WS .EQU 5 ; IO WAIT STATES (0-7) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_WAIT -EZ80_IO_MIN_NS .EQU 320 ; CALCULATE AT BOOT TIME THE REQUIRED W/S OR B/C, IF EZ80_WSMD_TYP = EZ80WSMD_CALC -EZ80_IO_MIN_WS .EQU 6 ; MINIMUM WAIT STATES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC +EZ80_IO_MIN_NS .EQU 250 ; CALCULATE AT BOOT TIME THE REQUIRED B/C, IF EZ80_WSMD_TYP = EZ80WSMD_CALC +EZ80_IO_MIN_BC .EQU 4 ; MINIMUM BUS CYCLES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC ; -; APPLY CYCLES, W/S OR CALCULATE CYCLES BASED ON DESIRED PERIOD -EZ80_WSMD_TYP .EQU EZ80WSMD_CALC ; BUS WAIT STATE CONFIG: EZ80WSMD_[CALC|CYCLES|WAIT] +; APPLY BUS CYCLES OR CALCULATE CYCLES BASED ON DESIRED PERIOD +EZ80_WSMD_TYP .EQU EZ80WSMD_CALC ; BUS WAIT STATE CONFIG: EZ80WSMD_[CALC|CYCLES] ; ; BUS TIMING FOR ON CHIP ROM ; EZ80_FLSH_WS .EQU 1 ; WAIT STATES FOR ON CHIP FLASH (0-7) EZ80_FLSH_MIN_NS .EQU 60 ; MINIMUM WAIT STATES TO APPLY TO ON-CHIP FLASH, IF EZ80_WSMD_TYP = EZ80WSMD_CALC EZ80_FWSMD_TYP .EQU EZ80WSMD_CALC ; WAIT STATE TYPE: EZ80RMMD_[CALC|WAIT] (CYCLES NOT ALLOWED) + +CHNATIVEENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER +CHSCSIENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE) +CHUFIENABLE .EQU FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE) +CHNATIVEFORCE .EQU FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED (REQUIRES CHNATIVEENABLE) +CHNATIVEEZ80 .EQU FALSE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE + +_CH376_DATA_PORT .EQU $FF88 ; CH376: DATA PORT +_CH376_COMMAND_PORT .EQU $FF89 ; CH376: COMMAND PORT +_USB_MODULE_LEDS .EQU $FF8A ; CH376: LED CONTROL PORT + diff --git a/Source/HBIOS/cfg_MBC.asm b/Source/HBIOS/cfg_MBC.asm index 18b5f779..a137c5d0 100644 --- a/Source/HBIOS/cfg_MBC.asm +++ b/Source/HBIOS/cfg_MBC.asm @@ -71,6 +71,7 @@ INTMODE .SET 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_MBC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPCL_RAM .SET $78 ; SBC MEM MGR RAM PAGE SELECT REG (WRITE ONLY) @@ -92,7 +93,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET (4915200/8) ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; @@ -362,6 +362,9 @@ AY_CLK .SET 1789772 ; AY: PSG CLOCK FREQ, ASSUME MSX STD AYMODE .SET AYMODE_MBC ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC|MBC|DUO|NABU] ; SPKENABLE .SET TRUE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) +SPKPORT .SET RTCIO ; SPK: THE PORT WITH THE SPEAKER IO BIT +SPKSHADOW .SET HB_RTCVAL ; SPK: THE SHADOW VALUE FOR THE PORT THAT HAS TO BE MAINTAINED +SPKMASK .SET %00000100 ; SPK: THE BIT MASK TO ACTUALLY TOGGLE ; DMAENABLE .SET FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .SET $E0 ; DMA: DMA BASE ADDRESS diff --git a/Source/HBIOS/cfg_MK4.asm b/Source/HBIOS/cfg_MK4.asm index ee5183f6..bd5795cd 100644 --- a/Source/HBIOS/cfg_MK4.asm +++ b/Source/HBIOS/cfg_MK4.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -97,7 +98,6 @@ CTCBASE .SET $B0 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_MON.asm b/Source/HBIOS/cfg_MON.asm index 99e65e2b..2a0ae026 100644 --- a/Source/HBIOS/cfg_MON.asm +++ b/Source/HBIOS/cfg_MON.asm @@ -73,6 +73,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_MON ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] ; @@ -92,7 +93,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET CPUOSC ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_N8.asm b/Source/HBIOS/cfg_N8.asm index 0fbda02b..2915e2ec 100644 --- a/Source/HBIOS/cfg_N8.asm +++ b/Source/HBIOS/cfg_N8.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_N8 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET 0 ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -99,7 +100,6 @@ CTCBASE .SET $B0 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_NABU.asm b/Source/HBIOS/cfg_NABU.asm index 443bc410..f21d2bfe 100644 --- a/Source/HBIOS/cfg_NABU.asm +++ b/Source/HBIOS/cfg_NABU.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -95,7 +96,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET CPUOSC ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_RCEZ80.asm b/Source/HBIOS/cfg_RCEZ80.asm index 9e1472a8..b0831e56 100644 --- a/Source/HBIOS/cfg_RCEZ80.asm +++ b/Source/HBIOS/cfg_RCEZ80.asm @@ -69,6 +69,7 @@ INTMODE .SET 1 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -93,7 +94,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET CPUOSC ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; @@ -250,7 +250,7 @@ VDUENABLE .SET FALSE ; VDU: ENABLE VDU VIDEO/KBD DRIVER (VDU.ASM) CVDUENABLE .SET FALSE ; CVDU: ENABLE CVDU VIDEO/KBD DRIVER (CVDU.ASM) GDCENABLE .SET FALSE ; GDC: ENABLE 7220 GDC VIDEO/KBD DRIVER (GDC.ASM) TMSENABLE .SET FALSE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM) -TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU] +TMSMODE .SET TMSMODE_MSX ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY] TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958 TMSTIMENABLE .SET FALSE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1) VGAENABLE .SET FALSE ; VGA: ENABLE VGA VIDEO/KBD DRIVER (VGA.ASM) @@ -406,6 +406,12 @@ EZ80TMR_NONE .SET 0 ; DO NOT USE ON-BOARD TIMER TO GENERATE TICKS EZ80TMR_INT .SET 1 ; MARSHALL TIMER TICK INTERRUPTS FROM EZ80 TO HBIOS EZ80TMR_FIRM .SET 2 ; DELEGATE SYS TIMER HBIOS CALL TO EZ80 FIRMWARE (TIMER TICK INTS DISABLED) ; +CHNATIVEENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE USB DRIVER +CHSCSIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE) +CHUFIENABLE .SET FALSE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE) +CHNATIVEFORCE .SET FALSE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED (REQUIRES CHNATIVEENABLE) +CHNATIVEEZ80 .SET TRUE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE + EZ80UARTENABLE .SET TRUE ; EZ80 UART: ENABLE EZ80 UART0 DRIVER (EZ80UART.ASM) EZ80RTCENABLE .SET TRUE ; EZ80 ON CHIP RTC EZ80TIMER .SET EZ80TMR_FIRM ; EZ80: TIMER TICK MODEL: EZ80TMR_[INT|FIRM] @@ -414,20 +420,15 @@ EZ80IOBASE .SET $FF ; EZ80 I/O BASE ADDRESS FOR EXTERNAL IO ; BUS TIMING FOR PAGED MEMORY ACCESS (CS3) EZ80_MEM_CYCLES .SET 3 ; MEMORY BUS CYCLES (1-15) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CYCLES EZ80_MEM_MIN_NS .SET 100 ; CALCULATE AT BOOT TIME THE REQUIRED W/S OR B/C, IF EZ80_WSMD_TYP = EZ80WSMD_CALC -EZ80_MEM_WS .SET 5 ; MEMORY WAIT STATES (0-7) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_WAIT -EZ80_MEM_MIN_WS .SET 0 ; MINIMUM WAIT STATES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC +EZ80_MEM_MIN_BC .SET 1 ; MINIMUM BUS CYCLES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC ; ; BUS TIMING FOR EXTERNAL I/O ACCESS (CS2) EZ80_IO_CYCLES .SET 4 ; IO BUS CYCLES (1-15) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CYCLES -EZ80_IO_WS .SET 7 ; IO WAIT STATES (0-7) TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_WAIT -EZ80_IO_MIN_NS .SET 250 ; CALCULATE AT BOOT TIME THE REQUIRED W/S OR B/C, IF EZ80_WSMD_TYP = EZ80WSMD_CALC - -; THE MINMUM W/S SHOULD BE AT LEAST 1 GREATER THAN THE HOLD TRIGGER COUNT PROGRAMMED WITHIN THE PLD OF THE -; EZ80 INTERFACE MODULE. SEE THE EZ80-CPU.PLD FILE WITHIN THE EZ80 FIRMWARE CODE BASE -EZ80_IO_MIN_WS .SET 7 ; MINIMUM WAIT STATES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC +EZ80_IO_MIN_NS .SET 250 ; CALCULATE AT BOOT TIME THE REQUIRED B/C, IF EZ80_WSMD_TYP = EZ80WSMD_CALC +EZ80_IO_MIN_BC .SET 4 ; MINIMUM BUS CYCLES TO APPLY, IF EZ80_WSMD_TYP = EZ80WSMD_CALC ; -; APPLY CYCLES, W/S OR CALCULATE CYCLES BASED ON DESIRED PERIOD -EZ80_WSMD_TYP .SET EZ80WSMD_CALC ; BUS WAIT STATE CONFIG: EZ80WSMD_[CALC|CYCLES|WAIT] +; APPLY BUS CYCLES OR CALCULATE CYCLES BASED ON DESIRED PERIOD +EZ80_WSMD_TYP .SET EZ80WSMD_CALC ; BUS WAIT STATE CONFIG: EZ80WSMD_[CALC|CYCLES] ; ; BUS TIMING FOR ON CHIP ROM ; diff --git a/Source/HBIOS/cfg_RCZ180.asm b/Source/HBIOS/cfg_RCZ180.asm index 9511969c..b311a722 100644 --- a/Source/HBIOS/cfg_RCZ180.asm +++ b/Source/HBIOS/cfg_RCZ180.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -97,7 +98,6 @@ CTCBASE .SET $88 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_RCZ280.asm b/Source/HBIOS/cfg_RCZ280.asm index 92ee15bd..f76a1ad6 100644 --- a/Source/HBIOS/cfg_RCZ280.asm +++ b/Source/HBIOS/cfg_RCZ280.asm @@ -71,6 +71,7 @@ INTMODE .SET 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -97,7 +98,6 @@ CTCBASE .SET $88 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_RCZ80.asm b/Source/HBIOS/cfg_RCZ80.asm index 77c0c6c3..e4ba044a 100644 --- a/Source/HBIOS/cfg_RCZ80.asm +++ b/Source/HBIOS/cfg_RCZ80.asm @@ -71,6 +71,7 @@ INTMODE .SET 1 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -96,8 +97,8 @@ CTCOSC .SET CPUOSC ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS -PCFCLK .SET 8 ; PCF CLOCK BASE -PCFTRNS .SET 90 ; PCF TRANSFER SPEED +PCFCLK .SET PCFCLK_8 ; PCF CLOCK BASE: PCFCLK_[3|443|6|8|12] +PCFTRNS .SET PCFTRNS_90 ; PCF TRANSFER SPEED: PCFTRNS_[90|45|11|15] ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_RPH.asm b/Source/HBIOS/cfg_RPH.asm index fad70b2e..ff9edaf0 100644 --- a/Source/HBIOS/cfg_RPH.asm +++ b/Source/HBIOS/cfg_RPH.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_RPH ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET 0 ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -97,7 +98,6 @@ CTCBASE .SET $B0 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_S100.asm b/Source/HBIOS/cfg_S100.asm index 4cbf7df1..99b503b7 100644 --- a/Source/HBIOS/cfg_S100.asm +++ b/Source/HBIOS/cfg_S100.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -97,7 +98,6 @@ CTCBASE .SET $88 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_SBC.asm b/Source/HBIOS/cfg_SBC.asm index 75fa135b..4b13996f 100644 --- a/Source/HBIOS/cfg_SBC.asm +++ b/Source/HBIOS/cfg_SBC.asm @@ -71,6 +71,7 @@ INTMODE .SET 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_SBC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPCL_RAM .SET $78 ; SBC MEM MGR RAM PAGE SELECT REG (WRITE ONLY) @@ -92,7 +93,6 @@ CTCTIMCH .SET 3 ; TIMER CHANNEL (0-3) CTCOSC .SET 614400 ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; @@ -348,6 +348,9 @@ AYMODE .SET AYMODE_SCG ; AY: DRIVER MODE: AYMODE_[SCG|N8|RCZ80|RCZ180|MSX|LINC| AY_FORCE .SET FALSE ; AY: BYPASS AUTO-DETECT, FORCED PRESENT ; SPKENABLE .SET FALSE ; SPK: ENABLE RTC LATCH IOBIT SOUND DRIVER (SPK.ASM) +SPKPORT .SET RTCIO ; SPK: THE PORT WITH THE SPEAKER IO BIT +SPKSHADOW .SET HB_RTCVAL ; SPK: THE SHADOW VALUE FOR THE PORT THAT HAS TO BE MAINTAINED +SPKMASK .SET %00000100 ; SPK: THE BIT MASK TO ACTUALLY TOGGLE ; DMAENABLE .SET FALSE ; DMA: ENABLE DMA DRIVER (DMA.ASM) DMABASE .SET $E0 ; DMA: DMA BASE ADDRESS diff --git a/Source/HBIOS/cfg_SCZ180.asm b/Source/HBIOS/cfg_SCZ180.asm index e4322a3f..86b4575a 100644 --- a/Source/HBIOS/cfg_SCZ180.asm +++ b/Source/HBIOS/cfg_SCZ180.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z180 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] RAMBIAS .SET ROMSIZE ; OFFSET OF START OF RAM IN PHYSICAL ADDRESS SPACE @@ -97,7 +98,6 @@ CTCBASE .SET $88 ; CTC BASE I/O ADDRESS CTCTIMER .SET FALSE ; ENABLE CTC PERIODIC TIMER ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_Z80RETRO.asm b/Source/HBIOS/cfg_Z80RETRO.asm index fe1bd88d..06ef9954 100644 --- a/Source/HBIOS/cfg_Z80RETRO.asm +++ b/Source/HBIOS/cfg_Z80RETRO.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $60 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -95,7 +96,6 @@ CTCTIMCH .SET 1 ; TIMER CHANNEL (0-3) CTCOSC .SET 7372800 ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_ZETA.asm b/Source/HBIOS/cfg_ZETA.asm index e12885d4..5417ebd8 100644 --- a/Source/HBIOS/cfg_ZETA.asm +++ b/Source/HBIOS/cfg_ZETA.asm @@ -71,6 +71,7 @@ INTMODE .SET 0 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_SBC ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPCL_RAM .SET $78 ; SBC MEM MGR RAM PAGE SELECT REG (WRITE ONLY) @@ -84,7 +85,6 @@ KIOBASE .SET $80 ; KIO BASE I/O ADDRESS CTCENABLE .SET FALSE ; ENABLE ZILOG CTC SUPPORT ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/cfg_ZETA2.asm b/Source/HBIOS/cfg_ZETA2.asm index 7981c6d5..15ac8659 100644 --- a/Source/HBIOS/cfg_ZETA2.asm +++ b/Source/HBIOS/cfg_ZETA2.asm @@ -71,6 +71,7 @@ INTMODE .SET 2 ; INTERRUPTS: 0=NONE, 1=MODE 1, 2=MODE 2, 3=MODE 3 (Z280) ; RAMSIZE .SET 512 ; SIZE OF RAM IN KB (MUST MATCH YOUR HARDWARE!!!) ROMSIZE .SET 512 ; SIZE OF ROM IN KB (MUST MATCH YOUR HARDWARE!!!) +ROMFONTS .SET TRUE ; LOAD FONTS FROM ROM APP_BNKS .SET $FF ; BANKS TO RESERVE FOR APP USE ($FF FOR AUTO SIZING) MEMMGR .SET MM_Z2 ; MEMORY MANAGER: MM_[SBC|Z2|N8|Z180|Z280|MBC|RPH|MON|EZ512] MPGSEL_0 .SET $78 ; Z2 MEM MGR BANK 0 PAGE SELECT REG (WRITE ONLY) @@ -95,7 +96,6 @@ CTCTIMCH .SET 1 ; TIMER CHANNEL (0-3) CTCOSC .SET 921600 ; CTC CLOCK FREQUENCY ; PCFENABLE .SET FALSE ; ENABLE PCF8584 I2C CONTROLLER -PCFBASE .SET $F0 ; PCF8584 BASE I/O ADDRESS ; EIPCENABLE .SET FALSE ; EIPC: ENABLE Z80 EIPC (Z84C15) INITIALIZATION ; diff --git a/Source/HBIOS/ch376-native/Makefile b/Source/HBIOS/ch376-native/Makefile new file mode 100644 index 00000000..95ab59ab --- /dev/null +++ b/Source/HBIOS/ch376-native/Makefile @@ -0,0 +1,107 @@ +SHELL := /bin/sh +SHELLFLAGS := -c -e -x +.ONESHELL: +MAKEFLAGS += --warn-undefined-variables +MAKEFLAGS += --no-builtin-rules +MAKEFLAGS += --always-make +ZCCRELFLAGS := -SO3 --max-allocs-per-node600000 --allow-unsafe-read --opt-code-speed + +SRC := ./source-doc/ +LIBS := -I./$(SRC)base-drv/ +ZCCFLAGS := +z80 -vn -startup=0 -clib=sdcc_iy -compiler=sdcc -Cs--std=c23 -Cs--Werror $(ZCCRELFLAGS) $(LIBS) + +ZCC_PATH := $(shell command -v zcc) +DOCKER_PATH := $(shell command -v docker) +ZCC := $(shell command -v zcc >/dev/null 2>&1 && echo zcc || echo 'docker run -w /host/${PWD} -v /:/host/ -u $(shell id -u ${USER}):$(shell id -g ${USER}) -t z88dk/z88dk:20250224 zcc') + +ifeq ($(ZCC_PATH),) + ifeq ($(DOCKER_PATH),) + .DEFAULT_GOAL := skip + else + $(info ZCC is set to use Docker to run zcc) + endif +else + $(info ZCC is set to $(ZCC_PATH)) +endif + +ASSDIR := ./ + +all: $(ASSDIR)base-drv.s $(ASSDIR)scsi-drv.s $(ASSDIR)ufi-drv.s $(ASSDIR)keyboard.s + +skip: + @echo "Unable to compile ch376 native to assembly. Install docker or z88dk." + exit 0 + +clean: + @rm -rf base-drv/*.s + rm -rf base-drv/*.asm + rm -rf scsi-drv/*.s + rm -rf scsi-drv/*.asm + rm -rf ufi-drv/*.s + rm -rf ufi-drv/*.asm + rm -rf keyboard/*.s + rm -rf keyboard/*.asm + rm ufi-drv.s + rm scsi-drv.s + rm base-drv.s + rm keyboard.s + +.PRECIOUS: $(ASSDIR)%.c.asm +$(ASSDIR)%.c.s: $(ASSDIR)%.c.asm + @mkdir -p $(dir $@) + echo "Converting $< to $@" + ${SRC}convert-for-uz80as.sh $< $@ + +define compile + @set -e + mkdir -p $(dir $@) + $(ZCC) $(ZCCFLAGS) --c-code-in-asm --assemble-only $< -o $@ + echo "Compiled $(notdir $@) from $(notdir $<)" +endef + +FIRMWARE_ALT = kyb-init ch376_init scsi-init ufi-init hbios-driver-storage + +define build_subsystem = +$$(ASSDIR)$(1).s: + @echo "Creating $(1).s" + echo "; Generated File -- not to be modify directly" > $$(ASSDIR)$(1).s + for dep in $$^; do + dep=$$$${dep#*/} + dep=$$$${dep#*/} + filename=$$$${dep##*/} + basename=$$$${filename%.*.*} + if echo "$(FIRMWARE_ALT)" | grep -w -q "$$$${basename}"; then + if [ -n "$$$${dep%%*.asm}" ]; then + echo '#include "'ch376-native/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s + else + echo '#include "'ch376-native/source-doc/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s + fi + else + echo '#IF (!CHNATIVEEZ80)' >> $$(ASSDIR)$(1).s + if [ -n "$$$${dep%%*.asm}" ]; then + echo '#include "'ch376-native/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s + else + echo '#include "'ch376-native/source-doc/$(1)/$$$${dep}'"' >> $$(ASSDIR)$(1).s + fi + echo '#ENDIF' >> $$(ASSDIR)$(1).s + fi + done + +$$(ASSDIR)$(1)/%.c.asm: $$(SRC)$(1)/%.c; $$(compile) +# $$(ASSDIR)$(1)/%.asm: $$(SRC)$(1)/%.asm; echo $$@ $$< + +$(1)_C_FILES := $$(wildcard $$(SRC)$(1)/*.c) +$(1)_ASM_FILES := $$(wildcard $$(SRC)$(1)/*.asm) +$(1)_C_S_FILES := $$(patsubst ./source-doc/%, ./%, $$($(1)_C_FILES:.c=.c.s)) +./$(1).s: $$($(1)_C_S_FILES) $$($(1)_ASM_FILES) +endef + +$(eval $(call build_subsystem,base-drv)) +$(eval $(call build_subsystem,scsi-drv)) +$(eval $(call build_subsystem,keyboard)) +$(eval $(call build_subsystem,ufi-drv)) + +.PHONY: format +format: SHELL:=/bin/bash +format: + @find \( -name "*.c" -o -name "*.h" \) -exec echo "formating {}" \; -exec clang-format -i {} \; diff --git a/Source/HBIOS/ch376-native/base-drv.asm b/Source/HBIOS/ch376-native/base-drv.asm new file mode 100644 index 00000000..008b11a5 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv.asm @@ -0,0 +1,106 @@ + +DELAY_FACTOR .EQU 640 + +CMD01_RD_USB_DATA0 .EQU $27 ; Read data block from current USB interrupt endpoint buffer or host endpoint receive buffer + ; output: length, data stream + +CMD10_WR_HOST_DATA .EQU $2C ; Write a data block to the send buffer of the USB host endpoint + ; input: length, data stream + +CH_CMD_RD_USB_DATA0 .EQU CMD01_RD_USB_DATA0 +CH_CMD_WR_HOST_DATA .EQU CMD10_WR_HOST_DATA + +; HL -> timeout +; returns +; L -> error code + +; --------------------------------- +; Function ch_wait_int_and_get_status +; --------------------------------- +_ch_wait_and_get_status + ld bc, DELAY_FACTOR + +keep_waiting: + ld a, $FF + in a, (_CH376_COMMAND_PORT & $FF) + rlca + jp nc, _ch_get_status + + dec bc + ld a, b + or c + jr nz, keep_waiting + + dec hl + ld a, h + or l + jr nz, _ch_wait_and_get_status + + call _delay + ld a, $FF + in a, (_CH376_COMMAND_PORT & $FF) + bit 4, a ; _CH376_COMMAND_PORT & PARA_STATE_BUSY + + ld l, $0C ; USB_ERR_CH376_BLOCKED; + ret nz + + ld l, $0D ; USB_ERR_CH376_TIMEOUT + ret + +; uint8_t ch_read_data(uint8_t *buffer) __sdcccall(1); +_ch_read_data: + push hl + ld l, CH_CMD_RD_USB_DATA0 + call _ch_command + pop hl + + call _delay + ld bc, _CH376_DATA_PORT + in a, (c) + + or a + ret z + + ld e, a + push af +read_block: + call _delay + in a, (c) + ld (hl), a + inc hl + dec e + jr nz, read_block + + pop af + ret + +;const uint8_t *ch_write_data(const uint8_t *buffer, uint8_t length) +_ch_write_data: + ld l, CH_CMD_WR_HOST_DATA + call _ch_command + + ld iy, 2 + add iy, sp + ld l, (iy+0) + ld h, (iy+1) + ld a, (iy+2) + + ld bc, _CH376_DATA_PORT + +; _CH376_DATA_PORT = length; + call _delay + out (c), a + + or a + ret z + + ld d, a +write_block: + call _delay + ld a, (hl) + out (c), a + inc hl + dec d + jr nz, write_block + + ret diff --git a/Source/HBIOS/ch376-native/base-drv.s b/Source/HBIOS/ch376-native/base-drv.s new file mode 100644 index 00000000..e534c158 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv.s @@ -0,0 +1,39 @@ +; Generated File -- not to be modify directly +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/ch376.c.s" +#ENDIF +#include "ch376-native/base-drv/ch376_init.c.s" +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/class_hub.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/critical-section.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/dev_transfers.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/enumerate.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/enumerate_hub.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/enumerate_storage.c.s" +#ENDIF +#include "ch376-native/base-drv/hbios-driver-storage.c.s" +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/protocol.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/transfers.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/usb-base-drv.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/usb_state.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/base-drv/work-area.c.s" +#ENDIF diff --git a/Source/HBIOS/ch376-native/base-drv/.gitignore b/Source/HBIOS/ch376-native/base-drv/.gitignore new file mode 100644 index 00000000..f4cb8488 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/.gitignore @@ -0,0 +1 @@ +*.asm diff --git a/Source/HBIOS/ch376-native/base-drv/ch376.c.s b/Source/HBIOS/ch376-native/base-drv/ch376.c.s new file mode 100644 index 00000000..0d55f1e0 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/ch376.c.s @@ -0,0 +1,769 @@ +; +; Generated from source-doc/base-drv/ch376.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/ch376.c:6: void ch_command(const uint8_t command) __z88dk_fastcall { +; --------------------------------- +; Function ch_command +; --------------------------------- +_ch_command: +;source-doc/base-drv/ch376.c:8: while ((CH376_COMMAND_PORT & PARA_STATE_BUSY) && --counter != 0) + ld b,$ff +l_ch_command_00102: + ld a, +((_CH376_COMMAND_PORT) / 256) + in a, (((_CH376_COMMAND_PORT) & $FF)) + bit 4, a + jr Z,l_ch_command_00104 + djnz l_ch_command_00102 +l_ch_command_00104: +;source-doc/base-drv/ch376.c:19: CH376_COMMAND_PORT = command; + ld a, l + ld bc,_CH376_COMMAND_PORT + out (c), a +;source-doc/base-drv/ch376.c:20: } + ret +;source-doc/base-drv/ch376.c:24: usb_error ch_long_get_status(void) { return ch_wait_and_get_status(5000); } +; --------------------------------- +; Function ch_long_get_status +; --------------------------------- +_ch_long_get_status: + ld hl,$1388 + jp _ch_wait_and_get_status +;source-doc/base-drv/ch376.c:26: usb_error ch_short_get_status(void) { return ch_wait_and_get_status(100); } +; --------------------------------- +; Function ch_short_get_status +; --------------------------------- +_ch_short_get_status: + ld hl,$0064 + jp _ch_wait_and_get_status +;source-doc/base-drv/ch376.c:28: usb_error ch_very_short_status(void) { return ch_wait_and_get_status(10); } +; --------------------------------- +; Function ch_very_short_status +; --------------------------------- +_ch_very_short_status: + ld hl,$000a + jp _ch_wait_and_get_status +;source-doc/base-drv/ch376.c:30: usb_error ch_get_status(void) { +; --------------------------------- +; Function ch_get_status +; --------------------------------- +_ch_get_status: +;source-doc/base-drv/ch376.c:31: ch_command(CH_CMD_GET_STATUS); + ld l,$22 + call _ch_command +;source-doc/base-drv/ch376.c:32: uint8_t ch_status = CH376_DATA_PORT; + ld a, +((_CH376_DATA_PORT) / 256) + in a, (((_CH376_DATA_PORT) & $FF)) +;source-doc/base-drv/ch376.c:34: if (ch_status >= USB_FILERR_MIN && ch_status <= USB_FILERR_MAX) + cp $41 + jr C,l_ch_get_status_00102 + cp $b5 + jr NC,l_ch_get_status_00102 +;source-doc/base-drv/ch376.c:35: return ch_status; + ld l, a + jr l_ch_get_status_00126 +l_ch_get_status_00102: +;source-doc/base-drv/ch376.c:37: if (ch_status == CH_CMD_RET_SUCCESS) + cp $51 + jr NZ,l_ch_get_status_00105 +;source-doc/base-drv/ch376.c:38: return USB_ERR_OK; + ld l,$00 + jr l_ch_get_status_00126 +l_ch_get_status_00105: +;source-doc/base-drv/ch376.c:40: if (ch_status == CH_USB_INT_SUCCESS) + cp $14 + jr NZ,l_ch_get_status_00107 +;source-doc/base-drv/ch376.c:41: return USB_ERR_OK; + ld l,$00 + jr l_ch_get_status_00126 +l_ch_get_status_00107: +;source-doc/base-drv/ch376.c:43: if (ch_status == CH_USB_INT_CONNECT) + cp $15 + jr NZ,l_ch_get_status_00109 +;source-doc/base-drv/ch376.c:44: return USB_INT_CONNECT; + ld l,$81 + jr l_ch_get_status_00126 +l_ch_get_status_00109: +;source-doc/base-drv/ch376.c:46: if (ch_status == CH_USB_INT_DISK_READ) + cp $1d + jr NZ,l_ch_get_status_00111 +;source-doc/base-drv/ch376.c:47: return USB_ERR_DISK_READ; + ld l,$1d + jr l_ch_get_status_00126 +l_ch_get_status_00111: +;source-doc/base-drv/ch376.c:49: if (ch_status == CH_USB_INT_DISK_WRITE) + cp $1e + jr NZ,l_ch_get_status_00113 +;source-doc/base-drv/ch376.c:50: return USB_ERR_DISK_WRITE; + ld l,$1e + jr l_ch_get_status_00126 +l_ch_get_status_00113: +;source-doc/base-drv/ch376.c:52: if (ch_status == CH_USB_INT_DISCONNECT) { + cp $16 + jr NZ,l_ch_get_status_00115 +;source-doc/base-drv/ch376.c:53: ch_cmd_set_usb_mode(5); + ld l,$05 + call _ch_cmd_set_usb_mode +;source-doc/base-drv/ch376.c:54: return USB_ERR_NO_DEVICE; + ld l,$05 + jr l_ch_get_status_00126 +l_ch_get_status_00115: +;source-doc/base-drv/ch376.c:57: if (ch_status == CH_USB_INT_BUF_OVER) + cp $17 + jr NZ,l_ch_get_status_00117 +;source-doc/base-drv/ch376.c:58: return USB_ERR_DATA_ERROR; + ld l,$04 + jr l_ch_get_status_00126 +l_ch_get_status_00117: +;source-doc/base-drv/ch376.c:60: ch_status &= $2F; + and $2f +;source-doc/base-drv/ch376.c:62: if (ch_status == $2A) + cp $2a + jr NZ,l_ch_get_status_00119 +;source-doc/base-drv/ch376.c:63: return USB_ERR_NAK; + ld l,$01 + jr l_ch_get_status_00126 +l_ch_get_status_00119: +;source-doc/base-drv/ch376.c:65: if (ch_status == $2E) + cp $2e + jr NZ,l_ch_get_status_00121 +;source-doc/base-drv/ch376.c:66: return USB_ERR_STALL; + ld l,$02 + jr l_ch_get_status_00126 +l_ch_get_status_00121: +;source-doc/base-drv/ch376.c:68: ch_status &= $23; + and $23 +;source-doc/base-drv/ch376.c:70: if (ch_status == $20) + cp $20 + jr NZ,l_ch_get_status_00123 +;source-doc/base-drv/ch376.c:71: return USB_ERR_TIMEOUT; + ld l,$03 + jr l_ch_get_status_00126 +l_ch_get_status_00123: +;source-doc/base-drv/ch376.c:73: if (ch_status == $23) + sub $23 + jr NZ,l_ch_get_status_00125 +;source-doc/base-drv/ch376.c:74: return USB_TOKEN_OUT_OF_SYNC; + ld l,$07 + jr l_ch_get_status_00126 +l_ch_get_status_00125: +;source-doc/base-drv/ch376.c:76: return USB_ERR_UNEXPECTED_STATUS_FROM_; + ld l,$08 +l_ch_get_status_00126: +;source-doc/base-drv/ch376.c:77: } + ret +;source-doc/base-drv/ch376.c:79: void ch_cmd_reset_all(void) { ch_command(CH_CMD_RESET_ALL); } +; --------------------------------- +; Function ch_cmd_reset_all +; --------------------------------- +_ch_cmd_reset_all: + ld l,$05 + jp _ch_command +;source-doc/base-drv/ch376.c:98: uint8_t ch_probe(void) { +; --------------------------------- +; Function ch_probe +; --------------------------------- +_ch_probe: + push ix + ld ix,0 + add ix,sp + dec sp +;source-doc/base-drv/ch376.c:100: do { + ld (ix-1),$05 +l_ch_probe_00103: +;source-doc/base-drv/ch376.c:83: ch_command(CH_CMD_CHECK_EXIST); + ld l,$06 + call _ch_command +;source-doc/base-drv/ch376.c:84: CH376_DATA_PORT = (uint8_t)~$55; + ld a,$aa + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/ch376.c:85: delay(); + call _delay +;source-doc/base-drv/ch376.c:86: complement = CH376_DATA_PORT; + ld a, +((_CH376_DATA_PORT) / 256) + in a, (((_CH376_DATA_PORT) & $FF)) +;source-doc/base-drv/ch376.c:87: return complement == $55; + sub $55 + jr NZ,l_ch_probe_00102 +;source-doc/base-drv/ch376.c:101: if (ch_cmd_check_exist()) +;source-doc/base-drv/ch376.c:102: return true; + ld l,$01 + jr l_ch_probe_00107 +l_ch_probe_00102: +;source-doc/base-drv/ch376.c:104: delay_medium(); + call _delay_medium +;source-doc/base-drv/ch376.c:105: } while (--i != 0); + dec (ix-1) + jr NZ,l_ch_probe_00103 +;source-doc/base-drv/ch376.c:107: return false; + ld l,$00 +l_ch_probe_00107: +;source-doc/base-drv/ch376.c:108: } + inc sp + pop ix + ret +;source-doc/base-drv/ch376.c:110: usb_error ch_cmd_set_usb_mode(const uint8_t mode) __z88dk_fastcall { +; --------------------------------- +; Function ch_cmd_set_usb_mode +; --------------------------------- +_ch_cmd_set_usb_mode: + ld c, l +;source-doc/base-drv/ch376.c:111: uint8_t result = 0; + ld b,$00 +;source-doc/base-drv/ch376.c:113: CH376_COMMAND_PORT = CH_CMD_SET_USB_MODE; + ld a,$15 + push bc + ld bc,_CH376_COMMAND_PORT + out (c), a +;source-doc/base-drv/ch376.c:114: delay(); + call _delay + pop bc +;source-doc/base-drv/ch376.c:115: CH376_DATA_PORT = mode; + ld a, c + push bc + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/ch376.c:116: delay(); + call _delay + pop bc +;source-doc/base-drv/ch376.c:120: while (result != CH_CMD_RET_SUCCESS && result != CH_CMD_RET_ABORT && --count != 0) { + ld c,$7f +l_ch_cmd_set_usb_mode_00103: + ld a, b + sub $51 + jr NZ,l_ch_cmd_set_usb_mode_00146 + ld a,$01 + jr l_ch_cmd_set_usb_mode_00147 +l_ch_cmd_set_usb_mode_00146: + xor a +l_ch_cmd_set_usb_mode_00147: + ld e,a + bit 0,a + jr NZ,l_ch_cmd_set_usb_mode_00105 + ld a, b + sub $5f + jr Z,l_ch_cmd_set_usb_mode_00105 + dec c + jr Z,l_ch_cmd_set_usb_mode_00105 +;source-doc/base-drv/ch376.c:121: result = CH376_DATA_PORT; + ld a, +((_CH376_DATA_PORT) / 256) + in a, (((_CH376_DATA_PORT) & $FF)) + ld b, a +;source-doc/base-drv/ch376.c:122: delay(); + push bc + call _delay + pop bc + jr l_ch_cmd_set_usb_mode_00103 +l_ch_cmd_set_usb_mode_00105: +;source-doc/base-drv/ch376.c:125: return (result == CH_CMD_RET_SUCCESS) ? USB_ERR_OK : USB_ERR_FAIL; + ld a, e + or a + jr Z,l_ch_cmd_set_usb_mode_00108 + ld l,$00 + jr l_ch_cmd_set_usb_mode_00109 +l_ch_cmd_set_usb_mode_00108: + ld l,$0e +l_ch_cmd_set_usb_mode_00109: +;source-doc/base-drv/ch376.c:126: } + ret +;source-doc/base-drv/ch376.c:128: uint8_t ch_cmd_get_ic_version(void) { +; --------------------------------- +; Function ch_cmd_get_ic_version +; --------------------------------- +_ch_cmd_get_ic_version: +;source-doc/base-drv/ch376.c:129: ch_command(CH_CMD_GET_IC_VER); + ld l,$01 + call _ch_command +;source-doc/base-drv/ch376.c:130: return CH376_DATA_PORT & $1f; + ld a, +((_CH376_DATA_PORT) / 256) + in a, (((_CH376_DATA_PORT) & $FF)) + and $1f + ld l, a +;source-doc/base-drv/ch376.c:131: } + ret +;source-doc/base-drv/ch376.c:133: void ch_issue_token(const uint8_t toggle_bit, const uint8_t endpoint, const ch376_pid pid) { +; --------------------------------- +; Function ch_issue_token +; --------------------------------- +_ch_issue_token: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/ch376.c:134: ch_command(CH_CMD_ISSUE_TKN_X); + ld l,$4e + call _ch_command +;source-doc/base-drv/ch376.c:135: CH376_DATA_PORT = toggle_bit; + ld a,(ix+4) + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/ch376.c:136: CH376_DATA_PORT = endpoint << 4 | pid; + ld a,(ix+5) + add a, a + add a, a + add a, a + add a, a + or (ix+6) + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/ch376.c:137: } + pop ix + ret +;source-doc/base-drv/ch376.c:139: void ch_issue_token_in(const endpoint_param *const endpoint) __z88dk_fastcall { +; --------------------------------- +; Function ch_issue_token_in +; --------------------------------- +_ch_issue_token_in: +;source-doc/base-drv/ch376.c:140: ch_issue_token(endpoint->toggle ? $80 : $00, endpoint->number, CH_PID_IN); + ld e,l + ld d,h + ld a, (hl) + rrca + and $07 + ld b, a + ex de, hl + ld a, (hl) + and $01 + jr Z,l_ch_issue_token_in_00103 + ld a,$80 + jr l_ch_issue_token_in_00104 +l_ch_issue_token_in_00103: + xor a +l_ch_issue_token_in_00104: + ld h,$09 + ld l,b + push hl + push af + inc sp + call _ch_issue_token + pop af + inc sp +;source-doc/base-drv/ch376.c:141: } + ret +;source-doc/base-drv/ch376.c:143: void ch_issue_token_out(const endpoint_param *const endpoint) __z88dk_fastcall { +; --------------------------------- +; Function ch_issue_token_out +; --------------------------------- +_ch_issue_token_out: +;source-doc/base-drv/ch376.c:144: ch_issue_token(endpoint->toggle ? $40 : $00, endpoint->number, CH_PID_OUT); + ld e,l + ld d,h + ld a, (hl) + rrca + and $07 + ld b, a + ex de, hl + ld a, (hl) + and $01 + jr Z,l_ch_issue_token_out_00103 + ld a,$40 + jr l_ch_issue_token_out_00104 +l_ch_issue_token_out_00103: + xor a +l_ch_issue_token_out_00104: + ld h,$01 + ld l,b + push hl + push af + inc sp + call _ch_issue_token + pop af + inc sp +;source-doc/base-drv/ch376.c:145: } + ret +;source-doc/base-drv/ch376.c:147: void ch_issue_token_out_ep0(void) { ch_issue_token($40, 0, CH_PID_OUT); } +; --------------------------------- +; Function ch_issue_token_out_ep0 +; --------------------------------- +_ch_issue_token_out_ep0: + ld a,$01 + push af + inc sp + xor a + ld d,a + ld e,$40 + push de + call _ch_issue_token + pop af + inc sp + ret +;source-doc/base-drv/ch376.c:149: void ch_issue_token_in_ep0(void) { ch_issue_token($80, 0, CH_PID_IN); } +; --------------------------------- +; Function ch_issue_token_in_ep0 +; --------------------------------- +_ch_issue_token_in_ep0: + ld a,$09 + push af + inc sp + xor a + ld d,a + ld e,$80 + push de + call _ch_issue_token + pop af + inc sp + ret +;source-doc/base-drv/ch376.c:151: void ch_issue_token_setup(void) { ch_issue_token(0, 0, CH_PID_SETUP); } +; --------------------------------- +; Function ch_issue_token_setup +; --------------------------------- +_ch_issue_token_setup: + ld a,$0d + push af + inc sp + xor a + push af + inc sp + xor a + push af + inc sp + call _ch_issue_token + pop af + inc sp + ret +;source-doc/base-drv/ch376.c:153: usb_error ch_data_in_transfer(uint8_t *buffer, int16_t buffer_size, endpoint_param *const endpoint) { +; --------------------------------- +; Function ch_data_in_transfer +; --------------------------------- +_ch_data_in_transfer: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/ch376.c:157: if (buffer_size == 0) + ld a,(ix+7) + or (ix+6) + jr NZ,l_ch_data_in_transfer_00102 +;source-doc/base-drv/ch376.c:158: return USB_ERR_OK; + ld l,$00 + jp l_ch_data_in_transfer_00111 +l_ch_data_in_transfer_00102: +;source-doc/base-drv/ch376.c:160: USB_MODULE_LEDS = $01; + ld a,$01 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:161: do { + ld c,(ix+8) + ld b,(ix+9) +l_ch_data_in_transfer_00107: +;source-doc/base-drv/ch376.c:162: ch_issue_token_in(endpoint); + ld l,c + ld h,b + push hl + call _ch_issue_token_in +;source-doc/base-drv/ch376.c:164: result = ch_long_get_status(); + call _ch_long_get_status + ld a, l + pop bc + ld l, a +;source-doc/base-drv/ch376.c:165: CHECK(result); + or a + jr NZ,l_ch_data_in_transfer_00110 +;source-doc/base-drv/ch376.c:167: endpoint->toggle = !endpoint->toggle; + ld e, c + ld d, b + ld l, e + ld h, d + ld a, (hl) + and $01 + xor $01 + and $01 + ld l, a + ld a, (de) + and $fe + or l + ld (de), a +;source-doc/base-drv/ch376.c:169: count = ch_read_data(buffer); + push bc + ld l,(ix+4) + ld h,(ix+5) + call _ch_read_data + ld e, a + pop bc +;source-doc/base-drv/ch376.c:171: if (count == 0) { + ld a, e +;source-doc/base-drv/ch376.c:172: USB_MODULE_LEDS = $00; + or a + jr NZ,l_ch_data_in_transfer_00106 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:173: return USB_ERR_DATA_ERROR; + ld l,$04 + jr l_ch_data_in_transfer_00111 +l_ch_data_in_transfer_00106: +;source-doc/base-drv/ch376.c:176: buffer += count; + ld a,(ix+4) + add a, e + ld (ix+4),a + jr NC,l_ch_data_in_transfer_00148 + inc (ix+5) +l_ch_data_in_transfer_00148: +;source-doc/base-drv/ch376.c:177: buffer_size -= count; + ld d,$00 + ld a,(ix+6) + sub e + ld (ix+6),a + ld a,(ix+7) + sbc a, d + ld (ix+7),a +;source-doc/base-drv/ch376.c:178: } while (buffer_size > 0); + xor a + cp (ix+6) + sbc a,(ix+7) + jp PO, l_ch_data_in_transfer_00149 + xor $80 +l_ch_data_in_transfer_00149: + jp M, l_ch_data_in_transfer_00107 +;source-doc/base-drv/ch376.c:180: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:181: return USB_ERR_OK; + ld l,$00 + jr l_ch_data_in_transfer_00111 +;source-doc/base-drv/ch376.c:183: done: +l_ch_data_in_transfer_00110: +;source-doc/base-drv/ch376.c:184: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:185: return result; +l_ch_data_in_transfer_00111: +;source-doc/base-drv/ch376.c:186: } + pop ix + ret +;source-doc/base-drv/ch376.c:189: usb_error ch_data_in_transfer_n(uint8_t *const buffer, uint8_t *const buffer_size, endpoint_param *const endpoint) { +; --------------------------------- +; Function ch_data_in_transfer_n +; --------------------------------- +_ch_data_in_transfer_n: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/ch376.c:193: USB_MODULE_LEDS = $01; + ld a,$01 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:195: ch_issue_token_in(endpoint); + ld l,(ix+8) + ld h,(ix+9) + call _ch_issue_token_in +;source-doc/base-drv/ch376.c:197: CHECK(ch_long_get_status()); + call _ch_long_get_status + ld a,l + or a + jr NZ,l_ch_data_in_transfer_n_00103 +;source-doc/base-drv/ch376.c:199: endpoint->toggle = !endpoint->toggle; + ld l,(ix+8) + ld h,(ix+9) + ld a, (hl) + and $01 + xor $01 + and $01 + ld c, a + ld a, (hl) + and $fe + or c + ld (hl), a +;source-doc/base-drv/ch376.c:201: count = ch_read_data(buffer); + ld l,(ix+4) + ld h,(ix+5) + call _ch_read_data +;source-doc/base-drv/ch376.c:203: *buffer_size = count; + ld c,(ix+6) + ld b,(ix+7) + ld (bc), a +;source-doc/base-drv/ch376.c:205: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:207: return USB_ERR_OK; + ld l,$00 + jr l_ch_data_in_transfer_n_00104 +;source-doc/base-drv/ch376.c:208: done: +l_ch_data_in_transfer_n_00103: +;source-doc/base-drv/ch376.c:209: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:210: return result; +l_ch_data_in_transfer_n_00104: +;source-doc/base-drv/ch376.c:211: } + pop ix + ret +;source-doc/base-drv/ch376.c:213: usb_error ch_data_out_transfer(const uint8_t *buffer, int16_t buffer_length, endpoint_param *const endpoint) { +; --------------------------------- +; Function ch_data_out_transfer +; --------------------------------- +_ch_data_out_transfer: + push ix + ld ix,0 + add ix,sp + dec sp +;source-doc/base-drv/ch376.c:216: const uint8_t max_packet_size = calc_max_packet_size(endpoint->max_packet_sizex); + ld c,(ix+8) + ld b,(ix+9) + ld e, c + ld d, b + inc de + ld a, (de) + ld (ix-1),a +;source-doc/base-drv/ch376.c:218: USB_MODULE_LEDS = $02; + ld a,$02 + push bc + ld bc,_USB_MODULE_LEDS + out (c), a + pop bc +;source-doc/base-drv/ch376.c:220: while (buffer_length > 0) { +l_ch_data_out_transfer_00103: + xor a + cp (ix+6) + sbc a,(ix+7) + jp PO, l_ch_data_out_transfer_00139 + xor $80 +l_ch_data_out_transfer_00139: + jp P, l_ch_data_out_transfer_00105 +;source-doc/base-drv/ch376.c:221: const uint8_t size = max_packet_size < buffer_length ? max_packet_size : buffer_length; + ld d,(ix-1) + ld e,$00 + ld a, d + sub (ix+6) + ld a, e + sbc a,(ix+7) + jp PO, l_ch_data_out_transfer_00140 + xor $80 +l_ch_data_out_transfer_00140: + jp P, l_ch_data_out_transfer_00109 + jr l_ch_data_out_transfer_00110 +l_ch_data_out_transfer_00109: + ld d,(ix+6) + ld e,(ix+7) +l_ch_data_out_transfer_00110: +;source-doc/base-drv/ch376.c:222: buffer = ch_write_data(buffer, size); + push bc + push de + push de + inc sp + ld l,(ix+4) + ld h,(ix+5) + push hl + call _ch_write_data + pop af + inc sp + pop de + pop bc + ld (ix+4),l + ld (ix+5),h +;source-doc/base-drv/ch376.c:223: buffer_length -= size; + ld e,$00 + ld a,(ix+6) + sub d + ld (ix+6),a + ld a,(ix+7) + sbc a, e + ld (ix+7),a +;source-doc/base-drv/ch376.c:224: ch_issue_token_out(endpoint); + ld l,c + ld h,b + push hl + call _ch_issue_token_out +;source-doc/base-drv/ch376.c:226: CHECK(ch_long_get_status()); + call _ch_long_get_status + ld a, l + pop bc + ld l, a + or a + jr NZ,l_ch_data_out_transfer_00106 +;source-doc/base-drv/ch376.c:228: endpoint->toggle = !endpoint->toggle; + ld e, c + ld d, b + ld l, e + ld h, d + ld a, (hl) + and $01 + xor $01 + and $01 + ld l, a + ld a, (de) + and $fe + or l + ld (de), a + jr l_ch_data_out_transfer_00103 +l_ch_data_out_transfer_00105: +;source-doc/base-drv/ch376.c:231: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:232: return USB_ERR_OK; + ld l,$00 + jr l_ch_data_out_transfer_00107 +;source-doc/base-drv/ch376.c:234: done: +l_ch_data_out_transfer_00106: +;source-doc/base-drv/ch376.c:235: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/ch376.c:236: return result; +l_ch_data_out_transfer_00107: +;source-doc/base-drv/ch376.c:237: } + inc sp + pop ix + ret +;source-doc/base-drv/ch376.c:239: void ch_set_usb_address(const uint8_t device_address) __z88dk_fastcall { +; --------------------------------- +; Function ch_set_usb_address +; --------------------------------- +_ch_set_usb_address: +;source-doc/base-drv/ch376.c:240: ch_command(CH_CMD_SET_USB_ADDR); + push hl + ld l,$13 + call _ch_command + pop hl +;source-doc/base-drv/ch376.c:241: CH376_DATA_PORT = device_address; + ld a, l + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/ch376.c:242: } + ret diff --git a/Source/HBIOS/ch376-native/base-drv/ch376_init.c.s b/Source/HBIOS/ch376-native/base-drv/ch376_init.c.s new file mode 100644 index 00000000..09682ce4 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/ch376_init.c.s @@ -0,0 +1,319 @@ +; +; Generated from source-doc/base-drv/ch376_init.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/ch376_init.c:4: static uint16_t wait_for_state(const uint8_t loop_counter, uint8_t state, const uint8_t desired_state) __sdcccall(1) { +; --------------------------------- +; Function wait_for_state +; --------------------------------- +_wait_for_state: + push ix + ld ix,0 + add ix,sp + dec sp + ld (ix-1),a +;source-doc/base-drv/ch376_init.c:5: uint16_t r = state; + ld c,l + ld e,l +;source-doc/base-drv/ch376_init.c:7: for (uint8_t i = 0; i < loop_counter; i++) { + ld d,$00 + ld b,d +l_wait_for_state_00108: + ld a, b + sub (ix-1) + jr NC,l_wait_for_state_00106 +;source-doc/base-drv/ch376_init.c:8: if (state == desired_state) + ld a,(ix+4) + sub c + jr Z,l_wait_for_state_00106 +;source-doc/base-drv/ch376_init.c:11: if (i & 1) + bit 0, b + jr Z,l_wait_for_state_00104 +;source-doc/base-drv/ch376_init.c:12: print_string("\b $"); + push bc + ld hl,ch376_init_str_0 + call _print_string + pop bc + jr l_wait_for_state_00105 +l_wait_for_state_00104: +;source-doc/base-drv/ch376_init.c:14: print_string("\b*$"); + push bc + ld hl,ch376_init_str_1 + call _print_string + pop bc +l_wait_for_state_00105: +;source-doc/base-drv/ch376_init.c:16: r = usb_init(state); + push bc + ld l, c + call _usb_init + ex de, hl + pop bc +;source-doc/base-drv/ch376_init.c:17: state = r & 255; + ld c, e +;source-doc/base-drv/ch376_init.c:7: for (uint8_t i = 0; i < loop_counter; i++) { + inc b + jr l_wait_for_state_00108 +l_wait_for_state_00106: +;source-doc/base-drv/ch376_init.c:20: return r; +;source-doc/base-drv/ch376_init.c:21: } + inc sp + pop ix + pop hl + inc sp + jp (hl) +ch376_init_str_0: + DEFB $08 + DEFM " $" + DEFB $00 +ch376_init_str_1: + DEFB $08 + DEFM "*$" + DEFB $00 +;source-doc/base-drv/ch376_init.c:33: static void _chnative_init(bool forced) { +; --------------------------------- +; Function _chnative_init +; --------------------------------- +__chnative_init: + push ix + ld ix,0 + add ix,sp + dec sp +;source-doc/base-drv/ch376_init.c:36: const uint8_t loop_counter = forced ? 40 : 5; + bit 0,(ix+4) + jr Z,l__chnative_init_00113 + ld a,$28 + jr l__chnative_init_00114 +l__chnative_init_00113: + ld a,$05 +l__chnative_init_00114: + ld (ix-1),a +;source-doc/base-drv/ch376_init.c:38: print_string("\r\nCH376: IO=0x$"); + ld hl,ch376_init_str_2 + call _print_string +;source-doc/base-drv/ch376_init.c:39: print_hex((uint8_t)&CH376_DAT_PORT_ADDR); + ld l, +((_CH376_DAT_PORT_ADDR) & $FF) + call _print_hex +;source-doc/base-drv/ch376_init.c:40: print_string(comma_0_x_dollar); + ld hl,_comma_0_x_dollar + call _print_string +;source-doc/base-drv/ch376_init.c:41: print_hex((uint8_t)&CH376_CMD_PORT_ADDR); + ld l, +((_CH376_CMD_PORT_ADDR) & $FF) + call _print_hex +;source-doc/base-drv/ch376_init.c:42: print_string(comma_0_x_dollar); + ld hl,_comma_0_x_dollar + call _print_string +;source-doc/base-drv/ch376_init.c:43: print_hex((uint8_t)&USB_MOD_LEDS_ADDR); + ld l, +((_USB_MOD_LEDS_ADDR) & $FF) + call _print_hex +;source-doc/base-drv/ch376_init.c:44: print_string(" *$"); + ld hl,ch376_init_str_3 + call _print_string +;source-doc/base-drv/ch376_init.c:46: r = wait_for_state(loop_counter, state, 1); + ld a,$01 + push af + inc sp + ld l,$00 + ld a,(ix-1) + call _wait_for_state +;source-doc/base-drv/ch376_init.c:47: state = r & 255; +;source-doc/base-drv/ch376_init.c:49: print_string("\bPRESENT (VER $"); + push de + ld hl,ch376_init_str_4 + call _print_string + pop de +;source-doc/base-drv/ch376_init.c:51: r = usb_init(state); + ld l, e + call _usb_init + ex de, hl +;source-doc/base-drv/ch376_init.c:52: state = r & 255; + ld c, e +;source-doc/base-drv/ch376_init.c:53: if (state != 2) { + ld a, c + sub $02 + jr Z,l__chnative_init_00102 +;source-doc/base-drv/ch376_init.c:54: print_string("\rCH376: $"); + ld hl,ch376_init_str_5 + call _print_string +;source-doc/base-drv/ch376_init.c:55: print_string("VERSION FAILURE\r\n$"); + ld hl,ch376_init_str_6 + call _print_string +;source-doc/base-drv/ch376_init.c:56: return; + jr l__chnative_init_00111 +l__chnative_init_00102: +;source-doc/base-drv/ch376_init.c:59: print_hex(r >> 8); + push bc + ld l, d + call _print_hex +;source-doc/base-drv/ch376_init.c:60: print_string(ch376_driver_version); + ld hl,_ch376_driver_version + call _print_string +;source-doc/base-drv/ch376_init.c:62: print_string("USB: *$"); + ld hl,ch376_init_str_7 + call _print_string + pop bc +;source-doc/base-drv/ch376_init.c:64: r = wait_for_state(loop_counter, state, 3); + ld a,$03 + push af + inc sp + ld l, c + ld a,(ix-1) + call _wait_for_state +;source-doc/base-drv/ch376_init.c:65: state = r & 255; +;source-doc/base-drv/ch376_init.c:67: if (state == 2) { + ld a, e + sub $02 + jr NZ,l__chnative_init_00104 +;source-doc/base-drv/ch376_init.c:68: print_string("\bDISCONNECTED$"); + ld hl,ch376_init_str_8 + call _print_string +;source-doc/base-drv/ch376_init.c:69: return; + jr l__chnative_init_00111 +l__chnative_init_00104: +;source-doc/base-drv/ch376_init.c:72: print_string("\bCONNECTED$"); + push de + ld hl,ch376_init_str_9 + call _print_string + pop de +;source-doc/base-drv/ch376_init.c:75: r = usb_init(state); + ld l, e + call _usb_init + ex de, hl +;source-doc/base-drv/ch376_init.c:76: state = r & 255; + ld c, e +;source-doc/base-drv/ch376_init.c:78: for (uint8_t i = 0; i < loop_counter; i++) { + ld b,$00 +l__chnative_init_00109: + ld a, b + sub (ix-1) + jr NC,l__chnative_init_00111 +;source-doc/base-drv/ch376_init.c:79: if (r >> 8 != 0) + ld a,$00 + or d + jr NZ,l__chnative_init_00111 +;source-doc/base-drv/ch376_init.c:82: print_string(".$"); + push bc + ld hl,ch376_init_str_10 + call _print_string + pop bc +;source-doc/base-drv/ch376_init.c:83: r = usb_init(state); + push bc + ld l, c + call _usb_init + ex de, hl + pop bc +;source-doc/base-drv/ch376_init.c:84: state = r & 255; + ld c, e +;source-doc/base-drv/ch376_init.c:78: for (uint8_t i = 0; i < loop_counter; i++) { + inc b + jr l__chnative_init_00109 +l__chnative_init_00111: +;source-doc/base-drv/ch376_init.c:86: } + inc sp + pop ix + ret +_comma_0_x_dollar: + DEFB +$20 + DEFB +$30 + DEFB +$78 + DEFB +$24 +ch376_init_str_2: + DEFB $0d + DEFB $0a + DEFM "CH376: IO=0x$" + DEFB $00 +ch376_init_str_3: + DEFM " *$" + DEFB $00 +ch376_init_str_4: + DEFB $08 + DEFM "PRESENT (VER $" + DEFB $00 +ch376_init_str_5: + DEFB $0d + DEFM "CH376: $" + DEFB $00 +ch376_init_str_6: + DEFM "VERSION FAILURE" + DEFB $0d + DEFB $0a + DEFM "$" + DEFB $00 +ch376_init_str_7: + DEFM "USB: *$" + DEFB $00 +ch376_init_str_8: + DEFB $08 + DEFM "DISCONNECTED$" + DEFB $00 +ch376_init_str_9: + DEFB $08 + DEFM "CONNECTED$" + DEFB $00 +ch376_init_str_10: + DEFM ".$" + DEFB $00 +;source-doc/base-drv/ch376_init.c:88: void chnative_init_force(void) { _chnative_init(true); } +; --------------------------------- +; Function chnative_init_force +; --------------------------------- +_chnative_init_force: + ld a,$01 + push af + inc sp + call __chnative_init + inc sp + ret +;source-doc/base-drv/ch376_init.c:90: void chnative_init(void) { _chnative_init(false); } +; --------------------------------- +; Function chnative_init +; --------------------------------- +_chnative_init: + xor a + push af + inc sp + call __chnative_init + inc sp + ret diff --git a/Source/HBIOS/ch376-native/base-drv/class_hub.c.s b/Source/HBIOS/ch376-native/base-drv/class_hub.c.s new file mode 100644 index 00000000..039abf0f --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/class_hub.c.s @@ -0,0 +1,85 @@ +; +; Generated from source-doc/base-drv/class_hub.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/class_hub.c:7: usb_error hub_get_descriptor(const device_config_hub *const hub_config, hub_descriptor *const hub_description) __sdcccall(1) { +; --------------------------------- +; Function hub_get_descriptor +; --------------------------------- +_hub_get_descriptor: +;source-doc/base-drv/class_hub.c:8: return usb_control_transfer(&cmd_get_hub_descriptor, hub_description, hub_config->address, hub_config->max_packet_size); + ld a,l + ld c,h + inc hl + ld b, (hl) + ld l, a + ld h, c + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld c, a + push bc + push de + ld hl,_cmd_get_hub_descriptor + push hl + call _usb_control_transfer + pop af + pop af + pop af + ld a, l +;source-doc/base-drv/class_hub.c:9: } + ret +_cmd_get_hub_descriptor: + DEFB +$a0 + DEFB +$06 + DEFB +$00 + DEFB +$29 + DEFB +$00 + DEFB +$00 + DEFW +$0008 diff --git a/Source/HBIOS/ch376-native/base-drv/critical-section.c.s b/Source/HBIOS/ch376-native/base-drv/critical-section.c.s new file mode 100644 index 00000000..b1e25189 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/critical-section.c.s @@ -0,0 +1,67 @@ +; +; Generated from source-doc/base-drv/critical-section.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_in_critical_usb_section: + DEFS 1 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/critical-section.c:6: void critical_begin() { in_critical_usb_section++; } +; --------------------------------- +; Function critical_begin +; --------------------------------- +_critical_begin: + ld hl,_in_critical_usb_section + inc (hl) + ret +;source-doc/base-drv/critical-section.c:8: void critical_end() { in_critical_usb_section--; } +; --------------------------------- +; Function critical_end +; --------------------------------- +_critical_end: + ld hl,_in_critical_usb_section + dec (hl) + ret +_in_critical_usb_section: + DEFB +$00 diff --git a/Source/HBIOS/ch376-native/base-drv/dev_transfers.c.s b/Source/HBIOS/ch376-native/base-drv/dev_transfers.c.s new file mode 100644 index 00000000..dfe3c49c --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/dev_transfers.c.s @@ -0,0 +1,449 @@ +; +; Generated from source-doc/base-drv/dev_transfers.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/dev_transfers.c:23: * See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer +; --------------------------------- +; Function usbdev_control_transfer +; --------------------------------- +_usbdev_control_transfer: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/dev_transfers.c:24: * + ld l,(ix+4) + ld h,(ix+5) + ld e,l + ld d,h + inc hl + ld b, (hl) + ex de, hl + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld e,(ix+8) + ld d,(ix+9) + ld c,a + push bc + push de + ld l,(ix+6) + ld h,(ix+7) + push hl + call _usb_control_transfer + pop af + pop af + pop af +;source-doc/base-drv/dev_transfers.c:25: * @param device the usb device + pop ix + ret +;source-doc/base-drv/dev_transfers.c:27: * @param buffer Pointer of data to send or receive into +; --------------------------------- +; Function usbdev_blk_out_trnsfer +; --------------------------------- +_usbdev_blk_out_trnsfer: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/dev_transfers.c:30: usb_error usbdev_control_transfer(device_config *const device, const setup_packet *const cmd_packet, uint8_t *const buffer) { + ld c,(ix+4) + ld b,(ix+5) + ld e, c + ld d, b + inc de + inc de + inc de +;source-doc/base-drv/dev_transfers.c:32: } + pop hl + ld l,c + ld h,b + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + push bc + push de + push de + push af + inc sp + ld l,(ix+8) + ld h,(ix+9) + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + call _usb_data_out_transfer + pop af + pop af + pop af + inc sp + pop de + pop bc +;source-doc/base-drv/dev_transfers.c:34: usb_error usbdev_blk_out_trnsfer(device_config *const dev, const uint8_t *const buffer, const uint16_t buffer_size) { + ld a, l + sub $02 + jr NZ,l_usbdev_blk_out_trnsfer_00102 +;source-doc/base-drv/dev_transfers.c:35: usb_error result; + inc bc + ld a, (bc) + ld b, a + pop hl + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + ld c, a + ld l, e + ld h, d + ld a, (hl) + rrca + and $07 + push de + push bc + inc sp + ld h, c + ld l,a + push hl + call _usbtrn_clr_ep_halt + pop af + inc sp + pop de +;source-doc/base-drv/dev_transfers.c:36: + ex de, hl + res 0, (hl) +;source-doc/base-drv/dev_transfers.c:37: endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_OUT]; + ld l,$02 +;source-doc/base-drv/dev_transfers.c:43: endpoint->toggle = 0; +l_usbdev_blk_out_trnsfer_00102: +;source-doc/base-drv/dev_transfers.c:44: return USB_ERR_STALL; + ld sp, ix + pop ix + ret +;source-doc/base-drv/dev_transfers.c:46: +; --------------------------------- +; Function usbdev_bulk_in_transfer +; --------------------------------- +_usbdev_bulk_in_transfer: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/dev_transfers.c:49: done: + ld c,(ix+4) + ld b,(ix+5) + ld hl,$0006 + add hl, bc +;source-doc/base-drv/dev_transfers.c:51: } + pop de + ld e,c + ld d,b + ex de,hl + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + push bc + push de + push de + push af + inc sp + ld l,(ix+8) + ld h,(ix+9) + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + call _usb_data_in_transfer_n + pop af + pop af + pop af + inc sp + pop de + pop bc +;source-doc/base-drv/dev_transfers.c:53: usb_error usbdev_bulk_in_transfer(device_config *const dev, uint8_t *const buffer, uint8_t *const buffer_size) { + ld a, l + sub $02 + jr NZ,l_usbdev_bulk_in_transfer_00102 +;source-doc/base-drv/dev_transfers.c:54: usb_error result; + inc bc + ld a, (bc) + ld b, a + pop hl + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + ld c, a + ld l, e + ld h, d + ld a, (hl) + rrca + and $07 + push de + push bc + inc sp + ld h, c + ld l,a + push hl + call _usbtrn_clr_ep_halt + pop af + inc sp + pop de +;source-doc/base-drv/dev_transfers.c:55: + ex de, hl + res 0, (hl) +;source-doc/base-drv/dev_transfers.c:56: endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_IN]; + ld l,$02 +;source-doc/base-drv/dev_transfers.c:61: usbtrn_clr_ep_halt(endpoint->number, dev->address, dev->max_packet_size); +l_usbdev_bulk_in_transfer_00102: +;source-doc/base-drv/dev_transfers.c:62: endpoint->toggle = 0; + ld sp, ix + pop ix + ret +;source-doc/base-drv/dev_transfers.c:64: } +; --------------------------------- +; Function usbdev_dat_in_trnsfer +; --------------------------------- +_usbdev_dat_in_trnsfer: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/dev_transfers.c:70: + ld c,(ix+4) + ld b,(ix+5) + ld e, c + ld d, b + inc de + inc de + inc de + push de + ld a,(ix+10) + ld e, a + add a, a + add a, e + pop de + add a, e + ld e, a + ld a,$00 + adc a, d + ld d, a +;source-doc/base-drv/dev_transfers.c:72: uint8_t *const buffer, + pop hl + ld l,c + ld h,b + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + push bc + push de + push de + push af + inc sp + ld l,(ix+8) + ld h,(ix+9) + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + call _usb_data_in_transfer + pop af + pop af + pop af + inc sp + pop de + pop bc +;source-doc/base-drv/dev_transfers.c:74: const usb_endpoint_type endpoint_type) { + ld a, l + sub $02 + jr NZ,l_usbdev_dat_in_trnsfer_00102 +;source-doc/base-drv/dev_transfers.c:75: usb_error result; + inc bc + ld a, (bc) + ld b, a + pop hl + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + ld c, a + ld l, e + ld h, d + ld a, (hl) + rrca + and $07 + push de + push bc + inc sp + ld h, c + ld l,a + push hl + call _usbtrn_clr_ep_halt + pop af + inc sp + pop de +;source-doc/base-drv/dev_transfers.c:76: + ex de, hl + res 0, (hl) +;source-doc/base-drv/dev_transfers.c:77: endpoint_param *const endpoint = &device->endpoints[endpoint_type]; + ld l,$02 +;source-doc/base-drv/dev_transfers.c:82: usbtrn_clr_ep_halt(endpoint->number, device->address, device->max_packet_size); +l_usbdev_dat_in_trnsfer_00102: +;source-doc/base-drv/dev_transfers.c:83: endpoint->toggle = 0; + ld sp, ix + pop ix + ret +;source-doc/base-drv/dev_transfers.c:85: } +; --------------------------------- +; Function usbdev_dat_in_trnsfer_0 +; --------------------------------- +_usbdev_dat_in_trnsfer_0: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/dev_transfers.c:88: done: + ld c,(ix+4) + ld b,(ix+5) + ld e, c + ld d, b + inc de + inc de + inc de +;source-doc/base-drv/dev_transfers.c:90: } + pop hl + ld l,c + ld h,b + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + ld l,(ix+8) + ld h,$00 + push bc + push de + push de + push af + inc sp + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + call _usb_data_in_transfer + pop af + pop af + pop af + inc sp + pop de + pop bc +;source-doc/base-drv/dev_transfers.c:92: usb_error usbdev_dat_in_trnsfer_0(device_config *const device, uint8_t *const buffer, const uint8_t buffer_size) { + ld a, l + sub $02 + jr NZ,l_usbdev_dat_in_trnsfer_0_00102 +;source-doc/base-drv/dev_transfers.c:93: usb_error result; + inc bc + ld a, (bc) + ld b, a + pop hl + ld a,(hl) + push hl + rlca + rlca + rlca + rlca + and $0f + ld c, a + ld l, e + ld h, d + ld a, (hl) + rrca + and $07 + push de + push bc + inc sp + ld h, c + ld l,a + push hl + call _usbtrn_clr_ep_halt + pop af + inc sp + pop de +;source-doc/base-drv/dev_transfers.c:94: + ex de, hl + res 0, (hl) +;source-doc/base-drv/dev_transfers.c:95: endpoint_param *const endpoint = &device->endpoints[0]; + ld l,$02 +;source-doc/base-drv/dev_transfers.c:98: +l_usbdev_dat_in_trnsfer_0_00102: +;source-doc/base-drv/dev_transfers.c:99: if (result == USB_ERR_STALL) { + ld sp, ix + pop ix + ret diff --git a/Source/HBIOS/ch376-native/base-drv/enumerate.c.s b/Source/HBIOS/ch376-native/base-drv/enumerate.c.s new file mode 100644 index 00000000..0639355c --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/enumerate.c.s @@ -0,0 +1,1085 @@ +; +; Generated from source-doc/base-drv/enumerate.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/enumerate.c:13: static usb_error adv_to_next_desc(_working *const working, const uint8_t descriptor_type) __sdcccall(1) { +; --------------------------------- +; Function adv_to_next_desc +; --------------------------------- +_adv_to_next_desc: + push ix + ld ix,0 + add ix,sp + push af + push af + ex de, hl +;source-doc/base-drv/enumerate.c:15: const uint8_t *buffer_end = working->config.buffer + MAX_CONFIG_SIZE; + ld hl,$00ab + add hl, de + ex (sp), hl +;source-doc/base-drv/enumerate.c:17: if (working->ptr >= buffer_end) + ld hl,$001b + add hl, de + ld (ix-2),l + ld (ix-1),h + pop de + pop hl + ld a,(hl) + push hl + push de + inc hl + ld b,(hl) + ld c,a + sub (ix-4) + ld a, b + sbc a,(ix-3) + jr C,l_adv_to_next_desc_00102 +;source-doc/base-drv/enumerate.c:18: return USB_ERR_BUFF_TO_LARGE; + ld a,$84 + jr l_adv_to_next_desc_00110 +l_adv_to_next_desc_00102: +;source-doc/base-drv/enumerate.c:20: d = (usb_descriptor_t *)working->ptr; + ld e, c + ld d, b +;source-doc/base-drv/enumerate.c:22: do { +l_adv_to_next_desc_00105: +;source-doc/base-drv/enumerate.c:23: working->ptr += d->bLength; + ld a, (de) + add a, c + ld c, a + ld a,$00 + adc a, b + ld b, a + ld l,(ix-2) + ld h,(ix-1) + ld (hl), c + inc hl + ld (hl), b +;source-doc/base-drv/enumerate.c:25: if (working->ptr >= buffer_end) + ld a, c + sub (ix-4) + ld a, b + sbc a,(ix-3) + jr C,l_adv_to_next_desc_00104 +;source-doc/base-drv/enumerate.c:26: return USB_ERR_BUFF_TO_LARGE; + ld a,$84 + jr l_adv_to_next_desc_00110 +l_adv_to_next_desc_00104: +;source-doc/base-drv/enumerate.c:17: if (working->ptr >= buffer_end) + pop de + pop hl + ld c,(hl) + push hl + push de + inc hl + ld b, (hl) +;source-doc/base-drv/enumerate.c:28: d = (usb_descriptor_t *)working->ptr; + ld e, c + ld d, b +;source-doc/base-drv/enumerate.c:29: } while (d->bDescriptorType != descriptor_type); + ld l, e + ld h, d + inc hl + ld a, (hl) + sub (ix+4) + jr NZ,l_adv_to_next_desc_00105 +;source-doc/base-drv/enumerate.c:31: if (working->ptr + d->bLength >= buffer_end) + ld a, (de) + ld l, a + ld h,$00 + add hl, bc + ld a, l + sub (ix-4) + ld a, h + sbc a,(ix-3) + jr C,l_adv_to_next_desc_00109 +;source-doc/base-drv/enumerate.c:32: return USB_ERR_BUFF_TO_LARGE; + ld a,$84 + jr l_adv_to_next_desc_00110 +l_adv_to_next_desc_00109: +;source-doc/base-drv/enumerate.c:34: return USB_ERR_OK; + xor a +l_adv_to_next_desc_00110: +;source-doc/base-drv/enumerate.c:35: } + ld sp, ix + pop ix + pop hl + inc sp + jp (hl) +;source-doc/base-drv/enumerate.c:37: void parse_endpoint_keyboard(device_config_keyboard *const keyboard_config, const endpoint_descriptor const *pEndpoint) +; --------------------------------- +; Function parse_endpoint_keyboard +; --------------------------------- +_parse_endpoint_keyboard: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/enumerate.c:39: endpoint_param *const ep = &keyboard_config->endpoints[0]; + inc hl + inc hl + inc hl +;source-doc/base-drv/enumerate.c:40: ep->number = pEndpoint->bEndpointAddress; + ld c,l + ld b,h + ex (sp),hl + ld l, e + ld h, d + inc hl + inc hl + ld a, (hl) + pop hl + push hl + rlca + and $0e + push bc + ld c, a + ld a, (hl) + and $f1 + or c + ld (hl), a +;source-doc/base-drv/enumerate.c:41: ep->toggle = 0; + pop hl + ld c,l + ld b,h + res 0, (hl) +;source-doc/base-drv/enumerate.c:42: ep->max_packet_sizex = calc_max_packet_sizex(pEndpoint->wMaxPacketSize); + inc bc + ld hl,4 + add hl, de + ld e, (hl) + inc hl + ld a, (hl) + and $03 + ld d, a + ld a, e + ld (bc), a + inc bc + ld a, d + and $03 + ld l, a + ld a, (bc) + and $fc + or l + ld (bc), a +;source-doc/base-drv/enumerate.c:43: } + ld sp, ix + pop ix + ret +;source-doc/base-drv/enumerate.c:45: usb_device_type identify_class_driver(_working *const working) { +; --------------------------------- +; Function identify_class_driver +; --------------------------------- +_identify_class_driver: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/enumerate.c:46: const interface_descriptor *const p = (const interface_descriptor *)working->ptr; + ld c,(ix+4) + ld b,(ix+5) + ld hl,27 + add hl, bc + ld c, (hl) + inc hl + ld b, (hl) +;source-doc/base-drv/enumerate.c:47: if (p->bInterfaceClass == 2) + ld hl,5 + add hl,bc + ld a,(hl) + ld e,a + sub $02 + jr NZ,l_identify_class_driver_00102 +;source-doc/base-drv/enumerate.c:48: return USB_IS_CDC; + ld l,$03 + jr l_identify_class_driver_00118 +l_identify_class_driver_00102: +;source-doc/base-drv/enumerate.c:50: if (p->bInterfaceClass == 8 && (p->bInterfaceSubClass == 6 || p->bInterfaceSubClass == 5) && p->bInterfaceProtocol == 80) + ld a, e + sub $08 + jr NZ,l_identify_class_driver_00199 + ld a,$01 + jr l_identify_class_driver_00200 +l_identify_class_driver_00199: + xor a +l_identify_class_driver_00200: + ld d,a + or a + jr Z,l_identify_class_driver_00104 + ld hl,$0006 + add hl,bc + ld a, (hl) + cp $06 + jr Z,l_identify_class_driver_00107 + sub $05 + jr NZ,l_identify_class_driver_00104 +l_identify_class_driver_00107: + ld hl,$0007 + add hl,bc + ld a, (hl) + sub $50 + jr NZ,l_identify_class_driver_00104 +;source-doc/base-drv/enumerate.c:51: return USB_IS_MASS_STORAGE; + ld l,$02 + jr l_identify_class_driver_00118 +l_identify_class_driver_00104: +;source-doc/base-drv/enumerate.c:53: if (p->bInterfaceClass == 8 && p->bInterfaceSubClass == 4 && p->bInterfaceProtocol == 0) + ld a, d + or a + jr Z,l_identify_class_driver_00109 + ld hl,$0006 + add hl,bc + ld a, (hl) + sub $04 + jr NZ,l_identify_class_driver_00109 + ld hl,$0007 + add hl,bc + ld a, (hl) + or a + jr NZ,l_identify_class_driver_00109 +;source-doc/base-drv/enumerate.c:54: return USB_IS_FLOPPY; + ld l,$01 + jr l_identify_class_driver_00118 +l_identify_class_driver_00109: +;source-doc/base-drv/enumerate.c:56: if (p->bInterfaceClass == 9 && p->bInterfaceSubClass == 0 && p->bInterfaceProtocol == 0) + ld a, e + sub $09 + jr NZ,l_identify_class_driver_00113 + ld hl,$0006 + add hl,bc + ld a, (hl) + or a + jr NZ,l_identify_class_driver_00113 + ld hl,7 + add hl, bc + ld a, (hl) + or a + jr NZ,l_identify_class_driver_00113 +;source-doc/base-drv/enumerate.c:57: return USB_IS_HUB; + ld l,$0f + jr l_identify_class_driver_00118 +l_identify_class_driver_00113: +;source-doc/base-drv/enumerate.c:59: if (p->bInterfaceClass == 3) + ld a, e + sub $03 + jr NZ,l_identify_class_driver_00117 +;source-doc/base-drv/enumerate.c:60: return USB_IS_KEYBOARD; + ld l,$04 + jr l_identify_class_driver_00118 +l_identify_class_driver_00117: +;source-doc/base-drv/enumerate.c:62: return USB_IS_UNKNOWN; + ld l,$06 +l_identify_class_driver_00118: +;source-doc/base-drv/enumerate.c:63: } + pop ix + ret +;source-doc/base-drv/enumerate.c:65: usb_error op_interface_next(_working *const working) __z88dk_fastcall { +; --------------------------------- +; Function op_interface_next +; --------------------------------- +_op_interface_next: + ex de, hl +;source-doc/base-drv/enumerate.c:68: if (--working->interface_count == 0) + ld hl,$0016 + add hl, de + ld a, (hl) + dec a + ld (hl), a +;source-doc/base-drv/enumerate.c:69: return USB_ERR_OK; + or a + jr NZ,l_op_interface_next_00102 + ld l,a + jr l_op_interface_next_00106 +l_op_interface_next_00102: +;source-doc/base-drv/enumerate.c:71: CHECK(adv_to_next_desc(working, USB_DESCR_INTERFACE)); + push de + ld a,$04 + push af + inc sp + ex de,hl + call _adv_to_next_desc + pop de + ld l, a + or a + ret NZ +;source-doc/base-drv/enumerate.c:72: return op_id_class_drv(working); + ex de, hl + call _op_id_class_drv + ld l, a +;source-doc/base-drv/enumerate.c:74: done: +;source-doc/base-drv/enumerate.c:75: return result; +l_op_interface_next_00106: +;source-doc/base-drv/enumerate.c:76: } + ret +;source-doc/base-drv/enumerate.c:78: usb_error op_endpoint_next(_working *const working) __sdcccall(1) { +; --------------------------------- +; Function op_endpoint_next +; --------------------------------- +_op_endpoint_next: +;source-doc/base-drv/enumerate.c:81: if (working->endpoint_count != 0 && --working->endpoint_count > 0) { + ld a, l + add a,$17 + ld c, a + ld a, h + adc a,$00 + ld b, a + ld a, (bc) + or a + jr Z,l_op_endpoint_next_00104 + dec a + ld (bc), a + or a + jr Z,l_op_endpoint_next_00104 +;source-doc/base-drv/enumerate.c:82: CHECK(adv_to_next_desc(working, USB_DESCR_ENDPOINT)); + push hl + ld a,$05 + push af + inc sp + call _adv_to_next_desc + pop hl + ld c, a + or a + jr NZ,l_op_endpoint_next_00106 +;source-doc/base-drv/enumerate.c:83: return op_parse_endpoint(working); + jp _op_parse_endpoint + jr l_op_endpoint_next_00107 +l_op_endpoint_next_00104: +;source-doc/base-drv/enumerate.c:86: return op_interface_next(working); + call _op_interface_next + ld a, l + jr l_op_endpoint_next_00107 +;source-doc/base-drv/enumerate.c:88: done: +l_op_endpoint_next_00106: +;source-doc/base-drv/enumerate.c:89: return result; + ld a, c +l_op_endpoint_next_00107: +;source-doc/base-drv/enumerate.c:90: } + ret +;source-doc/base-drv/enumerate.c:92: usb_error op_parse_endpoint(_working *const working) __sdcccall(1) { +; --------------------------------- +; Function op_parse_endpoint +; --------------------------------- +_op_parse_endpoint: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/enumerate.c:93: const endpoint_descriptor *endpoint = (endpoint_descriptor *)working->ptr; + ld de,$001c + ld c,l + ld b,h + add hl, de + ld a, (hl) + dec hl + ld l, (hl) + ld (ix-2),l + ld (ix-1),a +;source-doc/base-drv/enumerate.c:94: device_config *const device = working->p_current_device; + ld hl,29 + add hl,bc + ld e, (hl) + inc hl + ld d, (hl) +;source-doc/base-drv/enumerate.c:96: switch (working->usb_device) { + ld l, c + ld h, b + inc hl + inc hl + ld a, (hl) + cp $01 + jr Z,l_op_parse_endpoint_00102 + cp $02 + jr Z,l_op_parse_endpoint_00102 + sub $04 + jr Z,l_op_parse_endpoint_00103 + jr l_op_parse_endpoint_00104 +;source-doc/base-drv/enumerate.c:98: case USB_IS_MASS_STORAGE: { +l_op_parse_endpoint_00102: +;source-doc/base-drv/enumerate.c:99: parse_endpoints((device_config_storage *)device, endpoint); + push bc + ld l,(ix-2) + ld h,(ix-1) + push hl + push de + call _parse_endpoints + pop af + pop af + pop bc +;source-doc/base-drv/enumerate.c:100: break; + jr l_op_parse_endpoint_00104 +;source-doc/base-drv/enumerate.c:103: case USB_IS_KEYBOARD: { +l_op_parse_endpoint_00103: +;source-doc/base-drv/enumerate.c:104: parse_endpoint_keyboard((device_config_keyboard *)device, endpoint); + ex de, hl + push bc + ld e,(ix-2) + ld d,(ix-1) + call _parse_endpoint_keyboard + pop bc +;source-doc/base-drv/enumerate.c:107: } +l_op_parse_endpoint_00104: +;source-doc/base-drv/enumerate.c:109: return op_endpoint_next(working); + ld l, c + ld h, b + call _op_endpoint_next +;source-doc/base-drv/enumerate.c:110: } + ld sp, ix + pop ix + ret +;source-doc/base-drv/enumerate.c:113: configure_device(const _working *const working, const interface_descriptor *const interface, device_config *const dev_cfg) { +; --------------------------------- +; Function configure_device +; --------------------------------- +_configure_device: + push ix + ld ix,0 + add ix,sp + push af + push af +;source-doc/base-drv/enumerate.c:114: dev_cfg->interface_number = interface->bInterfaceNumber; + ld c,(ix+8) + ld b,(ix+9) + ld e, c + ld d, b + inc de + inc de + ld l,(ix+6) + ld h,(ix+7) + inc hl + inc hl + ld a, (hl) + ld (de), a +;source-doc/base-drv/enumerate.c:115: dev_cfg->max_packet_size = working->desc.bMaxPacketSize0; + ld hl,$0001 + add hl, bc + ex (sp), hl + ld e,(ix+4) + ld d,(ix+5) + ld hl,$000a + add hl,de + ld a, (hl) + pop hl + push hl + ld (hl), a +;source-doc/base-drv/enumerate.c:116: dev_cfg->address = working->current_device_address; + ld (ix-2),c + ld (ix-1),b + ld l, e + ld h, d + ld a,+(($0018) & $FF) + add a,l + ld l,a + ld a,+(($0018) / 256) + adc a,h + ld h,a + ld a, (hl) + ld l,(ix-2) + ld h,(ix-1) + add a, a + add a, a + add a, a + add a, a + push bc + ld c, a + ld a, (hl) + and $0f + or c + ld (hl), a + pop bc +;source-doc/base-drv/enumerate.c:117: dev_cfg->type = working->usb_device; + ld l, e + ld h, d + inc hl + inc hl + ld a, (hl) + and $0f + ld l, a + ld a, (bc) + and $f0 + or l + ld (bc), a +;source-doc/base-drv/enumerate.c:119: return usbtrn_set_config(dev_cfg->address, dev_cfg->max_packet_size, working->config.desc.bConfigurationvalue); + ld hl,36 + add hl, de + ld b, (hl) + pop hl + ld d,(hl) + push hl + ld l,(ix-2) + ld h,(ix-1) + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld c, d + push bc + push af + inc sp + call _usbtrn_set_config +;source-doc/base-drv/enumerate.c:120: } + ld sp,ix + pop ix + ret +;source-doc/base-drv/enumerate.c:122: usb_error op_cap_hub_drv_intf(_working *const working) __sdcccall(1) { +; --------------------------------- +; Function op_cap_hub_drv_intf +; --------------------------------- +_op_cap_hub_drv_intf: + push ix + ld ix,0 + add ix,sp + push af + push af + dec sp + ex de, hl +;source-doc/base-drv/enumerate.c:123: const interface_descriptor *const interface = (interface_descriptor *)working->ptr; + ld hl,$001c + add hl,de + ld a, (hl) + dec hl + ld l, (hl) + ld (ix-2),l + ld (ix-1),a +;source-doc/base-drv/enumerate.c:127: working->hub_config = &hub_config; + ld hl,$0019 + add hl, de + ld c, l + ld b, h + ld hl,0 + add hl, sp + ld a, l + ld (bc), a + inc bc + ld a, h + ld (bc), a +;source-doc/base-drv/enumerate.c:129: hub_config.type = USB_IS_HUB; + ld hl,0 + add hl, sp + ld a, (hl) + or $0f + ld (hl), a +;source-doc/base-drv/enumerate.c:130: CHECK(configure_device(working, interface, (device_config *const)&hub_config)); + push de + ld hl,2 + add hl, sp + push hl + ld l,(ix-2) + ld h,(ix-1) + push hl + push de + call _configure_device + pop af + pop af + pop af + pop de + ld a, l + inc l + dec l + jr NZ,l_op_cap_hub_drv_intf_00103 +;source-doc/base-drv/enumerate.c:131: RETURN_CHECK(configure_usb_hub(working)); + ex de, hl + call _configure_usb_hub + ld a, l +;source-doc/base-drv/enumerate.c:132: done: +l_op_cap_hub_drv_intf_00103: +;source-doc/base-drv/enumerate.c:133: return result; +;source-doc/base-drv/enumerate.c:134: } + ld sp, ix + pop ix + ret +;source-doc/base-drv/enumerate.c:136: usb_error op_cap_drv_intf(_working *const working) __z88dk_fastcall { +; --------------------------------- +; Function op_cap_drv_intf +; --------------------------------- +_op_cap_drv_intf: + push ix + ld ix,0 + add ix,sp + ld c, l + ld b, h + ld hl, -14 + add hl, sp + ld sp, hl +;source-doc/base-drv/enumerate.c:139: const interface_descriptor *const interface = (interface_descriptor *)working->ptr; + ld l,c + ld h, b + ld de,$001c + add hl, de + ld a, (hl) + dec hl + ld l, (hl) + ld (ix-2),l + ld (ix-1),a +;source-doc/base-drv/enumerate.c:141: working->endpoint_count = interface->bNumEndpoints; + ld hl,$0017 + add hl, bc + ex de, hl + ld l,(ix-2) + ld h,(ix-1) + inc hl + inc hl + inc hl + inc hl + ld a, (hl) + ld (de), a +;source-doc/base-drv/enumerate.c:142: if (working->endpoint_count > 0) + or a + jr Z,l_op_cap_drv_intf_00104 +;source-doc/base-drv/enumerate.c:143: CHECK(adv_to_next_desc(working, USB_DESCR_ENDPOINT)); + push bc + ld a,$05 + push af + inc sp + ld l, c + ld h, b + call _adv_to_next_desc + pop bc + or a + jp NZ, l_op_cap_drv_intf_00117 +l_op_cap_drv_intf_00104: +;source-doc/base-drv/enumerate.c:144: working->p_current_device = NULL; + ld hl,$001d + add hl, bc + ld e,l + ld d,h + xor a + ld (hl), a + inc hl + ld (hl), a +;source-doc/base-drv/enumerate.c:146: switch (working->usb_device) { + ld l, c + ld h, b + inc hl + inc hl + ld a, (hl) + cp $06 + jr Z,l_op_cap_drv_intf_00108 + sub $0f + jr NZ,l_op_cap_drv_intf_00111 +;source-doc/base-drv/enumerate.c:148: CHECK(op_cap_hub_drv_intf(working)) + ld l,c + ld h,b + push hl + call _op_cap_hub_drv_intf + pop bc + or a + jr Z,l_op_cap_drv_intf_00116 + jr l_op_cap_drv_intf_00117 +;source-doc/base-drv/enumerate.c:152: case USB_IS_UNKNOWN: { +l_op_cap_drv_intf_00108: +;source-doc/base-drv/enumerate.c:154: memset(&unkown_dev_cfg, 0, sizeof(device_config)); + push bc + ld hl,2 + add hl, sp + ld b,$06 +l_op_cap_drv_intf_00165: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_op_cap_drv_intf_00165 + pop bc +;source-doc/base-drv/enumerate.c:155: working->p_current_device = &unkown_dev_cfg; + ld hl,0 + add hl, sp + ld a, l + ld (de), a + inc de + ld a, h + ld (de), a +;source-doc/base-drv/enumerate.c:156: CHECK(configure_device(working, interface, &unkown_dev_cfg)); + push bc + push hl + ld l,(ix-2) + ld h,(ix-1) + push hl + push bc + call _configure_device + pop af + pop af + pop af + ld a, l + pop bc + or a + jr Z,l_op_cap_drv_intf_00116 + jr l_op_cap_drv_intf_00117 +;source-doc/base-drv/enumerate.c:160: default: { +l_op_cap_drv_intf_00111: +;source-doc/base-drv/enumerate.c:161: device_config *dev_cfg = find_first_free(); + push bc + push de + call _find_first_free + pop de + pop bc +;source-doc/base-drv/enumerate.c:162: if (dev_cfg == NULL) + ld a, h + or l + jr NZ,l_op_cap_drv_intf_00113 +;source-doc/base-drv/enumerate.c:163: return USB_ERR_OUT_OF_MEMORY; + ld l,$83 + jr l_op_cap_drv_intf_00118 +l_op_cap_drv_intf_00113: +;source-doc/base-drv/enumerate.c:164: working->p_current_device = dev_cfg; + ld a, l + ld (de), a + inc de + ld a, h + ld (de), a +;source-doc/base-drv/enumerate.c:165: CHECK(configure_device(working, interface, dev_cfg)); + push bc + push hl + ld l,(ix-2) + ld h,(ix-1) + push hl + push bc + call _configure_device + pop af + pop af + pop af + ld a, l + pop bc + or a + jr NZ,l_op_cap_drv_intf_00117 +;source-doc/base-drv/enumerate.c:168: } +l_op_cap_drv_intf_00116: +;source-doc/base-drv/enumerate.c:170: return op_parse_endpoint(working); + ld l, c + ld h, b + call _op_parse_endpoint + ld l, a + jr l_op_cap_drv_intf_00118 +;source-doc/base-drv/enumerate.c:172: done: +l_op_cap_drv_intf_00117: +;source-doc/base-drv/enumerate.c:173: return result; + ld l, a +l_op_cap_drv_intf_00118: +;source-doc/base-drv/enumerate.c:174: } + ld sp, ix + pop ix + ret +;source-doc/base-drv/enumerate.c:176: usb_error op_id_class_drv(_working *const working) __sdcccall(1) { +; --------------------------------- +; Function op_id_class_drv +; --------------------------------- +_op_id_class_drv: + ex de, hl +;source-doc/base-drv/enumerate.c:177: const interface_descriptor *const ptr = (const interface_descriptor *)working->ptr; + ld hl,27 + add hl,de + ld c, (hl) + inc hl + ld b, (hl) +;source-doc/base-drv/enumerate.c:179: if (ptr->bDescriptorType != USB_DESCR_INTERFACE) + inc bc + ld a, (bc) + sub $04 + jr Z,l_op_id_class_drv_00102 +;source-doc/base-drv/enumerate.c:180: return USB_ERR_FAIL; + ld a,$0e + jr l_op_id_class_drv_00103 +l_op_id_class_drv_00102: +;source-doc/base-drv/enumerate.c:182: working->usb_device = identify_class_driver(working); + ld c, e + ld b, d + inc bc + inc bc + push bc + push de + push de + call _identify_class_driver + pop af + ld a, l + pop de + pop bc + ld (bc), a +;source-doc/base-drv/enumerate.c:184: return op_cap_drv_intf(working); + ex de, hl + call _op_cap_drv_intf + ld a, l +l_op_id_class_drv_00103: +;source-doc/base-drv/enumerate.c:185: } + ret +;source-doc/base-drv/enumerate.c:187: usb_error op_get_cfg_desc(_working *const working) __sdcccall(1) { +; --------------------------------- +; Function op_get_cfg_desc +; --------------------------------- +_op_get_cfg_desc: + push ix + ld ix,0 + add ix,sp + dec sp +;source-doc/base-drv/enumerate.c:190: const uint8_t max_packet_size = working->desc.bMaxPacketSize0; + ld d,h + ld c,l + ld b,h + ld hl,10 + add hl,bc + ld a, (hl) + ld (ix-1),a +;source-doc/base-drv/enumerate.c:192: memset(working->config.buffer, 0, MAX_CONFIG_SIZE); + ld hl,$001f + add hl, bc + push bc + ld b,$46 +l_op_get_cfg_desc_00122: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_op_get_cfg_desc_00122 + pop bc +;source-doc/base-drv/enumerate.c:193: working->ptr = working->config.buffer; + ld hl,$001b + add hl, bc + ld a, c + add a,$1f + ld e, a + ld a, b + adc a,$00 + ld (hl), e + inc hl + ld (hl), a +;source-doc/base-drv/enumerate.c:196: working->config.buffer)); + ld hl,$001f + add hl, bc + ex de, hl + ld hl,$0018 + add hl,bc + ld a, (hl) + ld hl,$0015 + add hl,bc + ld h, (hl) + push bc + push de + ld d,$8c + push de + inc sp + ld d,(ix-1) + push de + inc sp + ld l,h + ld h,a + push hl + call _usbtrn_gfull_cfg_desc + pop af + pop af + pop af + ld a, l + pop bc + or a + jr NZ,l_op_get_cfg_desc_00105 +;source-doc/base-drv/enumerate.c:198: CHECK(adv_to_next_desc(working, USB_DESCR_INTERFACE)); + push bc + ld a,$04 + push af + inc sp + ld l, c + ld h, b + call _adv_to_next_desc + pop bc + or a + jr NZ,l_op_get_cfg_desc_00105 +;source-doc/base-drv/enumerate.c:199: working->interface_count = working->config.desc.bNumInterfaces; + ld hl,$0016 + add hl, bc + ex de, hl + ld hl,$0023 + add hl,bc + ld a, (hl) + ld (de), a +;source-doc/base-drv/enumerate.c:201: return op_id_class_drv(working); + ld l, c + ld h, b + call _op_id_class_drv +;source-doc/base-drv/enumerate.c:203: done: +;source-doc/base-drv/enumerate.c:204: return result; +l_op_get_cfg_desc_00105: +;source-doc/base-drv/enumerate.c:205: } + inc sp + pop ix + ret +;source-doc/base-drv/enumerate.c:207: usb_error read_all_configs(enumeration_state *const state) { +; --------------------------------- +; Function read_all_configs +; --------------------------------- +_read_all_configs: + push ix + ld ix,0 + add ix,sp + ld hl, -171 + add hl, sp + ld sp, hl +;source-doc/base-drv/enumerate.c:212: memset(&working, 0, sizeof(_working)); + ld hl,0 + add hl, sp + ld e,l + ld d,h + ld b,$56 + jr l_read_all_configs_00150 +l_read_all_configs_00149: + ld (hl),$00 + inc hl +l_read_all_configs_00150: + ld (hl),$00 + inc hl + djnz l_read_all_configs_00149 +;source-doc/base-drv/enumerate.c:213: working.state = state; + ld l, e + ld h, d + ld a,(ix+4) + ld (hl), a + inc hl + ld a,(ix+5) + ld (hl), a +;source-doc/base-drv/enumerate.c:215: CHECK(usbtrn_get_descriptor(&working.desc)); + push de + ld hl,5 + add hl, sp + push hl + call _usbtrn_get_descriptor + pop af + ld a, l + pop de + or a + jr NZ,l_read_all_configs_00108 +;source-doc/base-drv/enumerate.c:217: state->next_device_address++; + ld b,(ix+5) + ld a,(ix+4) + ld l, a + ld h, b + ld c, (hl) + inc c + ld l, a + ld h, b + ld (hl), c +;source-doc/base-drv/enumerate.c:218: working.current_device_address = state->next_device_address; + ld hl,$0018 + add hl, de + ld (hl), c +;source-doc/base-drv/enumerate.c:219: CHECK(usbtrn_set_address(working.current_device_address)); + push de + ld l, c + call _usbtrn_set_address + ld a, l + pop de +;source-doc/base-drv/enumerate.c:221: for (uint8_t config_index = 0; config_index < working.desc.bNumConfigurations; config_index++) { + or a + jr NZ,l_read_all_configs_00108 + ld c,a +l_read_all_configs_00110: + ld hl,20 + add hl, sp + ld b, (hl) + ld a, c + sub b + jr NC,l_read_all_configs_00107 +;source-doc/base-drv/enumerate.c:222: working.config_index = config_index; + ld hl,$0015 + add hl, de + ld (hl), c +;source-doc/base-drv/enumerate.c:224: CHECK(op_get_cfg_desc(&working)); + ld l, e + ld h, d + push bc + push de + call _op_get_cfg_desc + pop de + pop bc + or a + jr NZ,l_read_all_configs_00108 +;source-doc/base-drv/enumerate.c:221: for (uint8_t config_index = 0; config_index < working.desc.bNumConfigurations; config_index++) { + inc c + jr l_read_all_configs_00110 +l_read_all_configs_00107: +;source-doc/base-drv/enumerate.c:227: return USB_ERR_OK; + ld l,$00 + jr l_read_all_configs_00112 +;source-doc/base-drv/enumerate.c:228: done: +l_read_all_configs_00108: +;source-doc/base-drv/enumerate.c:229: return result; + ld l, a +l_read_all_configs_00112: +;source-doc/base-drv/enumerate.c:230: } + ld sp, ix + pop ix + ret +;source-doc/base-drv/enumerate.c:232: usb_error enumerate_all_devices(void) { +; --------------------------------- +; Function enumerate_all_devices +; --------------------------------- +_enumerate_all_devices: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/enumerate.c:233: _usb_state *const work_area = get_usb_work_area(); +;source-doc/base-drv/enumerate.c:235: memset(&state, 0, sizeof(enumeration_state)); + ld hl,0 + add hl, sp + ld e,l + ld d,h + xor a + ld (hl), a + inc hl + ld (hl), a +;source-doc/base-drv/enumerate.c:237: usb_error result = read_all_configs(&state); + push de + push de + call _read_all_configs + pop af + pop de +;source-doc/base-drv/enumerate.c:239: work_area->count_of_detected_usb_devices = state.next_device_address; + ld bc,_x + 1 + ld a, (de) + ld (bc), a +;source-doc/base-drv/enumerate.c:242: return result; +;source-doc/base-drv/enumerate.c:243: } + ld sp, ix + pop ix + ret diff --git a/Source/HBIOS/ch376-native/base-drv/enumerate_hub.c.s b/Source/HBIOS/ch376-native/base-drv/enumerate_hub.c.s new file mode 100644 index 00000000..db47e775 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/enumerate_hub.c.s @@ -0,0 +1,457 @@ +; +; Generated from source-doc/base-drv/enumerate_hub.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/enumerate_hub.c:13: usb_error hub_set_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) { +; --------------------------------- +; Function hub_set_feature +; --------------------------------- +_hub_set_feature: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/enumerate_hub.c:15: set_feature = cmd_set_feature; + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$0008 + ld hl,_cmd_set_feature + ldir + pop bc +;source-doc/base-drv/enumerate_hub.c:17: set_feature.bValue[0] = feature; + ld a,(ix+6) + ld (ix-6),a +;source-doc/base-drv/enumerate_hub.c:18: set_feature.bIndex[0] = index; + ld a,(ix+7) + ld (ix-4),a +;source-doc/base-drv/enumerate_hub.c:19: return usb_control_transfer(&set_feature, 0, hub_config->address, hub_config->max_packet_size); + ld e,(ix+5) + ld a,(ix+4) + ld l, a + ld h, e + inc hl + ld d, (hl) + ld l, a + ld h, e + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld e,a + push de + ld hl,$0000 + push hl + push bc + call _usb_control_transfer +;source-doc/base-drv/enumerate_hub.c:20: } + ld sp,ix + pop ix + ret +_cmd_set_feature: + DEFB +$23 + DEFB +$03 + DEFB +$08 + DEFB +$00 + DEFB +$01 + DEFB +$00 + DEFW +$0000 +_cmd_clear_feature: + DEFB +$23 + DEFB +$01 + DEFB +$08 + DEFB +$00 + DEFB +$01 + DEFB +$00 + DEFW +$0000 +_cmd_get_status_port: + DEFB +$a3 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$01 + DEFB +$00 + DEFW +$0004 +;source-doc/base-drv/enumerate_hub.c:22: usb_error hub_clear_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) { +; --------------------------------- +; Function hub_clear_feature +; --------------------------------- +_hub_clear_feature: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/enumerate_hub.c:24: clear_feature = cmd_clear_feature; + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$0008 + ld hl,_cmd_clear_feature + ldir + pop bc +;source-doc/base-drv/enumerate_hub.c:26: clear_feature.bValue[0] = feature; + ld a,(ix+6) + ld (ix-6),a +;source-doc/base-drv/enumerate_hub.c:27: clear_feature.bIndex[0] = index; + ld a,(ix+7) + ld (ix-4),a +;source-doc/base-drv/enumerate_hub.c:28: return usb_control_transfer(&clear_feature, 0, hub_config->address, hub_config->max_packet_size); + ld e,(ix+5) + ld a,(ix+4) + ld l, a + ld h, e + inc hl + ld d, (hl) + ld l, a + ld h, e + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld e,a + push de + ld hl,$0000 + push hl + push bc + call _usb_control_transfer +;source-doc/base-drv/enumerate_hub.c:29: } + ld sp,ix + pop ix + ret +;source-doc/base-drv/enumerate_hub.c:31: usb_error hub_get_status_port(const device_config_hub *const hub_config, const uint8_t index, hub_port_status *const port_status) { +; --------------------------------- +; Function hub_get_status_port +; --------------------------------- +_hub_get_status_port: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/enumerate_hub.c:33: get_status_port = cmd_get_status_port; + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$0008 + ld hl,_cmd_get_status_port + ldir + pop bc +;source-doc/base-drv/enumerate_hub.c:35: get_status_port.bIndex[0] = index; + ld a,(ix+6) + ld (ix-4),a +;source-doc/base-drv/enumerate_hub.c:36: return usb_control_transfer(&get_status_port, port_status, hub_config->address, hub_config->max_packet_size); + ld e,(ix+5) + ld a,(ix+4) + ld l, a + ld h, e + inc hl + ld d, (hl) + ld l, a + ld h, e + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld l,(ix+7) + ld h,(ix+8) + ld e,a + push de + push hl + push bc + call _usb_control_transfer +;source-doc/base-drv/enumerate_hub.c:37: } + ld sp,ix + pop ix + ret +;source-doc/base-drv/enumerate_hub.c:39: usb_error configure_usb_hub(_working *const working) __z88dk_fastcall { +; --------------------------------- +; Function configure_usb_hub +; --------------------------------- +_configure_usb_hub: + push ix + ld ix,0 + add ix,sp + ld c, l + ld b, h + ld hl, -14 + add hl, sp + ld sp, hl +;source-doc/base-drv/enumerate_hub.c:45: const device_config_hub *const hub_config = working->hub_config; + ld (ix-2),c + ld (ix-1),b + ld hl,25 + add hl, bc + ld c, (hl) + inc hl + ld b, (hl) +;source-doc/base-drv/enumerate_hub.c:47: CHECK(hub_get_descriptor(hub_config, &hub_description)); + push bc + ld hl,2 + add hl, sp + ld e,c + ld d,b + ex de,hl + call _hub_get_descriptor + pop bc + or a + jp NZ, l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:49: uint8_t i = hub_description.bNbrPorts; + ld d,(ix-12) +;source-doc/base-drv/enumerate_hub.c:50: do { +l_configure_usb_hub_00126: +;source-doc/base-drv/enumerate_hub.c:51: CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i)); + push bc + push de + ld e,$08 + push de + push bc + call _hub_clear_feature + pop af + pop af + ld a, l + pop de + pop bc + or a + jp NZ, l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:53: CHECK(hub_set_feature(hub_config, FEAT_PORT_POWER, i)); + push bc + push de + ld e,$08 + push de + push bc + call _hub_set_feature + pop af + pop af + ld a, l + pop de + pop bc + or a + jp NZ, l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:55: hub_clear_feature(hub_config, FEAT_PORT_RESET, i); + push bc + push de + ld e,$04 + push de + push bc + call _hub_clear_feature + pop af + pop af + pop de + pop bc +;source-doc/base-drv/enumerate_hub.c:57: CHECK(hub_set_feature(hub_config, FEAT_PORT_RESET, i)); + push bc + push de + ld e,$04 + push de + push bc + call _hub_set_feature + pop af + pop af + ld a, l + pop de + pop bc + or a + jp NZ, l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:59: CHECK(hub_get_status_port(hub_config, i, &port_status)); + push bc + push de + ld hl,12 + add hl, sp + push hl + push de + inc sp + push bc + call _hub_get_status_port + pop af + pop af + inc sp + ld a, l + pop de + pop bc + or a + jp NZ, l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:61: if (port_status.wPortStatus & PORT_STAT_CONNECTION) { + ld e,(ix-6) + bit 0, e + jr Z,l_configure_usb_hub_00124 +;source-doc/base-drv/enumerate_hub.c:62: CHECK(hub_clear_feature(hub_config, HUB_FEATURE_PORT_CONNECTION_CHA, i)); + push bc + push de + ld e,$10 + push de + push bc + call _hub_clear_feature + pop af + pop af + ld a, l + pop de + pop bc + or a + jr NZ,l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:64: CHECK(hub_clear_feature(hub_config, FEAT_PORT_ENABLE_CHANGE, i)); + push bc + push de + ld e,$11 + push de + push bc + call _hub_clear_feature + pop af + pop af + ld a, l + pop de + pop bc + or a + jr NZ,l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:66: CHECK(hub_clear_feature(hub_config, FEAT_PORT_RESET_CHANGE, i)); + push bc + push de + ld e,$14 + push de + push bc + call _hub_clear_feature + pop af + pop af + ld a, l + pop de + pop bc + or a + jr NZ,l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:67: delay_short(); + push bc + push de + call _delay_short + pop de + pop bc +;source-doc/base-drv/enumerate_hub.c:69: CHECK(hub_get_status_port(hub_config, i, &port_status)); + push bc + push de + ld hl,12 + add hl, sp + push hl + push de + inc sp + push bc + call _hub_get_status_port + pop af + pop af + inc sp + ld a, l + pop de + pop bc + or a + jr NZ,l_configure_usb_hub_00129 +;source-doc/base-drv/enumerate_hub.c:70: delay_short(); + push bc + push de + call _delay_short + pop de + pop bc +;source-doc/base-drv/enumerate_hub.c:72: CHECK(read_all_configs(working->state)); + ld l,(ix-2) + ld h,(ix-1) + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + push bc + push de + push hl + call _read_all_configs + pop af + ld a, l + pop de + pop bc + or a + jr Z,l_configure_usb_hub_00127 + jr l_configure_usb_hub_00129 +l_configure_usb_hub_00124: +;source-doc/base-drv/enumerate_hub.c:75: CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i)); + push bc + push de + ld e,$08 + push de + push bc + call _hub_clear_feature + pop af + pop af + ld a, l + pop de + pop bc + or a + jr NZ,l_configure_usb_hub_00129 +l_configure_usb_hub_00127: +;source-doc/base-drv/enumerate_hub.c:77: } while (--i != 0); + dec d + jp NZ, l_configure_usb_hub_00126 +;source-doc/base-drv/enumerate_hub.c:79: return USB_ERR_OK; + ld l,$00 + jr l_configure_usb_hub_00130 +;source-doc/base-drv/enumerate_hub.c:80: done: +l_configure_usb_hub_00129: +;source-doc/base-drv/enumerate_hub.c:81: return result; + ld l, a +l_configure_usb_hub_00130: +;source-doc/base-drv/enumerate_hub.c:82: } + ld sp, ix + pop ix + ret diff --git a/Source/HBIOS/ch376-native/base-drv/enumerate_storage.c.s b/Source/HBIOS/ch376-native/base-drv/enumerate_storage.c.s new file mode 100644 index 00000000..bbae0804 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/enumerate_storage.c.s @@ -0,0 +1,142 @@ +; +; Generated from source-doc/base-drv/enumerate_storage.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/enumerate_storage.c:5: void parse_endpoints(device_config_storage *const storage_dev, const endpoint_descriptor const *pEndpoint) { +; --------------------------------- +; Function parse_endpoints +; --------------------------------- +_parse_endpoints: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/base-drv/enumerate_storage.c:7: if (!(pEndpoint->bmAttributes & $02)) + ld l,(ix+6) + ld h,(ix+7) + ld c,l + ld b,h + inc hl + inc hl + inc hl + ld a, (hl) + ld (ix-2),a + bit 1,a +;source-doc/base-drv/enumerate_storage.c:8: return; + jr Z,l_parse_endpoints_00108 +;source-doc/base-drv/enumerate_storage.c:10: const uint8_t x = calc_max_packet_sizex(pEndpoint->wMaxPacketSize); + ld hl,4 + add hl,bc + ld a, (hl) + ld (ix-1),a +;source-doc/base-drv/enumerate_storage.c:11: endpoint_param *const eps = storage_dev->endpoints; + ld e,(ix+4) + ld d,(ix+5) + inc de + inc de + inc de +;source-doc/base-drv/enumerate_storage.c:15: if (!(pEndpoint->bEndpointAddress & $80)) + inc bc + inc bc + ld a, (bc) + ld c,a + and $80 + ld b,$00 +;source-doc/base-drv/enumerate_storage.c:14: if (pEndpoint->bmAttributes & $01) { // 3 -> Interrupt + bit 0,(ix-2) + jr Z,l_parse_endpoints_00106 +;source-doc/base-drv/enumerate_storage.c:15: if (!(pEndpoint->bEndpointAddress & $80)) + or b +;source-doc/base-drv/enumerate_storage.c:16: return; + jr Z,l_parse_endpoints_00108 +;source-doc/base-drv/enumerate_storage.c:18: ep = &eps[ENDPOINT_INTERRUPT_IN]; + ld hl,$0006 + add hl, de + ex de, hl + jr l_parse_endpoints_00107 +l_parse_endpoints_00106: +;source-doc/base-drv/enumerate_storage.c:21: ep = (pEndpoint->bEndpointAddress & $80) ? &eps[ENDPOINT_BULK_IN] : &eps[ENDPOINT_BULK_OUT]; + or b + jr Z,l_parse_endpoints_00110 + inc de + inc de + inc de +l_parse_endpoints_00110: +l_parse_endpoints_00107: +;source-doc/base-drv/enumerate_storage.c:24: ep->number = pEndpoint->bEndpointAddress & $07; + ld l, e + ld h, d + ld a, c + and $07 + rlca + and $0e + ld c, a + ld a, (hl) + and $f1 + or c + ld (hl), a +;source-doc/base-drv/enumerate_storage.c:25: ep->toggle = 0; + ld l, e + ld h, d + res 0, (hl) +;source-doc/base-drv/enumerate_storage.c:26: ep->max_packet_sizex = x; + inc de + ld a,(ix-1) + ld b,$00 + ld (de), a + inc de + ld a, b + and $03 + ld l, a + ld a, (de) + and $fc + or l + ld (de), a +l_parse_endpoints_00108: +;source-doc/base-drv/enumerate_storage.c:27: } + ld sp, ix + pop ix + ret diff --git a/Source/HBIOS/ch376-native/base-drv/hbios-driver-storage.c.s b/Source/HBIOS/ch376-native/base-drv/hbios-driver-storage.c.s new file mode 100644 index 00000000..a6b4761e --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/hbios-driver-storage.c.s @@ -0,0 +1,97 @@ +; +; Generated from source-doc/base-drv/hbios-driver-storage.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_hbios_usbstore_devs: + DEFS 12 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/hbios-driver-storage.c:5: uint8_t find_storage_dev(void) { +; --------------------------------- +; Function find_storage_dev +; --------------------------------- +_find_storage_dev: +;source-doc/base-drv/hbios-driver-storage.c:6: for (uint8_t i = 0; i < MAX_NUMBER_OF_DEVICES; i++) + ld c,$00 + ld de,_hbios_usbstore_devs+0 + ld b,c +l_find_storage_dev_00105: + ld a, b + sub $06 + jr NC,l_find_storage_dev_00103 +;source-doc/base-drv/hbios-driver-storage.c:7: if (hbios_usbstore_devs[i].drive_index == 0) + ld l, b + ld h,$00 + add hl, hl + add hl, de + ld a, (hl) + or a + jr NZ,l_find_storage_dev_00106 +;source-doc/base-drv/hbios-driver-storage.c:8: return i; + ld l, c + jr l_find_storage_dev_00107 +l_find_storage_dev_00106: +;source-doc/base-drv/hbios-driver-storage.c:6: for (uint8_t i = 0; i < MAX_NUMBER_OF_DEVICES; i++) + inc b + ld c, b + jr l_find_storage_dev_00105 +l_find_storage_dev_00103: +;source-doc/base-drv/hbios-driver-storage.c:10: return -1; + ld l,$ff +l_find_storage_dev_00107: +;source-doc/base-drv/hbios-driver-storage.c:11: } + ret +_hbios_usbstore_devs: + DEFB +$00 + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 diff --git a/Source/HBIOS/ch376-native/base-drv/protocol.c.s b/Source/HBIOS/ch376-native/base-drv/protocol.c.s new file mode 100644 index 00000000..4a5425a1 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/protocol.c.s @@ -0,0 +1,482 @@ +; +; Generated from source-doc/base-drv/protocol.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/protocol.c:25: * +; --------------------------------- +; Function usbtrn_get_descriptor +; --------------------------------- +_usbtrn_get_descriptor: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/protocol.c:28: */ + ld hl,0 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cmd_get_dev_descriptr + ldir +;source-doc/base-drv/protocol.c:29: usb_error usbtrn_get_descriptor(device_descriptor *const buffer) { + ld (ix-2),$08 + xor a + ld (ix-1),a +;source-doc/base-drv/protocol.c:31: setup_packet cmd; + ld c,(ix+4) + ld b,(ix+5) + push bc + push bc + ld e,c + ld d,b + ld a,$08 + push af + inc sp + xor a + push af + inc sp + push de + ld hl,8 + add hl, sp + push hl + call _usb_control_transfer + pop af + pop af + pop af + ld a, l + pop de + pop bc + ld l, a +;source-doc/base-drv/protocol.c:33: cmd.wLength = 8; + or a + jr NZ,l_usbtrn_get_descriptor_00103 +;source-doc/base-drv/protocol.c:35: result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, 8); + push de + push bc + ld hl,4 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cmd_get_dev_descriptr + ldir + pop bc + pop de +;source-doc/base-drv/protocol.c:36: + ld (ix-2),$12 + xor a + ld (ix-1),a +;source-doc/base-drv/protocol.c:37: CHECK(result); + ld hl,7 + add hl, bc + ld a, (hl) + push af + inc sp + xor a + push af + inc sp + push de + ld hl,4 + add hl, sp + push hl + call _usb_control_transfer + pop af + pop af + pop af +;source-doc/base-drv/protocol.c:41: result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, buffer->bMaxPacketSize0); +l_usbtrn_get_descriptor_00103: +;source-doc/base-drv/protocol.c:42: +;source-doc/base-drv/protocol.c:43: RETURN_CHECK(result); + ld sp, ix + pop ix + ret +_cmd_get_dev_descriptr: + DEFB +$80 + DEFB +$06 + DEFB +$00 + DEFB +$01 + DEFB +$00 + DEFB +$00 + DEFW +$0008 +;source-doc/base-drv/protocol.c:47: } +; --------------------------------- +; Function usbtrn_get_descriptor2 +; --------------------------------- +_usbtrn_get_descriptor2: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/protocol.c:51: * + ld hl,0 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cmd_get_dev_descriptr + ldir +;source-doc/base-drv/protocol.c:52: * @param buffer the buffer to store the device descriptor in + ld (ix-2),$08 + xor a + ld (ix-1),a +;source-doc/base-drv/protocol.c:54: */ + ld c,(ix+4) + ld b,(ix+5) + push bc + push bc + ld e,c + ld d,b + ld h,$08 + ld l,(ix+6) + push hl + push de + ld hl,8 + add hl, sp + push hl + call _usb_control_transfer + pop af + pop af + pop af + ld a, l + pop de + pop bc + ld l, a +;source-doc/base-drv/protocol.c:56: usb_error result; + or a + jr NZ,l_usbtrn_get_descriptor2_00103 +;source-doc/base-drv/protocol.c:58: setup_packet cmd; + push de + push bc + ld hl,4 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cmd_get_dev_descriptr + ldir + pop bc + pop de +;source-doc/base-drv/protocol.c:59: cmd = cmd_get_dev_descriptr; + ld (ix-2),$12 + xor a + ld (ix-1),a +;source-doc/base-drv/protocol.c:60: cmd.wLength = 8; + ld hl,7 + add hl, bc + ld h,(hl) + ld l,(ix+6) + push hl + push de + ld hl,4 + add hl, sp + push hl + call _usb_control_transfer + pop af + pop af + pop af +;source-doc/base-drv/protocol.c:61: +l_usbtrn_get_descriptor2_00103: +;source-doc/base-drv/protocol.c:62: result = usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, 8); +;source-doc/base-drv/protocol.c:63: + ld sp, ix + pop ix + ret +;source-doc/base-drv/protocol.c:69: done: +; --------------------------------- +; Function usbtrn_set_address +; --------------------------------- +_usbtrn_set_address: + push ix + ld ix,0 + add ix,sp + push af + push af + push af + push af + ld c, l +;source-doc/base-drv/protocol.c:71: } + push bc + ld hl,2 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cmd_set_device_address + ldir + pop bc +;source-doc/base-drv/protocol.c:72: + ld (ix-6),c +;source-doc/base-drv/protocol.c:74: + xor a + push af + inc sp + xor a + push af + inc sp + ld hl,$0000 + push hl + ld hl,4 + add hl, sp + push hl + call _usb_control_transfer +;source-doc/base-drv/protocol.c:75: /** + ld sp,ix + pop ix + ret +_cmd_set_device_address: + DEFB +$00 + DEFB +$05 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFW +$0000 +;source-doc/base-drv/protocol.c:81: usb_error usbtrn_set_address(const uint8_t device_address) __z88dk_fastcall { +; --------------------------------- +; Function usbtrn_set_config +; --------------------------------- +_usbtrn_set_config: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/protocol.c:83: cmd = cmd_set_device_address; + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$0008 + ld hl,_cmd_set_configuration + ldir + pop bc +;source-doc/base-drv/protocol.c:84: cmd.bValue[0] = device_address; + ld a,(ix+6) + ld (ix-6),a +;source-doc/base-drv/protocol.c:86: return usb_control_transfer(&cmd, 0, 0, 0); + ld h,(ix+5) + ld l,(ix+4) + push hl + ld hl,$0000 + push hl + push bc + call _usb_control_transfer +;source-doc/base-drv/protocol.c:87: } + ld sp,ix + pop ix + ret +_cmd_set_configuration: + DEFB +$00 + DEFB +$09 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFW +$0000 +;source-doc/base-drv/protocol.c:93: * +; --------------------------------- +; Function usbtrn_get_config_desc +; --------------------------------- +_usbtrn_get_config_desc: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/protocol.c:99: cmd = cmd_set_configuration; + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$0008 + ld hl,_cmd_get_config_desc + ldir + pop bc +;source-doc/base-drv/protocol.c:100: cmd.bValue[0] = configuration; + ld a,(ix+6) + ld (ix-6),a +;source-doc/base-drv/protocol.c:101: + ld hl,$0006 + add hl, bc + ld e,(ix+7) + xor a + ld (hl), e + inc hl + ld (hl), a +;source-doc/base-drv/protocol.c:103: } + ld e,(ix+4) + ld d,(ix+5) + ld h,(ix+9) + ld l,(ix+8) + push hl + push de + push bc + call _usb_control_transfer +;source-doc/base-drv/protocol.c:104: + ld sp,ix + pop ix + ret +_cmd_get_config_desc: + DEFB +$80 + DEFB +$06 + DEFB +$00 + DEFB +$02 + DEFB +$00 + DEFB +$00 + DEFW +$0000 +;source-doc/base-drv/protocol.c:106: +; --------------------------------- +; Function usbtrn_gfull_cfg_desc +; --------------------------------- +_usbtrn_gfull_cfg_desc: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/protocol.c:114: * @param max_packet_size the max packet size for control transfers (endpoint 0) + ld c,(ix+8) + ld b,(ix+9) + push bc + ld a,(ix+6) + push af + inc sp + ld d,(ix+5) + ld e,$09 + push de + ld a,(ix+4) + push af + inc sp + push bc + call _usbtrn_get_config_desc + pop af + pop af + pop af + pop bc + ld a, l + or a + jr NZ,l_usbtrn_gfull_cfg_desc_00107 +;source-doc/base-drv/protocol.c:116: */ + ld l,(ix+8) + ld h,(ix+9) + inc hl + inc hl + ld d, (hl) +;source-doc/base-drv/protocol.c:117: usb_error usbtrn_get_config_desc(config_descriptor *const buffer, + ld a,(ix+7) + sub d + jr NC,l_usbtrn_gfull_cfg_desc_00104 +;source-doc/base-drv/protocol.c:118: const uint8_t config_index, + ld d,(ix+7) +l_usbtrn_gfull_cfg_desc_00104: +;source-doc/base-drv/protocol.c:120: const uint8_t device_address, + ld h,(ix+6) + ld l,(ix+5) + push hl + ld e,(ix+4) + push de + push bc + call _usbtrn_get_config_desc + pop af + pop af + pop af + ld a, l +;source-doc/base-drv/protocol.c:122: setup_packet cmd; + or a + jr NZ,l_usbtrn_gfull_cfg_desc_00107 + ld l,a +;source-doc/base-drv/protocol.c:123: cmd = cmd_get_config_desc; +;source-doc/base-drv/protocol.c:124: cmd.bValue[0] = config_index; +l_usbtrn_gfull_cfg_desc_00107: +;source-doc/base-drv/protocol.c:125: cmd.wLength = (uint16_t)buffer_size; + pop ix + ret +;source-doc/base-drv/protocol.c:129: +; --------------------------------- +; Function usbtrn_clr_ep_halt +; --------------------------------- +_usbtrn_clr_ep_halt: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/base-drv/protocol.c:131: const uint8_t device_address, + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$0008 + ld hl,_usb_cmd_clr_ep_halt + ldir + pop bc +;source-doc/base-drv/protocol.c:132: const uint8_t max_packet_size, + ld a,(ix+4) + ld (ix-4),a +;source-doc/base-drv/protocol.c:134: uint8_t *const buffer) { + ld h,(ix+6) + ld l,(ix+5) + push hl + ld hl,$0000 + push hl + push bc + call _usb_control_transfer +;source-doc/base-drv/protocol.c:135: usb_error result; + ld sp,ix + pop ix + ret +_usb_cmd_clr_ep_halt: + DEFB +$02 + DEFB +$01 + DEFB +$00 + DEFB +$00 + DEFB +$ff + DEFB +$00 + DEFW +$0000 diff --git a/Source/HBIOS/ch376-native/base-drv/transfers.c.s b/Source/HBIOS/ch376-native/base-drv/transfers.c.s new file mode 100644 index 00000000..e6b015fe --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/transfers.c.s @@ -0,0 +1,311 @@ +; +; Generated from source-doc/base-drv/transfers.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/transfers.c:23: * See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer +; --------------------------------- +; Function usb_control_transfer +; --------------------------------- +_usb_control_transfer: + push ix + ld ix,0 + add ix,sp + push af + push af +;source-doc/base-drv/transfers.c:28: * @param max_packet_size Maximum packet size for endpoint + ld hl,0 + add hl, sp + set 0, (hl) + ld hl,0 + add hl, sp + ld a, (hl) + and $f1 + ld (hl), a + ld c,(ix+9) + ld b,$00 + ld hl,1 + add hl, sp + ld (hl), c + inc hl + ld a, b + and $03 + ld e, a + ld a, (hl) + and $fc + or e + ld (hl), a +;source-doc/base-drv/transfers.c:30: */ + ld c,(ix+4) + ld b,(ix+5) + ld a, (bc) + and $80 +;source-doc/base-drv/transfers.c:32: void *const buffer, + ld (ix-1),a + or a + jr Z,l_usb_control_transfer_00102 + ld a,(ix+7) + or (ix+6) + jr NZ,l_usb_control_transfer_00102 +;source-doc/base-drv/transfers.c:33: const uint8_t device_address, + ld l,$0f + jp l_usb_control_transfer_00114 +l_usb_control_transfer_00102: +;source-doc/base-drv/transfers.c:35: usb_error result; + push bc + call _critical_begin +;source-doc/base-drv/transfers.c:37: + ld l,(ix+8) + call _ch_set_usb_address + pop bc +;source-doc/base-drv/transfers.c:39: + ld e,(ix+4) + ld d,(ix+5) + push bc + ld a,$08 + push af + inc sp + push de + call _ch_write_data + pop af + inc sp +;source-doc/base-drv/transfers.c:40: if (transferIn && buffer == 0) + call _ch_issue_token_setup +;source-doc/base-drv/transfers.c:41: return USB_ERR_OTHER; + call _ch_short_get_status + pop bc +;source-doc/base-drv/transfers.c:42: + ld a, l + or a + jr NZ,l_usb_control_transfer_00113 +;source-doc/base-drv/transfers.c:44: + ld hl,6 + add hl, bc + ld c, (hl) + inc hl +;source-doc/base-drv/transfers.c:47: ch_write_data((const uint8_t *)cmd_packet, sizeof(setup_packet)); + ld a,(hl) + ld b,a + or c + jr Z,l_usb_control_transfer_00116 + ld hl,0 + add hl, sp + ld e,(ix+6) + ld d,(ix+7) + ld a,(ix-1) + or a + jr Z,l_usb_control_transfer_00118 + push hl + push bc + push de + call _ch_data_in_transfer + pop af + pop af + pop af + jr l_usb_control_transfer_00119 +l_usb_control_transfer_00118: + push hl + push bc + push de + call _ch_data_out_transfer + pop af + pop af + pop af +l_usb_control_transfer_00119: + jr l_usb_control_transfer_00117 +l_usb_control_transfer_00116: +;source-doc/base-drv/transfers.c:48: ch_issue_token_setup(); + ld l,$00 +l_usb_control_transfer_00117: +;source-doc/base-drv/transfers.c:50: CHECK(result); + ld a, l + or a + jr NZ,l_usb_control_transfer_00113 +;source-doc/base-drv/transfers.c:52: const uint16_t length = cmd_packet->wLength; + ld a,(ix-1) + or a + jr Z,l_usb_control_transfer_00112 +;source-doc/base-drv/transfers.c:53: + ld l,$2c + call _ch_command +;source-doc/base-drv/transfers.c:54: result = length != 0 + ld a,$00 + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/transfers.c:55: ? (transferIn ? ch_data_in_transfer(buffer, length, &endpoint) : ch_data_out_transfer(buffer, length, &endpoint)) + call _ch_issue_token_out_ep0 +;source-doc/base-drv/transfers.c:56: : USB_ERR_OK; + call _ch_long_get_status +;source-doc/base-drv/transfers.c:58: CHECK(result) + ld a,l + or a + jr Z,l_usb_control_transfer_00108 + sub $02 + jr NZ,l_usb_control_transfer_00113 +l_usb_control_transfer_00108: +;source-doc/base-drv/transfers.c:59: + ld l,$00 +;source-doc/base-drv/transfers.c:60: if (transferIn) { + jr l_usb_control_transfer_00113 +;source-doc/base-drv/transfers.c:63: ch_issue_token_out_ep0(); +l_usb_control_transfer_00112: +;source-doc/base-drv/transfers.c:66: if (result == USB_ERR_OK || result == USB_ERR_STALL) { + call _ch_issue_token_in_ep0 +;source-doc/base-drv/transfers.c:67: result = USB_ERR_OK; + call _ch_long_get_status +;source-doc/base-drv/transfers.c:71: RETURN_CHECK(result); +l_usb_control_transfer_00113: +;source-doc/base-drv/transfers.c:72: } + push hl + call _critical_end + pop hl +;source-doc/base-drv/transfers.c:73: +l_usb_control_transfer_00114: +;source-doc/base-drv/transfers.c:74: ch_issue_token_in_ep0(); + ld sp, ix + pop ix + ret +;source-doc/base-drv/transfers.c:79: done: +; --------------------------------- +; Function usb_data_in_transfer +; --------------------------------- +_usb_data_in_transfer: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/transfers.c:81: return result; + call _critical_begin +;source-doc/base-drv/transfers.c:83: + ld l,(ix+8) + call _ch_set_usb_address +;source-doc/base-drv/transfers.c:85: * @brief Perform a USB data in on the specified endpoint + ld l,(ix+9) + ld h,(ix+10) + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _ch_data_in_transfer + pop af + pop af +;source-doc/base-drv/transfers.c:87: * @param buffer the buffer to receive the data + ex (sp),hl + call _critical_end + pop hl +;source-doc/base-drv/transfers.c:89: * @param device_address the usb address of the device +;source-doc/base-drv/transfers.c:90: * @param endpoint the usb endpoint to receive from (toggle of endpoint is updated) + pop ix + ret +;source-doc/base-drv/transfers.c:95: usb_error result; +; --------------------------------- +; Function usb_data_in_transfer_n +; --------------------------------- +_usb_data_in_transfer_n: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/transfers.c:98: ch_set_usb_address(device_address); + call _critical_begin +;source-doc/base-drv/transfers.c:100: result = ch_data_in_transfer(buffer, buffer_size, endpoint); + ld l,(ix+8) + call _ch_set_usb_address +;source-doc/base-drv/transfers.c:102: critical_end(); + ld l,(ix+9) + ld h,(ix+10) + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _ch_data_in_transfer_n + pop af + pop af +;source-doc/base-drv/transfers.c:104: return result; + ex (sp),hl + call _critical_end + pop hl +;source-doc/base-drv/transfers.c:106: +;source-doc/base-drv/transfers.c:107: /** + pop ix + ret +;source-doc/base-drv/transfers.c:112: * @param device_address the usb address of the device +; --------------------------------- +; Function usb_data_out_transfer +; --------------------------------- +_usb_data_out_transfer: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/transfers.c:114: * @return usb_error USB_ERR_OK if all good, otherwise specific error code + call _critical_begin +;source-doc/base-drv/transfers.c:116: usb_error + ld l,(ix+8) + call _ch_set_usb_address +;source-doc/base-drv/transfers.c:118: usb_error result; + ld l,(ix+9) + ld h,(ix+10) + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _ch_data_out_transfer + pop af + pop af +;source-doc/base-drv/transfers.c:120: critical_begin(); + ex (sp),hl + call _critical_end + pop hl +;source-doc/base-drv/transfers.c:122: ch_set_usb_address(device_address); +;source-doc/base-drv/transfers.c:123: + pop ix + ret diff --git a/Source/HBIOS/ch376-native/base-drv/usb-base-drv.c.s b/Source/HBIOS/ch376-native/base-drv/usb-base-drv.c.s new file mode 100644 index 00000000..4af2d4cc --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/usb-base-drv.c.s @@ -0,0 +1,224 @@ +; +; Generated from source-doc/base-drv/usb-base-drv.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/usb-base-drv.c:7: static usb_error usb_host_bus_reset(void) { +; --------------------------------- +; Function usb_host_bus_reset +; --------------------------------- +_usb_host_bus_reset: +;source-doc/base-drv/usb-base-drv.c:8: ch_cmd_set_usb_mode(CH_MODE_HOST); + ld l,$06 + call _ch_cmd_set_usb_mode +;source-doc/base-drv/usb-base-drv.c:9: delay_20ms(); + call _delay_20ms +;source-doc/base-drv/usb-base-drv.c:11: ch_cmd_set_usb_mode(CH_MODE_HOST_RESET); + ld l,$07 + call _ch_cmd_set_usb_mode +;source-doc/base-drv/usb-base-drv.c:12: delay_20ms(); + call _delay_20ms +;source-doc/base-drv/usb-base-drv.c:14: ch_cmd_set_usb_mode(CH_MODE_HOST); + ld l,$06 + call _ch_cmd_set_usb_mode +;source-doc/base-drv/usb-base-drv.c:15: delay_20ms(); + call _delay_20ms +;source-doc/base-drv/ch376.h:108: #define TRACE_USB_ERROR(result) + ld l,$0b + call _ch_command +;source-doc/base-drv/ch376.h:109: + ld a,$25 + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/ch376.h:110: #endif + ld a,$df + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/base-drv/usb-base-drv.c:19: return USB_ERR_OK; + ld l,$00 +;source-doc/base-drv/usb-base-drv.c:20: } + ret +;source-doc/base-drv/usb-base-drv.c:24: uint16_t usb_init(uint8_t state) __z88dk_fastcall { +; --------------------------------- +; Function usb_init +; --------------------------------- +_usb_init: +;source-doc/base-drv/usb-base-drv.c:27: USB_MODULE_LEDS = $03; + ld a,$03 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/usb-base-drv.c:29: if (state == 0) { + ld a, l + or a + jr NZ,l_usb_init_00104 +;source-doc/base-drv/usb-base-drv.c:30: ch_cmd_reset_all(); + call _ch_cmd_reset_all +;source-doc/base-drv/usb-base-drv.c:31: delay_medium(); + call _delay_medium +;source-doc/base-drv/usb-base-drv.c:33: if (!ch_probe()) { + call _ch_probe + ld a, l +;source-doc/base-drv/usb-base-drv.c:34: USB_MODULE_LEDS = $00; + or a + jr NZ,l_usb_init_00102 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/usb-base-drv.c:35: return $FF00; + ld hl,$ff00 + jp l_usb_init_00113 +l_usb_init_00102: +;source-doc/base-drv/usb-base-drv.c:37: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/usb-base-drv.c:38: return 1; + ld hl,$0001 + jr l_usb_init_00113 +l_usb_init_00104: +;source-doc/base-drv/usb-base-drv.c:41: if (state == 1) { + ld a, l + dec a + jr NZ,l_usb_init_00106 +;source-doc/base-drv/usb-base-drv.c:42: r = ch_cmd_get_ic_version(); + call _ch_cmd_get_ic_version +;source-doc/base-drv/usb-base-drv.c:44: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/usb-base-drv.c:45: return (uint16_t)r << 8 | 2; + xor a + ld h, l + ld l,$02 + jr l_usb_init_00113 +l_usb_init_00106: +;source-doc/base-drv/usb-base-drv.c:48: if (state == 2) { + ld a, l + sub $02 + jr NZ,l_usb_init_00159 + ld a,$01 + jr l_usb_init_00160 +l_usb_init_00159: + xor a +l_usb_init_00160: + ld c,a + or a + jr Z,l_usb_init_00110 +;source-doc/base-drv/usb-base-drv.c:49: usb_host_bus_reset(); + call _usb_host_bus_reset +;source-doc/base-drv/usb-base-drv.c:51: r = ch_very_short_status(); + call _ch_very_short_status + ld a, l +;source-doc/base-drv/usb-base-drv.c:53: if (r != USB_INT_CONNECT) { + sub $81 + jr Z,l_usb_init_00108 +;source-doc/base-drv/usb-base-drv.c:54: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/usb-base-drv.c:55: return 2; + ld hl,$0002 + jr l_usb_init_00113 +l_usb_init_00108: +;source-doc/base-drv/usb-base-drv.c:58: return 3; + ld hl,$0003 + jr l_usb_init_00113 +l_usb_init_00110: +;source-doc/base-drv/usb-base-drv.c:61: memset(get_usb_work_area(), 0, sizeof(_usb_state)); + ld b,$32 + ld hl,_x + jr l_usb_init_00163 +l_usb_init_00162: + ld (hl),$00 + inc hl +l_usb_init_00163: + ld (hl),$00 + inc hl + djnz l_usb_init_00162 +;source-doc/base-drv/usb-base-drv.c:62: if (state != 2) { + bit 0, c + jr NZ,l_usb_init_00112 +;source-doc/base-drv/usb-base-drv.c:63: usb_host_bus_reset(); + call _usb_host_bus_reset +;source-doc/base-drv/usb-base-drv.c:64: delay_medium(); + call _delay_medium +l_usb_init_00112: +;source-doc/base-drv/usb-base-drv.c:66: enumerate_all_devices(); + call _enumerate_all_devices +;source-doc/base-drv/usb-base-drv.c:67: USB_MODULE_LEDS = $00; + ld a,$00 + ld bc,_USB_MODULE_LEDS + out (c), a +;source-doc/base-drv/usb-base-drv.c:68: return (uint16_t)count_of_devices() << 8 | 4; + call _count_of_devices + ld h, a + xor a + ld l,$04 +l_usb_init_00113: +;source-doc/base-drv/usb-base-drv.c:69: } + ret +;source-doc/base-drv/usb-base-drv.c:71: usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba) { +; --------------------------------- +; Function usb_scsi_seek +; --------------------------------- +_usb_scsi_seek: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/usb-base-drv.c:72: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config +;source-doc/base-drv/usb-base-drv.c:74: dev->current_lba = lba; + ld hl,$000c + add hl, de + ex de, hl + ld hl,6 + add hl, sp + ld bc,$0004 + ldir +;source-doc/base-drv/usb-base-drv.c:75: return USB_ERR_OK; + ld l,$00 +;source-doc/base-drv/usb-base-drv.c:76: } + pop ix + ret diff --git a/Source/HBIOS/ch376-native/base-drv/usb_state.c.s b/Source/HBIOS/ch376-native/base-drv/usb_state.c.s new file mode 100644 index 00000000..754109d8 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/usb_state.c.s @@ -0,0 +1,258 @@ +; +; Generated from source-doc/base-drv/usb_state.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/base-drv/usb_state.c:17: uint8_t count_of_devices(void) __sdcccall(1) { +; --------------------------------- +; Function count_of_devices +; --------------------------------- +_count_of_devices: +;source-doc/base-drv/usb_state.c:18: _usb_state *const p = get_usb_work_area(); +;source-doc/base-drv/usb_state.c:22: const device_config *p_config = first_device_config(p); + ld hl,_x + call _first_device_config +;source-doc/base-drv/usb_state.c:23: while (p_config) { + ld c,$00 +l_count_of_devices_00104: + ld a, d + or e + jr Z,l_count_of_devices_00106 +;source-doc/base-drv/usb_state.c:24: const uint8_t type = p_config->type; + ld l, e + ld h, d + ld a, (hl) + and $0f +;source-doc/base-drv/usb_state.c:26: if (type != USB_IS_HUB && type) + cp $0f + jr Z,l_count_of_devices_00102 + or a + jr Z,l_count_of_devices_00102 +;source-doc/base-drv/usb_state.c:27: count++; + inc c +l_count_of_devices_00102: +;source-doc/base-drv/usb_state.c:30: p_config = next_device_config(p, p_config); + push bc + ld hl,_x + call _next_device_config + pop bc + jr l_count_of_devices_00104 +l_count_of_devices_00106: +;source-doc/base-drv/usb_state.c:33: return count; + ld a, c +;source-doc/base-drv/usb_state.c:34: } + ret +_device_config_sizes: + DEFB +$00 + DEFB +$10 + DEFB +$10 + DEFB +$0c + DEFB +$06 + DEFB $00 + DEFB $00 +;source-doc/base-drv/usb_state.c:37: device_config *find_first_free(void) { +; --------------------------------- +; Function find_first_free +; --------------------------------- +_find_first_free: +;source-doc/base-drv/usb_state.c:38: _usb_state *const boot_state = get_usb_work_area(); +;source-doc/base-drv/usb_state.c:41: device_config *p = first_device_config(boot_state); + ld hl,_x + call _first_device_config +;source-doc/base-drv/usb_state.c:42: while (p) { +l_find_first_free_00103: + ld a, d + or e + jr Z,l_find_first_free_00105 +;source-doc/base-drv/usb_state.c:43: if (p->type == 0) + ld l, e + ld h, d + ld a, (hl) + and $0f + jr NZ,l_find_first_free_00102 +;source-doc/base-drv/usb_state.c:44: return p; + ex de, hl + jr l_find_first_free_00106 +l_find_first_free_00102: +;source-doc/base-drv/usb_state.c:46: p = next_device_config(boot_state, p); + ld hl,_x + call _next_device_config + jr l_find_first_free_00103 +l_find_first_free_00105: +;source-doc/base-drv/usb_state.c:49: return NULL; + ld hl,$0000 +l_find_first_free_00106: +;source-doc/base-drv/usb_state.c:50: } + ret +;source-doc/base-drv/usb_state.c:52: device_config *first_device_config(const _usb_state *const p) __sdcccall(1) { return (device_config *)&p->device_configs[0]; } +; --------------------------------- +; Function first_device_config +; --------------------------------- +_first_device_config: + ex de, hl + inc de + inc de + ret +;source-doc/base-drv/usb_state.c:54: device_config *next_device_config(const _usb_state *const usb_state, const device_config *const p) __sdcccall(1) { +; --------------------------------- +; Function next_device_config +; --------------------------------- +_next_device_config: + ld c, l + ld b, h +;source-doc/base-drv/usb_state.c:55: if (p->type == 0) + ld l, e + ld h, d + ld a, (hl) + and $0f + jr NZ,l_next_device_config_00102 +;source-doc/base-drv/usb_state.c:56: return NULL; + ld de,$0000 + jr l_next_device_config_00105 +l_next_device_config_00102: +;source-doc/base-drv/usb_state.c:58: const uint8_t size = device_config_sizes[p->type]; + ld l, e + ld h, d + ld a, (hl) + and $0f + add a, +((_device_config_sizes) & $FF) + ld l, a + ld a,$00 + adc a, +((_device_config_sizes) / 256) + ld h, a + ld a, (hl) +;source-doc/base-drv/usb_state.c:65: const uint8_t *_p = (uint8_t *)p; +;source-doc/base-drv/usb_state.c:66: device_config *const result = (device_config *)(_p + size); + add a, e + ld e, a + ld a,$00 + adc a, d + ld d, a +;source-doc/base-drv/usb_state.c:68: if (result >= (device_config *)&usb_state->device_configs_end) + ld hl,$0062 + add hl, bc + ld a, e + sub l + ld a, d + sbc a, h + ret C +;source-doc/base-drv/usb_state.c:69: return NULL; + ld de,$0000 +;source-doc/base-drv/usb_state.c:71: return result; +l_next_device_config_00105: +;source-doc/base-drv/usb_state.c:72: } + ret +;source-doc/base-drv/usb_state.c:74: device_config *get_usb_device_config(const uint8_t device_index) __sdcccall(1) { +; --------------------------------- +; Function get_usb_device_config +; --------------------------------- +_get_usb_device_config: + ld c, a +;source-doc/base-drv/usb_state.c:75: const _usb_state *const usb_state = get_usb_work_area(); +;source-doc/base-drv/usb_state.c:79: for (device_config *p = first_device_config(usb_state); p; p = next_device_config(usb_state, p)) { + push bc + ld hl,_x + call _first_device_config + pop bc + ld b,$01 +l_get_usb_device_config_00107: + ld a, d + or e + jr Z,l_get_usb_device_config_00105 +;source-doc/base-drv/usb_state.c:80: if (p->type != USB_NOT_SUPPORTED) { + ld l, e + ld h, d + ld a, (hl) + and $0f + jr Z,l_get_usb_device_config_00108 +;source-doc/base-drv/usb_state.c:81: if (counter == device_index) + ld a, c + sub b +;source-doc/base-drv/usb_state.c:82: return p; + jr Z,l_get_usb_device_config_00109 +;source-doc/base-drv/usb_state.c:83: counter++; + inc b +l_get_usb_device_config_00108: +;source-doc/base-drv/usb_state.c:79: for (device_config *p = first_device_config(usb_state); p; p = next_device_config(usb_state, p)) { + push bc + ld hl,_x + call _next_device_config + pop bc + jr l_get_usb_device_config_00107 +l_get_usb_device_config_00105: +;source-doc/base-drv/usb_state.c:87: return NULL; // is not a usb device + ld de,$0000 +l_get_usb_device_config_00109: +;source-doc/base-drv/usb_state.c:88: } + ret +;source-doc/base-drv/usb_state.c:90: usb_device_type usb_get_device_type(const uint16_t dev_index) { +; --------------------------------- +; Function usb_get_device_type +; --------------------------------- +_usb_get_device_type: + push ix + ld ix,0 + add ix,sp +;source-doc/base-drv/usb_state.c:91: const device_config *dev = get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config + ld l, e +;source-doc/base-drv/usb_state.c:93: if (dev == NULL) + ld a,d + ld h,a + or e + jr NZ,l_usb_get_device_type_00102 +;source-doc/base-drv/usb_state.c:94: return -1; + ld l,$ff + jr l_usb_get_device_type_00103 +l_usb_get_device_type_00102: +;source-doc/base-drv/usb_state.c:96: return dev->type; + ld a, (hl) + and $0f + ld l, a +l_usb_get_device_type_00103: +;source-doc/base-drv/usb_state.c:97: } + pop ix + ret diff --git a/Source/HBIOS/ch376-native/base-drv/work-area.c.s b/Source/HBIOS/ch376-native/base-drv/work-area.c.s new file mode 100644 index 00000000..00b5a957 --- /dev/null +++ b/Source/HBIOS/ch376-native/base-drv/work-area.c.s @@ -0,0 +1,149 @@ +; +; Generated from source-doc/base-drv/work-area.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_x: + DEFS 99 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +_x: + DEFB $00 + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB +$00 diff --git a/Source/HBIOS/ch376-native/cruntime.asm b/Source/HBIOS/ch376-native/cruntime.asm new file mode 100644 index 00000000..74426810 --- /dev/null +++ b/Source/HBIOS/ch376-native/cruntime.asm @@ -0,0 +1,133 @@ + +_memset_callee: + pop af ; return address + pop bc ; address to be set + pop de ; value to be set + pop hl ; number of bytes to set + push af ; restore return address + + ld a, b + or c + ret z + + ld a, e + push hl + pop de + ret z + + ld (hl), a + inc de + dec bc + ld a, b + or c + ret z + + push hl + ldir + pop hl + ret + +_memcpy_callee: + + pop af + pop bc + pop hl + pop de + push af + + + ; enter : bc = size_t n + ; hl = void *s2 = src + ; de = void *s1 = dst + ; + ; exit : hl = void *s1 = dst + ; de = ptr in s1 to one byte past last byte copied + ; bc = 0 + ; carry reset + ; + ; uses : af, bc, de, hl + + ld a, b + or c + jr z, zero_n + +asm0_memcpy: + push de + ldir + pop hl + or a + ret + +zero_n: + push de + pop hl + ret + +.if 0 +; required if --optimise-for-size is targetted +; but there appears to be a regression that stop the driver from working +; if optimised for size is selected +___sdcc_enter_ix: + ex (sp), ix + push ix + ld ix, 2 + add ix, sp + ret + +____sdcc_lib_setmem_hl: +l_setmem_hl: + ret + +____sdcc_load_debc_mhl: + ld c, (hl) + inc hl + ld b, (hl) + inc hl + ld e, (hl) + inc hl + ld d, (hl) + ret + +____sdcc_4_push_hlix: + pop af + push af + push af + push af + + push de + + push ix + pop de + + add hl, de + + ex de, hl + + ld hl, 2+2 + add hl, sp + + ex de, hl + + ldi + ldi + ldi + ld a, (hl) + ld (de), a + + inc bc + inc bc + inc bc + + pop de + ret + +____sdcc_store_debc_mhl: + ld (hl), c + inc hl + ld (hl), b + inc hl + ld (hl), e + inc hl + ld (hl), d + ret +.endif diff --git a/Source/HBIOS/ch376-native/ez80-firmware.asm b/Source/HBIOS/ch376-native/ez80-firmware.asm new file mode 100644 index 00000000..2cce1a71 --- /dev/null +++ b/Source/HBIOS/ch376-native/ez80-firmware.asm @@ -0,0 +1,143 @@ +; delegate usb function to firmware of ez80 module + +; extern uint16_t usb_init(uint8_t state) __z88dk_fastcall; +_usb_init: + EZ80_EX_USB_INIT + RET + +; usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba) +_usb_scsi_seek: + ; iy+2 : dev_index + ; iy+4:5:6:7 : lba + LD IY, 0 + ADD IY, SP + EZ80_EXTN_IY_TO_MB_IY + + LD C, (IY+2) + LD_DE_IY_P_.L(4) ; LD.L DE, (IY+4) + LD L, (IY+7) + EZ80_EX_USB_STORAGE_SEEK + LD L, A + RET + +; usb_error usb_scsi_init(const uint16_t dev_index) +_usb_scsi_init: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + EZ80_EX_USB_SCSI_INIT + LD L, A + RET + +; usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer); +_usb_scsi_read: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + LD E, (IY+4) + LD D, (IY+5) + EZ80_EXTN_DE_TO_MB_DE + EZ80_EX_USB_SCSI_READ + LD L, A + RET + +; usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer) +_usb_scsi_write: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + LD E, (IY+4) + LD D, (IY+5) + EZ80_EXTN_DE_TO_MB_DE + EZ80_EX_USB_SCSI_WRITE + LD L, A + RET + +; usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *cap_result) +_usb_scsi_read_capacity: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + LD E, (IY+4) + LD D, (IY+5) + EZ80_EXTN_DE_TO_MB_DE + EZ80_EX_USB_SCSI_READ_CAP + LD L, A + RET + +; extern uint8_t usb_ufi_read(const uint16_t dev_index, uint8_t *const buffer) +_usb_ufi_read: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + LD E, (IY+4) + LD D, (IY+5) + EZ80_EXTN_DE_TO_MB_DE + EZ80_EX_USB_UFI_READ + LD L, A + RET + +;extern usb_error usb_ufi_write(const uint16_t dev_index, uint8_t *const buffer); +_usb_ufi_write: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + LD E, (IY+4) + LD D, (IY+5) + EZ80_EXTN_DE_TO_MB_DE + EZ80_EX_USB_UFI_WRITE + LD L, A + RET + +; extern uint32_t usb_ufi_get_cap(const uint16_t dev_index) +_usb_ufi_get_cap: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + EZ80_EXTN_DE_TO_MB_DE + EZ80_EX_USB_UFI_GET_CAP ; + + LD D, E ; convert E:uHL to DE:HL + EZ80_CPY_UHL_TO_EHL + RET + +; extern void usb_kyb_init(const uint8_t dev_index) __sdcccall(1); +_usb_kyb_init: + LD C, A + EZ80_EX_USB_KYB_INIT + RET + +; extern uint8_t usb_kyb_flush() __sdcccall(1); +_usb_kyb_flush: + EZ80_EX_USB_KYB_FLUSH + RET + +; extern uint8_t usb_kyb_status() __sdcccall(1); +_usb_kyb_status: + EZ80_EX_USB_KYB_STATUS + RET + +; extern uint16_t usb_kyb_read(); +; H = 0/1 set if char, L=>code +_usb_kyb_read: + EZ80_EX_USB_KYB_READ + LD H, A + RET + + +;usb_device_type usb_get_device_type(const uint16_t dev_index) +_usb_get_device_type: + LD IY, 0 + ADD IY, SP + + LD C, (IY+2) + EZ80_EX_USB_GET_DEV_TYPE + LD L, A + RET diff --git a/Source/HBIOS/ch376-native/keyboard.s b/Source/HBIOS/ch376-native/keyboard.s new file mode 100644 index 00000000..abc73e8a --- /dev/null +++ b/Source/HBIOS/ch376-native/keyboard.s @@ -0,0 +1,11 @@ +; Generated File -- not to be modify directly +#IF (!CHNATIVEEZ80) +#include "ch376-native/keyboard/class_hid.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/keyboard/class_hid_keyboard.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/keyboard/kyb_driver.c.s" +#ENDIF +#include "ch376-native/keyboard/kyb-init.c.s" diff --git a/Source/HBIOS/ch376-native/keyboard/.gitignore b/Source/HBIOS/ch376-native/keyboard/.gitignore new file mode 100644 index 00000000..f4cb8488 --- /dev/null +++ b/Source/HBIOS/ch376-native/keyboard/.gitignore @@ -0,0 +1 @@ +*.asm diff --git a/Source/HBIOS/ch376-native/keyboard/class_hid.c.s b/Source/HBIOS/ch376-native/keyboard/class_hid.c.s new file mode 100644 index 00000000..91dd09e8 --- /dev/null +++ b/Source/HBIOS/ch376-native/keyboard/class_hid.c.s @@ -0,0 +1,169 @@ +; +; Generated from source-doc/keyboard/class_hid.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/keyboard/class_hid.c:6: usb_error hid_set_protocol(const device_config_keyboard *const dev, const uint8_t protocol) __sdcccall(1) { +; --------------------------------- +; Function hid_set_protocol +; --------------------------------- +_hid_set_protocol: + push ix + ld ix,0 + add ix,sp + push af + push af + push af + push af +;source-doc/keyboard/class_hid.c:8: cmd = cmd_hid_set; + push hl + ex de,hl + ld hl,2 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cmd_hid_set + ldir + pop de +;source-doc/keyboard/class_hid.c:10: cmd.bRequest = HID_SET_PROTOCOL; + ld (ix-7),$0b +;source-doc/keyboard/class_hid.c:11: cmd.bValue[0] = protocol; + ld a,(ix+4) + ld (ix-6),a +;source-doc/keyboard/class_hid.c:13: return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size); + ld l, e + ld h, d + inc hl + ld b, (hl) + ex de, hl + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld c,a + push bc + ld hl,$0000 + push hl + ld hl,4 + add hl, sp + push hl + call _usb_control_transfer + pop af + pop af + pop af + ld a, l +;source-doc/keyboard/class_hid.c:14: } + ld sp, ix + pop ix + pop hl + inc sp + jp (hl) +_cmd_hid_set: + DEFB +$21 + DEFB +$0b + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFW +$0000 +;source-doc/keyboard/class_hid.c:16: usb_error hid_set_idle(const device_config_keyboard *const dev, const uint8_t duration) __sdcccall(1) { +; --------------------------------- +; Function hid_set_idle +; --------------------------------- +_hid_set_idle: + push ix + ld ix,0 + add ix,sp + push af + push af + push af + push af +;source-doc/keyboard/class_hid.c:18: cmd = cmd_hid_set; + push hl + ex de,hl + ld hl,2 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cmd_hid_set + ldir + pop de +;source-doc/keyboard/class_hid.c:20: cmd.bRequest = HID_SET_IDLE; + ld (ix-7),$0a +;source-doc/keyboard/class_hid.c:21: cmd.bValue[0] = duration; + ld a,(ix+4) + ld (ix-6),a +;source-doc/keyboard/class_hid.c:23: return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size); + ld l, e + ld h, d + inc hl + ld b, (hl) + ex de, hl + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld c,a + push bc + ld hl,$0000 + push hl + ld hl,4 + add hl, sp + push hl + call _usb_control_transfer + pop af + pop af + pop af + ld a, l +;source-doc/keyboard/class_hid.c:24: } + ld sp, ix + pop ix + pop hl + inc sp + jp (hl) diff --git a/Source/HBIOS/ch376-native/keyboard/class_hid_keyboard.c.s b/Source/HBIOS/ch376-native/keyboard/class_hid_keyboard.c.s new file mode 100644 index 00000000..5aaf2176 --- /dev/null +++ b/Source/HBIOS/ch376-native/keyboard/class_hid_keyboard.c.s @@ -0,0 +1,440 @@ +; +; Generated from source-doc/keyboard/class_hid_keyboard.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_scancodes_shift_table: + DEFS 128 +_scancodes_table: + DEFS 128 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/keyboard/class_hid_keyboard.c:334: }; +; --------------------------------- +; Function char_with_caps_lock +; --------------------------------- +_char_with_caps_lock: +;source-doc/keyboard/class_hid_keyboard.c:335: + bit 0, l +;source-doc/keyboard/class_hid_keyboard.c:336: static char char_with_caps_lock(const char c, const bool caps_lock_engaged) __sdcccall(1) { + jr Z,l_char_with_caps_lock_00109 +;source-doc/keyboard/class_hid_keyboard.c:338: return c; + cp $41 + jr C,l_char_with_caps_lock_00104 + cp $5b + jr NC,l_char_with_caps_lock_00104 +;source-doc/keyboard/class_hid_keyboard.c:339: + add a,$20 + jr l_char_with_caps_lock_00109 +l_char_with_caps_lock_00104: +;source-doc/keyboard/class_hid_keyboard.c:341: return c - 'A' + 'a'; + cp $61 + ret C + cp $7b + ret NC +;source-doc/keyboard/class_hid_keyboard.c:342: + add a,$e0 +;source-doc/keyboard/class_hid_keyboard.c:344: return c - 'a' + 'A'; +l_char_with_caps_lock_00109: +;source-doc/keyboard/class_hid_keyboard.c:345: + ret +;source-doc/keyboard/class_hid_keyboard.c:347: } +; --------------------------------- +; Function scancode_to_char +; --------------------------------- +_scancode_to_char: + push ix + ld ix,0 + add ix,sp +;source-doc/keyboard/class_hid_keyboard.c:348: + ld c,a + ld e,l + and $11 + jr Z,l_scancode_to_char_00118 +;source-doc/keyboard/class_hid_keyboard.c:349: char scancode_to_char(const uint8_t modifier_keys, const uint8_t code, const bool caps_lock_engaged) __sdcccall(1) { + ld a, e + sub $04 + jr C,l_scancode_to_char_00102 + ld a,$1d + sub e + jr C,l_scancode_to_char_00102 +;source-doc/keyboard/class_hid_keyboard.c:350: if ((modifier_keys & (KEY_MOD_LCTRL | KEY_MOD_RCTRL))) { + ld a, e + add a,$fd + jr l_scancode_to_char_00121 +l_scancode_to_char_00102: +;source-doc/keyboard/class_hid_keyboard.c:352: return code - 3; + ld a,e + cp $1f + jr Z,l_scancode_to_char_00104 + sub $2c + jr NZ,l_scancode_to_char_00105 +l_scancode_to_char_00104: +;source-doc/keyboard/class_hid_keyboard.c:353: + xor a + jr l_scancode_to_char_00121 +l_scancode_to_char_00105: +;source-doc/keyboard/class_hid_keyboard.c:355: return 0; + ld a, e + sub $2f + jr NZ,l_scancode_to_char_00108 +;source-doc/keyboard/class_hid_keyboard.c:356: + ld a,$1b + jr l_scancode_to_char_00121 +l_scancode_to_char_00108: +;source-doc/keyboard/class_hid_keyboard.c:358: return 27; + ld a, e + sub $31 + jr NZ,l_scancode_to_char_00110 +;source-doc/keyboard/class_hid_keyboard.c:359: + ld a,$1c + jr l_scancode_to_char_00121 +l_scancode_to_char_00110: +;source-doc/keyboard/class_hid_keyboard.c:361: return 28; + ld a, e + sub $30 + jr NZ,l_scancode_to_char_00112 +;source-doc/keyboard/class_hid_keyboard.c:362: + ld a,$1d + jr l_scancode_to_char_00121 +l_scancode_to_char_00112: +;source-doc/keyboard/class_hid_keyboard.c:364: return 29; + ld a, e + sub $23 + jr NZ,l_scancode_to_char_00114 +;source-doc/keyboard/class_hid_keyboard.c:365: + ld a,$1e + jr l_scancode_to_char_00121 +l_scancode_to_char_00114: +;source-doc/keyboard/class_hid_keyboard.c:367: return 30; + ld a, e + sub $2d + jr NZ,l_scancode_to_char_00118 +;source-doc/keyboard/class_hid_keyboard.c:368: + ld a,$1f + jr l_scancode_to_char_00121 +l_scancode_to_char_00118: +;source-doc/keyboard/class_hid_keyboard.c:371: } + ld a, c + and $22 + jr Z,l_scancode_to_char_00120 +;source-doc/keyboard/class_hid_keyboard.c:372: + ld d,$00 + ld hl,_scancodes_shift_table + add hl, de + ld a, (hl) + ld l,(ix+4) + call _char_with_caps_lock + jr l_scancode_to_char_00121 +l_scancode_to_char_00120: +;source-doc/keyboard/class_hid_keyboard.c:374: return char_with_caps_lock(scancodes_shift_table[code], caps_lock_engaged); + ld d,$00 + ld hl,_scancodes_table + add hl, de + ld a, (hl) + ld l,(ix+4) + call _char_with_caps_lock +l_scancode_to_char_00121: +;source-doc/keyboard/class_hid_keyboard.c:375: + pop ix + pop hl + inc sp + jp (hl) +_scancodes_shift_table: + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$41 + DEFB +$42 + DEFB +$43 + DEFB +$44 + DEFB +$45 + DEFB +$46 + DEFB +$47 + DEFB +$48 + DEFB +$49 + DEFB +$4a + DEFB +$4b + DEFB +$4c + DEFB +$4d + DEFB +$4e + DEFB +$4f + DEFB +$50 + DEFB +$51 + DEFB +$52 + DEFB +$53 + DEFB +$54 + DEFB +$55 + DEFB +$56 + DEFB +$57 + DEFB +$58 + DEFB +$59 + DEFB +$5a + DEFB +$21 + DEFB +$40 + DEFB +$23 + DEFB +$24 + DEFB +$25 + DEFB +$5e + DEFB +$26 + DEFB +$2a + DEFB +$28 + DEFB +$29 + DEFB +$0d + DEFB +$1b + DEFB +$08 + DEFB +$09 + DEFB +$20 + DEFB +$5f + DEFB +$2b + DEFB +$7b + DEFB +$7d + DEFB +$7c + DEFB +$7e + DEFB +$3a + DEFB +$22 + DEFB +$7e + DEFB +$3c + DEFB +$3e + DEFB +$3f + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$2f + DEFB +$2a + DEFB +$2d + DEFB +$2b + DEFB +$0d + DEFB +$31 + DEFB +$32 + DEFB +$33 + DEFB +$34 + DEFB +$35 + DEFB +$36 + DEFB +$37 + DEFB +$38 + DEFB +$39 + DEFB +$30 + DEFB +$2e + DEFB +$5c + DEFB +$00 + DEFB +$00 + DEFB +$3d + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +_scancodes_table: + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$61 + DEFB +$62 + DEFB +$63 + DEFB +$64 + DEFB +$65 + DEFB +$66 + DEFB +$67 + DEFB +$68 + DEFB +$69 + DEFB +$6a + DEFB +$6b + DEFB +$6c + DEFB +$6d + DEFB +$6e + DEFB +$6f + DEFB +$70 + DEFB +$71 + DEFB +$72 + DEFB +$73 + DEFB +$74 + DEFB +$75 + DEFB +$76 + DEFB +$77 + DEFB +$78 + DEFB +$79 + DEFB +$7a + DEFB +$31 + DEFB +$32 + DEFB +$33 + DEFB +$34 + DEFB +$35 + DEFB +$36 + DEFB +$37 + DEFB +$38 + DEFB +$39 + DEFB +$30 + DEFB +$0d + DEFB +$1b + DEFB +$08 + DEFB +$09 + DEFB +$20 + DEFB +$2d + DEFB +$3d + DEFB +$5b + DEFB +$5d + DEFB +$5c + DEFB +$23 + DEFB +$3b + DEFB +$27 + DEFB +$60 + DEFB +$2c + DEFB +$2e + DEFB +$2f + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$2f + DEFB +$2a + DEFB +$2d + DEFB +$2b + DEFB +$0d + DEFB +$31 + DEFB +$32 + DEFB +$33 + DEFB +$34 + DEFB +$35 + DEFB +$36 + DEFB +$37 + DEFB +$38 + DEFB +$39 + DEFB +$30 + DEFB +$2e + DEFB +$5c + DEFB +$00 + DEFB +$00 + DEFB +$3d + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 diff --git a/Source/HBIOS/ch376-native/keyboard/kyb-init.c.s b/Source/HBIOS/ch376-native/keyboard/kyb-init.c.s new file mode 100644 index 00000000..a85ad925 --- /dev/null +++ b/Source/HBIOS/ch376-native/keyboard/kyb-init.c.s @@ -0,0 +1,122 @@ +; +; Generated from source-doc/keyboard/kyb-init.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/keyboard/kyb-init.c:6: uint8_t keyboard_init(void) __sdcccall(1) { +; --------------------------------- +; Function keyboard_init +; --------------------------------- +_keyboard_init: + push ix + ld ix,0 + add ix,sp + dec sp +;source-doc/keyboard/kyb-init.c:7: uint8_t index = 1; +;source-doc/keyboard/kyb-init.c:9: do { + ld c,$01 + ld (ix-1),c +l_keyboard_init_00103: +;source-doc/keyboard/kyb-init.c:10: usb_device_type t = usb_get_device_type(index); + ld e, c + ld d,$00 + push bc + push de + push de + call _usb_get_device_type + pop af + ld a, l + pop de + pop bc +;source-doc/keyboard/kyb-init.c:12: if (t == USB_IS_KEYBOARD) { + sub $04 + jr NZ,l_keyboard_init_00104 +;source-doc/keyboard/kyb-init.c:13: print_string("\r\nUSB: KEYBOARD @ $"); + push de + ld hl,kyb_init_str_0 + call _print_string + pop de +;source-doc/keyboard/kyb-init.c:14: print_uint16(index); + ex de, hl + call _print_uint16 +;source-doc/keyboard/kyb-init.c:15: print_string(" $"); + ld hl,kyb_init_str_1 + call _print_string +;source-doc/keyboard/kyb-init.c:17: usb_kyb_init(index); + ld a,(ix-1) + call _usb_kyb_init +;source-doc/keyboard/kyb-init.c:18: return 1; + ld a,$01 + jr l_keyboard_init_00106 +l_keyboard_init_00104: +;source-doc/keyboard/kyb-init.c:20: } while (++index != MAX_NUMBER_OF_DEVICES + 1); + inc c + ld (ix-1),c + ld a, c + sub $07 + jr NZ,l_keyboard_init_00103 +;source-doc/keyboard/kyb-init.c:22: print_string("\r\nUSB: KEYBOARD: NOT FOUND$"); + ld hl,kyb_init_str_2 + call _print_string +;source-doc/keyboard/kyb-init.c:24: return 0; + xor a +l_keyboard_init_00106: +;source-doc/keyboard/kyb-init.c:25: } + inc sp + pop ix + ret +kyb_init_str_0: + DEFB $0d + DEFB $0a + DEFM "USB: KEYBOARD @ $" + DEFB $00 +kyb_init_str_1: + DEFM " $" + DEFB $00 +kyb_init_str_2: + DEFB $0d + DEFB $0a + DEFM "USB: KEYBOARD: NOT FOUND$" + DEFB $00 diff --git a/Source/HBIOS/ch376-native/keyboard/kyb_driver.c.s b/Source/HBIOS/ch376-native/keyboard/kyb_driver.c.s new file mode 100644 index 00000000..d6162fda --- /dev/null +++ b/Source/HBIOS/ch376-native/keyboard/kyb_driver.c.s @@ -0,0 +1,406 @@ +; +; Generated from source-doc/keyboard/kyb_driver.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_caps_lock_engaged: + DEFS 1 +_keyboard_config: + DEFS 2 +_buffer: + DEFS 8 +_write_index: + DEFS 1 +_read_index: + DEFS 1 +_report: + DEFS 8 +_previous: + DEFS 8 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/keyboard/kyb_driver.c:23: #define EI __asm__("EI") +; --------------------------------- +; Function report_diff +; --------------------------------- +_report_diff: +;source-doc/keyboard/kyb_driver.c:24: + ld de,_report+0 +;source-doc/keyboard/kyb_driver.c:25: static uint8_t report_diff() __sdcccall(1) { +;source-doc/keyboard/kyb_driver.c:28: + ld b,$08 + ld hl,_previous +l_report_diff_00103: +;source-doc/keyboard/kyb_driver.c:29: uint8_t i = sizeof(report); + ld a, (de) + inc de + ld c, (hl) + inc hl + sub c + jr Z,l_report_diff_00104 +;source-doc/keyboard/kyb_driver.c:30: do { + ld a,$01 + jr l_report_diff_00106 +l_report_diff_00104: +;source-doc/keyboard/kyb_driver.c:31: if (*a++ != *b++) + djnz l_report_diff_00103 +;source-doc/keyboard/kyb_driver.c:33: } while (--i != 0); + xor a +l_report_diff_00106: +;source-doc/keyboard/kyb_driver.c:34: + ret +;source-doc/keyboard/kyb_driver.c:36: } +; --------------------------------- +; Function keyboard_buf_put +; --------------------------------- +_keyboard_buf_put: + ld c, a +;source-doc/keyboard/kyb_driver.c:37: + ld b,$00 + ld hl,+(_report + 2) + add hl, bc +;source-doc/keyboard/kyb_driver.c:38: static void keyboard_buf_put(const uint8_t indx) __sdcccall(1) { + ld a,(hl) + ld e,a + sub $80 + jr NC,l_keyboard_buf_put_00112 + ld a, e + or a +;source-doc/keyboard/kyb_driver.c:39: const uint8_t key_code = report.keyCode[indx]; + jr Z,l_keyboard_buf_put_00112 +;source-doc/keyboard/kyb_driver.c:42: + ld b,$00 + ld hl,+(_previous + 2) + add hl, bc + ld a, (hl) + sub e +;source-doc/keyboard/kyb_driver.c:43: // if already reported, just skip it + jr Z,l_keyboard_buf_put_00112 +;source-doc/keyboard/kyb_driver.c:45: return; + ld a, e + sub $39 + jr NZ,l_keyboard_buf_put_00107 +;source-doc/keyboard/kyb_driver.c:46: + ld hl,_caps_lock_engaged + ld a, (hl) + xor $01 + ld (hl), a +;source-doc/keyboard/kyb_driver.c:47: if (key_code == KEY_CODE_CAPS_LOCK) { + jr l_keyboard_buf_put_00112 +l_keyboard_buf_put_00107: +;source-doc/keyboard/kyb_driver.c:50: } + ld a,(_report) + ld hl,_caps_lock_engaged + ld h, (hl) + push hl + inc sp + ld l, e + call _scancode_to_char + ld b, a +;source-doc/keyboard/kyb_driver.c:52: const unsigned char c = scancode_to_char(report.bModifierKeys, key_code, caps_lock_engaged); + or a +;source-doc/keyboard/kyb_driver.c:53: + ret Z +;source-doc/keyboard/kyb_driver.c:55: return; + ld a, (_write_index) + inc a + and $07 + ld c, a +;source-doc/keyboard/kyb_driver.c:56: + ld hl,_read_index + ld a, (hl) + sub c + ret Z +;source-doc/keyboard/kyb_driver.c:57: uint8_t next_write_index = (write_index + 1) & KEYBOARD_BUFFER_SIZE_MASK; + ld hl,(_write_index) + ld h,$00 + ld de,_buffer + add hl,de + ld a,b + ld (hl),a + ld hl,_write_index +;source-doc/keyboard/kyb_driver.c:58: if (next_write_index != read_index) { // Check if buffer is not full + ld (hl), c +l_keyboard_buf_put_00112: +;source-doc/keyboard/kyb_driver.c:60: write_index = next_write_index; + ret +;source-doc/keyboard/kyb_driver.c:62: } +; --------------------------------- +; Function usb_kyb_status +; --------------------------------- +_usb_kyb_status: +;source-doc/keyboard/kyb_driver.c:63: + DI +;source-doc/keyboard/kyb_driver.c:67: uint8_t size; + ld a,(_write_index) + ld hl,_read_index + sub (hl) + jr C,l_usb_kyb_status_00102 +;source-doc/keyboard/kyb_driver.c:68: + ld a,(_write_index) + ld hl,_read_index + sub (hl) + jr l_usb_kyb_status_00103 +l_usb_kyb_status_00102: +;source-doc/keyboard/kyb_driver.c:70: size = write_index - read_index; + ld hl, (_read_index) + ld a,$08 + sub l + ld hl, (_write_index) + add a, l +l_usb_kyb_status_00103: +;source-doc/keyboard/kyb_driver.c:72: size = KEYBOARD_BUFFER_SIZE - read_index + write_index; + EI +;source-doc/keyboard/kyb_driver.c:73: +;source-doc/keyboard/kyb_driver.c:74: EI; + ret +;source-doc/keyboard/kyb_driver.c:76: } +; --------------------------------- +; Function usb_kyb_read +; --------------------------------- +_usb_kyb_read: +;source-doc/keyboard/kyb_driver.c:77: + ld a,(_write_index) + ld hl,_read_index + sub (hl) + jr NZ,l_usb_kyb_read_00102 +;source-doc/keyboard/kyb_driver.c:78: uint16_t usb_kyb_read() { + ld hl,$ff00 + jr l_usb_kyb_read_00103 +l_usb_kyb_read_00102: +;source-doc/keyboard/kyb_driver.c:80: return $FF00; // H = -1, L = 0 + DI +;source-doc/keyboard/kyb_driver.c:81: + ld hl,(_read_index) + ld h,$00 + ld bc,_buffer + add hl,bc + ld a,(hl) + ld c,l + ld b,h + ld hl,_read_index + ld l, a +;source-doc/keyboard/kyb_driver.c:82: DI; + ld a, (_read_index) + inc a + and $07 + ld (_read_index), a +;source-doc/keyboard/kyb_driver.c:83: const uint8_t c = buffer[read_index]; + EI +;source-doc/keyboard/kyb_driver.c:86: + ld h,$00 +l_usb_kyb_read_00103: +;source-doc/keyboard/kyb_driver.c:87: /* H = 0, L = ascii char */ + ret +;source-doc/keyboard/kyb_driver.c:89: } +; --------------------------------- +; Function usb_kyb_flush +; --------------------------------- +_usb_kyb_flush: +;source-doc/keyboard/kyb_driver.c:90: + DI +;source-doc/keyboard/kyb_driver.c:91: uint8_t usb_kyb_flush() __sdcccall(1) { + xor a + ld (_read_index),a + ld (_write_index),a +;source-doc/keyboard/kyb_driver.c:94: + ld de,_previous+0 +;source-doc/keyboard/kyb_driver.c:95: uint8_t i = sizeof(previous); +;source-doc/keyboard/kyb_driver.c:96: uint8_t *a = (uint8_t *)previous; + ld b,$08 + ld hl,_report +l_usb_kyb_flush_00101: +;source-doc/keyboard/kyb_driver.c:97: uint8_t *b = (uint8_t *)report; + xor a + ld (de), a + inc de +;source-doc/keyboard/kyb_driver.c:98: do { + ld (hl),$00 + inc hl +;source-doc/keyboard/kyb_driver.c:99: *a++ = 0; + djnz l_usb_kyb_flush_00101 +;source-doc/keyboard/kyb_driver.c:101: } while (--i != 0); + EI +;source-doc/keyboard/kyb_driver.c:103: EI; + xor a +;source-doc/keyboard/kyb_driver.c:104: + ret +;source-doc/keyboard/kyb_driver.c:106: } +; --------------------------------- +; Function usb_kyb_tick +; --------------------------------- +_usb_kyb_tick: +;source-doc/keyboard/kyb_driver.c:109: usb_error result; + ld hl,_in_critical_usb_section + ld a, (hl) + or a +;source-doc/keyboard/kyb_driver.c:110: + jr NZ,l_usb_kyb_tick_00112 +;././source-doc/base-drv//ch376.h:108: #define TRACE_USB_ERROR(result) + ld l,$0b + call _ch_command +;././source-doc/base-drv//ch376.h:109: + ld a,$25 + ld bc,_CH376_DATA_PORT + out (c), a +;././source-doc/base-drv//ch376.h:110: #endif + ld a,$1f + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/keyboard/kyb_driver.c:113: + ld bc,_report+0 + ld hl, (_keyboard_config) + ld a,$08 + push af + inc sp + push bc + push hl + call _usbdev_dat_in_trnsfer_0 + pop af + pop af + inc sp +;././source-doc/base-drv//ch376.h:108: #define TRACE_USB_ERROR(result) + push hl + ld l,$0b + call _ch_command + pop hl +;././source-doc/base-drv//ch376.h:109: + ld a,$25 + ld bc,_CH376_DATA_PORT + out (c), a +;././source-doc/base-drv//ch376.h:110: #endif + ld a,$df + ld bc,_CH376_DATA_PORT + out (c), a +;source-doc/keyboard/kyb_driver.c:115: result = usbdev_dat_in_trnsfer_0((device_config *)keyboard_config, (uint8_t *)&report, 8); + ld a, l + or a + jr NZ,l_usb_kyb_tick_00112 +;source-doc/keyboard/kyb_driver.c:116: ch_configure_nak_retry_3s(); + call _report_diff + or a + jr Z,l_usb_kyb_tick_00112 +;source-doc/keyboard/kyb_driver.c:118: if (report_diff()) { + ld b,$06 +l_usb_kyb_tick_00103: +;source-doc/keyboard/kyb_driver.c:119: uint8_t i = 6; + ld a, b + dec a + push bc + call _keyboard_buf_put + pop bc +;source-doc/keyboard/kyb_driver.c:120: do { + djnz l_usb_kyb_tick_00103 +;source-doc/keyboard/kyb_driver.c:121: keyboard_buf_put(i - 1); + ld de,_previous + ld bc,$0008 + ld hl,_report + ldir +l_usb_kyb_tick_00112: +;source-doc/keyboard/kyb_driver.c:124: } + ret +;source-doc/keyboard/kyb_driver.c:126: } +; --------------------------------- +; Function usb_kyb_init +; --------------------------------- +_usb_kyb_init: +;source-doc/keyboard/kyb_driver.c:127: + call _get_usb_device_config + ex de, hl + ld (_keyboard_config), hl +;source-doc/keyboard/kyb_driver.c:129: keyboard_config = (device_config_keyboard *)get_usb_device_config(dev_index); + ld hl,_keyboard_config + 1 + ld a, (hl) + dec hl + or (hl) +;source-doc/keyboard/kyb_driver.c:130: + ret Z +;source-doc/keyboard/kyb_driver.c:132: return; + ld a,$01 + push af + inc sp + ld hl, (_keyboard_config) + call _hid_set_protocol +;source-doc/keyboard/kyb_driver.c:133: + ld a,$80 + push af + inc sp + ld hl, (_keyboard_config) + call _hid_set_idle +;source-doc/keyboard/kyb_driver.c:134: hid_set_protocol(keyboard_config, 1); + ret +_caps_lock_engaged: + DEFB +$01 +_keyboard_config: + DEFW +$0000 +_buffer: + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 +_write_index: + DEFB +$00 +_read_index: + DEFB +$00 +_report: + DEFB +$00 + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 +_previous: + DEFB +$00 + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 diff --git a/Source/HBIOS/ch376-native/print.asm b/Source/HBIOS/ch376-native/print.asm new file mode 100644 index 00000000..99d736f2 --- /dev/null +++ b/Source/HBIOS/ch376-native/print.asm @@ -0,0 +1,39 @@ + + ; HL = unsigned 16 bit number to write out + ; call CHPUT to write a single ascii character (in A) +_print_uint16: + ld a, h + or l + jr z, print_zero + ld e, 0 + ld bc, -10000 + call num1 + ld bc, -1000 + call num1 + ld bc, -100 + call num1 + ld c, -10 + call num1 + ld c, b + +num1: ld a, '0'-1 +num2: inc a + add hl, bc + jr c, num2 + sbc hl, bc + + cp '0' + jr nz, num3 + + ld a, e + cp 1 + ret nz + ld a, '0' + +num3: + ld e, 1 + jp COUT + +print_zero + ld a, '0' + jp COUT diff --git a/Source/HBIOS/ch376-native/readme.md b/Source/HBIOS/ch376-native/readme.md new file mode 100644 index 00000000..f92ffd8c --- /dev/null +++ b/Source/HBIOS/ch376-native/readme.md @@ -0,0 +1,125 @@ +# Native CH376 Driver + +The native CH376 HBIOS driver is written in c, using z88dk's zcc compiler. + +The build process, is a 3 stage process. + +1. Compile all the C code to assembly files (.asm) +2. Translate the produced .asm files syntax to compile with the RomWBW assembler (.s) +3. Assemble the driver .s files as per the standard HBIOS build process + +The original C code and produced/translated .s files are all committed units in the repo. But it is +expected, that only the c files are to be modified/updated. + +The .s files are checked in, so builders do not require the C compiler tool chain (z88dk) to be installed. + +The c compiling/translating process is only supported on linux, as the script to translate the .asm files +to .s files is a linux bash script. (Although the script can be easily run within Windows's Sub-system for linux) + +## Compiling the C code + +> Requires linux with docker installed. + +> The C code only needs to be recompiled if and when you change any of the `.c` source files. + +To compile the `.c` code to generate updated `.s` files: + +Within the `Source/HBIOS/ch376-native` directory: + +``` +make +``` + +The make script will search for z88dk's `zcc` compiler, if not found, will attempt to use a docker wrapper. +It will not work if z88dk or docker is not installed. + +## USB Native Driver systems + +The default builds of RomWBW do not enable the CH376 native usb drivers. These drivers take a reasonable chunk of ROM space. As such you +will need to build a new HBIOS image customised for your platform. Please familiarise yourself with the HBIOS/RomWBW build and configuration process. + +The usb driver is divided into a few sub-system, which can be individually enabled within the standard HBIOS config files. + +For activating the full native USB support, the non native CH365 drivers need to be disabled and the relevant `CHNATIVE` drivers enabled + +Example: + +``` +CHENABLE .SET FALSE ; CH: ENABLE CH375/376 USB SUPPORT +CH0USBENABLE .SET FALSE ; CH375: ENABLE CH375 USB DRIVER +CH1USBENABLE .SET FALSE ; CH376: ENABLE CH376 USB DRIVER +CHNATIVEENABLE .SET TRUE ; CH376: ENABLE CH376 NATIVE USB DRIVER +CHSCSIENABLE .SET TRUE ; CH376: ENABLE CH376 NATIVE MASS STORAGE DEVICES (REQUIRES CHNATIVEENABLE) +CHUFIENABLE .SET TRUE ; CH376: ENABLE CH376 NATIVE UFI FLOPPY DISK DEVICES (REQUIRES CHNATIVEENABLE) +CHNATIVEEZ80 .SET FALSE ; CH376: DELEGATE USB DRIVERS TO EZ80'S FIRMWARE +CHNATIVEFORCE .SET TRUE ; CH376: DISABLE AUTO-DETECTION OF MODULE - ASSUME ITS INSTALLED +``` + +As the USB driver is a fairly large, you may need to disable other HBIOS drivers in your configuration. As such, it is +recommend to only enable drivers for your platform's hardware configuration - for example, enable only the serial driver +required for your system. + +``` +DUARTENABLE .SET FALSE ; DUART: ENABLE 2681/2692 SERIAL DRIVER (DUART.ASM) +UARTENABLE .SET FALSE ; UART: ENABLE 8250/16550-LIKE SERIAL DRIVER (UART.ASM) +ACIAENABLE .SET FALSE ; ACIA: ENABLE MOTOROLA 6850 ACIA DRIVER (ACIA.ASM) +SIOENABLE .SET TRUE ; SIO: ENABLE ZILOG SIO SERIAL DRIVER (SIO.ASM) +``` + +You may also need to disable other storage drivers: + +``` +FDENABLE .SET FALSE ; FD: ENABLE FLOPPY DISK DRIVER (FD.ASM) +IDEENABLE .SET FALSE ; IDE: ENABLE IDE DISK DRIVER (IDE.ASM) +PPIDEENABLE .SET FALSE ; PPIDE: ENABLE PARALLEL PORT IDE DISK DRIVER (PPIDE.ASM) +``` + +### base-drv `CHNATIVEENABLE` + +The `base-drv` system contains the core code to discover, enumerate, and communicate with USB devices. + +It also includes the driver code to enumerate and operating USB devices through a USB hub. + +### scsi-drv `CHSCSIENABLE` + +The `scsi-drv` system can be enabled with the HBIOS config `CHSCSIENABLE` + +When activated, access to most USB mass storage devices (thumb drives, magnetic usb drives) is enabled. + +### ufi-drv `CHUFIENABLE` + +The `ufi-drv` system can be enabled with the HBIOS config `CHUFIENABLE` + +When activated, access to 3.5" Floppy USB devices will be enabled. + +### keyboard `TMSMODE_MSXUKY` + +The `keyboard` system can be enabled with the inferred config entry `USBKYBENABLE` + +This config item is not to be directly set, but is activated via the TMS keyboard driver + +Example configuration, combined with the TMS VDP module driver. + +``` +TMSENABLE .SET TRUE ; TMS: ENABLE TMS9918 VIDEO/KBD DRIVER (TMS.ASM) +TMSMODE .SET TMSMODE_MSXUKY ; TMS: DRIVER MODE: TMSMODE_[SCG|N8|MSX|MSXKBD|MSXMKY|MBC|COLECO|DUO|NABU|MSXUKY] +TMS80COLS .SET FALSE ; TMS: ENABLE 80 COLUMN SCREEN, REQUIRES V9958 +TMSTIMENABLE .SET TRUE ; TMS: ENABLE TIMER INTERRUPTS (REQUIRES IM1) +``` + +When activated, usb keyboards can be used as input devices. + +### Force activation `CHNATIVEFORCE` + +The CH376 module, during a cold power on boot, can take many seconds before it will +respond to the CPU. As such, the CPU may fail to detect the presence of the module. + +A manual reset (without power cycling) generally enables detection. The config entry +`CHNATIVEFORCE` can be enabled to force the CPU to always wait for the module to come online. + + +### eZ80 support `CHNATIVEEZ80` + +If you have the eZ80 CPU installed with onboard USB firmware support, you +can gain performance by delegating HBIOS to the firmware implementation. To enable +delegation, enable the config entry `CHNATIVEEZ80` diff --git a/Source/HBIOS/ch376-native/scsi-drv.s b/Source/HBIOS/ch376-native/scsi-drv.s new file mode 100644 index 00000000..ea6f8a70 --- /dev/null +++ b/Source/HBIOS/ch376-native/scsi-drv.s @@ -0,0 +1,8 @@ +; Generated File -- not to be modify directly +#IF (!CHNATIVEEZ80) +#include "ch376-native/scsi-drv/class_scsi.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/scsi-drv/scsi_driver.c.s" +#ENDIF +#include "ch376-native/scsi-drv/scsi-init.c.s" diff --git a/Source/HBIOS/ch376-native/scsi-drv/.gitignore b/Source/HBIOS/ch376-native/scsi-drv/.gitignore new file mode 100644 index 00000000..f4cb8488 --- /dev/null +++ b/Source/HBIOS/ch376-native/scsi-drv/.gitignore @@ -0,0 +1 @@ +*.asm diff --git a/Source/HBIOS/ch376-native/scsi-drv/class_scsi.c.s b/Source/HBIOS/ch376-native/scsi-drv/class_scsi.c.s new file mode 100644 index 00000000..06422929 --- /dev/null +++ b/Source/HBIOS/ch376-native/scsi-drv/class_scsi.c.s @@ -0,0 +1,446 @@ +; +; Generated from source-doc/scsi-drv/class_scsi.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_scsi_cmd_blk_wrap: + DEFS 15 +_next_tag: + DEFS 2 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/scsi-drv/class_scsi.c:11: usb_error do_scsi_cmd(device_config_storage *const dev, +; --------------------------------- +; Function do_scsi_cmd +; --------------------------------- +_do_scsi_cmd: + push ix + ld ix,0 + add ix,sp + ld hl, -21 + add hl, sp + ld sp, hl +;source-doc/scsi-drv/class_scsi.c:17: _scsi_command_status_wrapper csw = {{{0}}}; + ld a,$00 + ld (ix-21),a + ld (ix-20),a + ld (ix-19),a + ld (ix-18),a + xor a + ld (ix-17),a + ld (ix-16),a + xor a + ld (ix-15),a + ld (ix-14),a + ld a,$00 + ld (ix-13),a + ld (ix-12),a + ld (ix-11),a + ld (ix-10),a + ld (ix-9),$00 +;source-doc/scsi-drv/class_scsi.c:19: cbw->dCBWTag[0] = next_tag++; + ld c,(ix+6) + ld b,(ix+7) + ld hl,$0004 + add hl, bc + ld (ix-8),l + ld (ix-7),h + ld a, (_next_tag) + ld e, a + ld hl,_next_tag + 1 + ld d, (hl) + ld hl, (_next_tag) + inc hl + ld (_next_tag), hl + ld l,(ix-8) + ld h,(ix-7) + ld (hl), e + inc hl + ld (hl), d +;source-doc/scsi-drv/class_scsi.c:21: if (!send) + bit 0,(ix+10) + jr NZ,l_do_scsi_cmd_00102 +;source-doc/scsi-drv/class_scsi.c:22: cbw->bmCBWFlags = $80; + ld hl,$000c + add hl, bc + ld (hl),$80 +l_do_scsi_cmd_00102: +;source-doc/scsi-drv/class_scsi.c:24: critical_begin(); + push bc + call _critical_begin + pop bc +;source-doc/scsi-drv/class_scsi.c:27: &dev->endpoints[ENDPOINT_BULK_OUT])); + ld a,(ix+4) + ld (ix-6),a + ld e, a + ld a,(ix+5) + ld (ix-5),a + ld d,a + inc de + inc de + inc de + ld a,(ix-6) + ld (ix-4),a + ld l, a + ld a,(ix-5) + ld (ix-3),a + ld h,a + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld l,(ix+6) + ld h,(ix+7) + push bc + push de + push de + push af + inc sp + push hl + ld hl,$001f + ex (sp), hl + push hl + call _usb_data_out_transfer + pop af + pop af + pop af + inc sp + pop de + pop bc + ld a, l + or a + jp NZ, l_do_scsi_cmd_00120 +;source-doc/scsi-drv/class_scsi.c:29: if (cbw->dCBWDataTransferLength != 0) { + ld hl,8 + add hl, bc + ld c, (hl) + inc hl + ld b, (hl) + inc hl + inc hl + ld a, (hl) + dec hl + ld l, (hl) + or l + or b + or c + jr Z,l_do_scsi_cmd_00113 +;source-doc/scsi-drv/class_scsi.c:32: &dev->endpoints[ENDPOINT_BULK_IN])); + ld (ix-2),c + ld (ix-1),b + ld c,(ix+8) + ld b,(ix+9) +;source-doc/scsi-drv/class_scsi.c:30: if (!send) { + bit 0,(ix+10) + jr NZ,l_do_scsi_cmd_00110 +;source-doc/scsi-drv/class_scsi.c:32: &dev->endpoints[ENDPOINT_BULK_IN])); + ld a,(ix-6) + add a,$06 + ld e, a + ld a,(ix-5) + adc a,$00 + ld d, a + ld l,(ix-4) + ld h,(ix-3) + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + push de + push af + inc sp + ld l,(ix-2) + ld h,(ix-1) + push hl + push bc + call _usb_data_in_transfer + pop af + pop af + pop af + inc sp + ld a, l + or a + jr Z,l_do_scsi_cmd_00113 + jr l_do_scsi_cmd_00120 +l_do_scsi_cmd_00110: +;source-doc/scsi-drv/class_scsi.c:36: &dev->endpoints[ENDPOINT_BULK_OUT])); + ld l,(ix-4) + ld h,(ix-3) + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + push de + push af + inc sp + ld l,(ix-2) + ld h,(ix-1) + push hl + push bc + call _usb_data_out_transfer + pop af + pop af + pop af + inc sp + ld a, l + or a + jr NZ,l_do_scsi_cmd_00120 +l_do_scsi_cmd_00113: +;source-doc/scsi-drv/class_scsi.c:41: usb_data_in_transfer((uint8_t *)&csw, sizeof(_scsi_command_status_wrapper), dev->address, &dev->endpoints[ENDPOINT_BULK_IN])); + ld a,(ix-6) + add a,$06 + ld c, a + ld a,(ix-5) + adc a,$00 + ld b, a + ld l,(ix-4) + ld h,(ix-3) + ld a, (hl) + rlca + rlca + rlca + rlca + and $0f + ld d, a + push bc + push de + inc sp + ld hl,$000d + push hl + ld hl,5 + add hl, sp + push hl + call _usb_data_in_transfer + pop af + pop af + pop af + inc sp + ld a, l + or a + jr NZ,l_do_scsi_cmd_00120 +;source-doc/scsi-drv/class_scsi.c:43: if (csw.bCSWStatus != 0 || csw.dCSWTag[0] != cbw->dCBWTag[0]) + ld a,(ix-9) + or a + jr NZ,l_do_scsi_cmd_00116 + ld c,(ix-17) + ld b,(ix-16) + ld l,(ix-8) + ld h,(ix-7) + ld a, (hl) + inc hl + ld h, (hl) + ld l, a + xor a + sbc hl,bc + jr Z,l_do_scsi_cmd_00117 +l_do_scsi_cmd_00116: +;source-doc/scsi-drv/class_scsi.c:44: result = USB_ERR_FAIL; + ld l,$0e + jr l_do_scsi_cmd_00120 +l_do_scsi_cmd_00117: +;source-doc/scsi-drv/class_scsi.c:46: result = USB_ERR_OK; + ld l,$00 +;source-doc/scsi-drv/class_scsi.c:48: done: +l_do_scsi_cmd_00120: +;source-doc/scsi-drv/class_scsi.c:49: critical_end(); + push hl + call _critical_end + pop hl +;source-doc/scsi-drv/class_scsi.c:50: return result; +;source-doc/scsi-drv/class_scsi.c:51: } + ld sp, ix + pop ix + ret +;source-doc/scsi-drv/class_scsi.c:53: usb_error scsi_test(device_config_storage *const dev) { +; --------------------------------- +; Function scsi_test +; --------------------------------- +_scsi_test: + push ix + ld ix,0 + add ix,sp + ld hl, -27 + add hl, sp + ld sp, hl +;source-doc/scsi-drv/class_scsi.c:55: cbw_scsi.cbw = scsi_cmd_blk_wrap; + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$000f + ld hl,_scsi_cmd_blk_wrap + ldir +;source-doc/scsi-drv/class_scsi.c:56: memset(&cbw_scsi.test, 0, sizeof(_scsi_packet_test)); + ld hl,17 + add hl, sp + ld b,$06 +l_scsi_test_00103: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_scsi_test_00103 + pop bc +;source-doc/scsi-drv/class_scsi.c:58: cbw_scsi.cbw.bCBWLUN = 0; + ld (ix-14),$00 +;source-doc/scsi-drv/class_scsi.c:59: cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_test); + ld (ix-13),$0c +;source-doc/scsi-drv/class_scsi.c:60: cbw_scsi.cbw.dCBWDataTransferLength = 0; + ld hl,$0008 + add hl, bc + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + ld (hl), a + inc hl + ld (hl), a +;source-doc/scsi-drv/class_scsi.c:62: return do_scsi_cmd(dev, &cbw_scsi.cbw, 0, false); + xor a + push af + inc sp + ld hl,$0000 + push hl + push bc + ld l,(ix+4) + ld h,(ix+5) + push hl + call _do_scsi_cmd +;source-doc/scsi-drv/class_scsi.c:63: } + ld sp,ix + pop ix + ret +;source-doc/scsi-drv/class_scsi.c:67: usb_error scsi_request_sense(device_config_storage *const dev, scsi_sense_result *const sens_result) { +; --------------------------------- +; Function scsi_request_sense +; --------------------------------- +_scsi_request_sense: + push ix + ld ix,0 + add ix,sp + ld hl, -27 + add hl, sp + ld sp, hl +;source-doc/scsi-drv/class_scsi.c:69: cbw_scsi.cbw = scsi_cmd_blk_wrap; + ld hl,0 + add hl, sp + ld e,l + ld d,h + push hl + ld bc,$000f + ld hl,_scsi_cmd_blk_wrap + ldir +;source-doc/scsi-drv/class_scsi.c:70: cbw_scsi.request_sense = scsi_pckt_req_sense; + ld hl,17 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,_scsi_pckt_req_sense + ldir + pop bc +;source-doc/scsi-drv/class_scsi.c:72: cbw_scsi.cbw.bCBWLUN = 0; + ld (ix-14),$00 +;source-doc/scsi-drv/class_scsi.c:73: cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_request_sense); + ld (ix-13),$0c +;source-doc/scsi-drv/class_scsi.c:74: cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_sense_result); + ld hl,$0008 + add hl, bc + ld (hl),$12 + inc hl + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + ld (hl), a +;source-doc/scsi-drv/class_scsi.c:76: return do_scsi_cmd(dev, &cbw_scsi.cbw, sens_result, false); + ld e,(ix+6) + ld d,(ix+7) + xor a + push af + inc sp + push de + push bc + ld l,(ix+4) + ld h,(ix+5) + push hl + call _do_scsi_cmd +;source-doc/scsi-drv/class_scsi.c:77: } + ld sp,ix + pop ix + ret +_scsi_pckt_req_sense: + DEFB +$03 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$12 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +_scsi_cmd_blk_wrap: + DEFB +$55 + DEFB +$53 + DEFB +$42 + DEFB +$43 + DEFW +$0000 + DEFW +$0000 + DEFB +$00,$00, +$00, +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +_next_tag: + DEFW +$0000 diff --git a/Source/HBIOS/ch376-native/scsi-drv/scsi-init.c.s b/Source/HBIOS/ch376-native/scsi-drv/scsi-init.c.s new file mode 100644 index 00000000..2c74f9b7 --- /dev/null +++ b/Source/HBIOS/ch376-native/scsi-drv/scsi-init.c.s @@ -0,0 +1,148 @@ +; +; Generated from source-doc/scsi-drv/scsi-init.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/scsi-drv/scsi-init.c:9: void chscsi_init(void) { +; --------------------------------- +; Function chscsi_init +; --------------------------------- +_chscsi_init: + push ix + ld ix,0 + add ix,sp + push af + dec sp +;source-doc/scsi-drv/scsi-init.c:11: do { + ld (ix-1),$01 +l_chscsi_init_00103: +;source-doc/scsi-drv/scsi-init.c:12: usb_device_type t = usb_get_device_type(index); + ld a,(ix-1) + ld (ix-3),a + ld (ix-2),$00 + pop hl + push hl + push hl + call _usb_get_device_type + pop af + ld a, l +;source-doc/scsi-drv/scsi-init.c:14: if (t == USB_IS_MASS_STORAGE) { + sub $02 + jr NZ,l_chscsi_init_00104 +;source-doc/scsi-drv/scsi-init.c:15: const uint8_t dev_index = find_storage_dev(); // index == -1 (no more left) should never happen + call _find_storage_dev +;source-doc/scsi-drv/scsi-init.c:17: hbios_usbstore_devs[dev_index].drive_index = dev_index + 1; + ld a, l + ld c,$00 + add a, a + rl c + add a, +((_hbios_usbstore_devs) & $FF) + ld e, a + ld a, c + adc a, +((_hbios_usbstore_devs) / 256) + ld d, a + ld c, e + ld b, d + ld a, l + inc a + ld (bc), a +;source-doc/scsi-drv/scsi-init.c:18: hbios_usbstore_devs[dev_index].usb_device = index; + ld c, e + ld b, d + inc bc + ld a,(ix-1) + ld (bc), a +;source-doc/scsi-drv/scsi-init.c:20: print_string("\r\nUSB: MASS STORAGE @ $"); + push hl + push de + ld hl,scsi_init_str_0 + call _print_string +;source-doc/scsi-drv/scsi-init.c:21: print_uint16(index); + ld l,(ix-3) + ld h,$00 + call _print_uint16 +;source-doc/scsi-drv/scsi-init.c:22: print_string(":$"); + ld hl,scsi_init_str_1 + call _print_string + pop de + pop hl +;source-doc/scsi-drv/scsi-init.c:23: print_uint16(dev_index); + ld h,$00 + push de + call _print_uint16 +;source-doc/scsi-drv/scsi-init.c:24: print_string(" $"); + ld hl,scsi_init_str_2 + call _print_string +;source-doc/scsi-drv/scsi-init.c:25: usb_scsi_init(index); + ld l,(ix-3) + ld h,$00 + push hl + call _usb_scsi_init + pop af + pop de +;source-doc/scsi-drv/scsi-init.c:26: dio_add_entry(ch_scsi_fntbl, &hbios_usbstore_devs[dev_index]); + ld hl,_ch_scsi_fntbl + call _dio_add_entry +l_chscsi_init_00104: +;source-doc/scsi-drv/scsi-init.c:29: } while (++index != MAX_NUMBER_OF_DEVICES + 1); + inc (ix-1) + ld a,(ix-1) + sub $07 + jr NZ,l_chscsi_init_00103 +;source-doc/scsi-drv/scsi-init.c:30: } + ld sp, ix + pop ix + ret +scsi_init_str_0: + DEFB $0d + DEFB $0a + DEFM "USB: MASS STORAGE @ $" + DEFB $00 +scsi_init_str_1: + DEFM ":$" + DEFB $00 +scsi_init_str_2: + DEFM " $" + DEFB $00 diff --git a/Source/HBIOS/ch376-native/scsi-drv/scsi_driver.c.s b/Source/HBIOS/ch376-native/scsi-drv/scsi_driver.c.s new file mode 100644 index 00000000..45b0f18d --- /dev/null +++ b/Source/HBIOS/ch376-native/scsi-drv/scsi_driver.c.s @@ -0,0 +1,470 @@ +; +; Generated from source-doc/scsi-drv/scsi_driver.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_scsi_pkt_read_cap: + DEFS 12 +_cbw: + DEFS 27 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/scsi-drv/scsi_driver.c:8: usb_error usb_scsi_init(const uint16_t dev_index) { +; --------------------------------- +; Function usb_scsi_init +; --------------------------------- +_usb_scsi_init: + push ix + ld ix,0 + add ix,sp + ld hl, -18 + add hl, sp + ld sp, hl +;source-doc/scsi-drv/scsi_driver.c:11: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config +;source-doc/scsi-drv/scsi_driver.c:16: critical_begin(); + push de + call _critical_begin + pop de +;source-doc/scsi-drv/scsi_driver.c:17: while ((result = scsi_test(dev)) && --counter > 0) + ld c,$03 +l_usb_scsi_init_00102: + push bc + push de + push de + call _scsi_test + pop af + ld a, l + pop de + pop bc + ld l, a + or a + jr Z,l_usb_scsi_init_00104 + dec c + jr Z,l_usb_scsi_init_00104 +;source-doc/scsi-drv/scsi_driver.c:18: scsi_request_sense(dev, &response); + push bc + push de + ld hl,4 + add hl, sp + push hl + push de + call _scsi_request_sense + pop af + pop af + pop de + pop bc + jr l_usb_scsi_init_00102 +l_usb_scsi_init_00104: +;source-doc/scsi-drv/scsi_driver.c:19: critical_end(); + push hl + call _critical_end + pop hl +;source-doc/scsi-drv/scsi_driver.c:21: return result; +;source-doc/scsi-drv/scsi_driver.c:22: } + ld sp, ix + pop ix + ret +;source-doc/scsi-drv/scsi_driver.c:26: usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *cap_result) { +; --------------------------------- +; Function usb_scsi_read_capacity +; --------------------------------- +_usb_scsi_read_capacity: + push ix + ld ix,0 + add ix,sp + ld hl, -27 + add hl, sp + ld sp, hl +;source-doc/scsi-drv/scsi_driver.c:27: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config +;source-doc/scsi-drv/scsi_driver.c:30: cbw_scsi.cbw = scsi_cmd_blk_wrap; + push de + ld hl,2 + add hl, sp + ex de, hl + ld bc,$000f + ld hl,_scsi_cmd_blk_wrap + ldir + pop de +;source-doc/scsi-drv/scsi_driver.c:31: cbw_scsi.read_capacity = scsi_pkt_read_cap; + push de + ld hl,17 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,_scsi_pkt_read_cap + ldir + pop de +;source-doc/scsi-drv/scsi_driver.c:33: cbw_scsi.cbw.bCBWLUN = 0; + ld (ix-14),$00 +;source-doc/scsi-drv/scsi_driver.c:34: cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_read_capacity); + ld (ix-13),$0c +;source-doc/scsi-drv/scsi_driver.c:35: cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_read_capacity_result); + ld (ix-19),$08 + xor a + ld (ix-18),a + ld (ix-17),a + ld (ix-16),a +;source-doc/scsi-drv/scsi_driver.c:37: return do_scsi_cmd(dev, &cbw_scsi.cbw, cap_result, false); + ld c,(ix+6) + ld b,(ix+7) + xor a + push af + inc sp + push bc + ld hl,3 + add hl, sp + push hl + push de + call _do_scsi_cmd + pop af + pop af + pop af + inc sp +;source-doc/scsi-drv/scsi_driver.c:38: } + ld sp, ix + pop ix + ret +;source-doc/scsi-drv/scsi_driver.c:58: usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer) { +; --------------------------------- +; Function usb_scsi_read +; --------------------------------- +_usb_scsi_read: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/scsi-drv/scsi_driver.c:61: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config + pop bc + push de +;source-doc/scsi-drv/scsi_driver.c:63: memset(&cbw, 0, sizeof(cbw_scsi_read_write)); + ld de,_cbw + ld l, e + ld h, d + ld b,$0e + jr l_usb_scsi_read_00113 +l_usb_scsi_read_00112: + ld (hl),$00 + inc hl +l_usb_scsi_read_00113: + ld (hl),$00 + inc hl + djnz l_usb_scsi_read_00112 +;source-doc/scsi-drv/scsi_driver.c:64: cbw.cbw = scsi_cmd_blk_wrap; + ld bc,$000f + ld hl,_scsi_cmd_blk_wrap + ldir +;source-doc/scsi-drv/scsi_driver.c:66: cbw.cbw.bCBWLUN = 0; + ld hl,_cbw + 13 + ld (hl),$00 +;source-doc/scsi-drv/scsi_driver.c:67: cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write); + ld hl,_cbw + 14 + ld (hl),$0c +;source-doc/scsi-drv/scsi_driver.c:68: cbw.cbw.dCBWDataTransferLength = 512; + ld hl,$0200 + ld (_cbw + 8),hl + ld h, l + ld (_cbw + 8 + 2),hl +;source-doc/scsi-drv/scsi_driver.c:70: cbw.scsi_cmd.operation_code = $28; // read operation + ld hl,_cbw + 15 + ld (hl),$28 +;source-doc/scsi-drv/scsi_driver.c:71: cbw.scsi_cmd.transfer_len[1] = 1; + ld hl,_cbw + 23 + ld (hl),$01 +;source-doc/scsi-drv/scsi_driver.c:72: cbw.scsi_cmd.lba[0] = dev->current_lba >> 24; + pop hl + push hl + ld de,$000c + add hl, de + push hl + inc hl + inc hl + inc hl + ld a, (hl) + ld ((_cbw + 17)),a + pop hl +;source-doc/scsi-drv/scsi_driver.c:73: cbw.scsi_cmd.lba[1] = dev->current_lba >> 16; + push hl + inc hl + inc hl + ld a, (hl) + ld ((_cbw + 18)),a + pop hl +;source-doc/scsi-drv/scsi_driver.c:74: cbw.scsi_cmd.lba[2] = dev->current_lba >> 8; + push hl + inc hl + ld a, (hl) + ld ((_cbw + 19)),a + pop hl +;source-doc/scsi-drv/scsi_driver.c:75: cbw.scsi_cmd.lba[3] = dev->current_lba; + ld bc,_cbw + 20 + ld a, (hl) + ld (bc), a +;source-doc/scsi-drv/scsi_driver.c:77: result = do_scsi_cmd(dev, &cbw.cbw, buffer, false); + ld c,(ix+6) + ld b,(ix+7) + push hl + xor a + push af + inc sp + push bc + ld de,_cbw + push de + ld e,(ix-2) + ld d,(ix-1) + push de + call _do_scsi_cmd + pop af + pop af + pop af + inc sp + ld a, l + pop hl + ld (ix-1),a +;source-doc/scsi-drv/scsi_driver.c:79: if (result == USB_ERR_OK) + or a + jr NZ,l_usb_scsi_read_00102 +;source-doc/scsi-drv/scsi_driver.c:80: dev->current_lba++; + ld c,(hl) + push hl + inc hl + ld b, (hl) + inc hl + ld e, (hl) + inc hl + ld d, (hl) + pop hl + inc c + jr NZ,l_usb_scsi_read_00114 + inc b + jr NZ,l_usb_scsi_read_00114 + inc de +l_usb_scsi_read_00114: + ld (hl), c + inc hl + ld (hl), b + inc hl + ld (hl), e + inc hl + ld (hl), d +l_usb_scsi_read_00102: +;source-doc/scsi-drv/scsi_driver.c:81: return result; + ld l,(ix-1) +;source-doc/scsi-drv/scsi_driver.c:82: } + ld sp, ix + pop ix + ret +;source-doc/scsi-drv/scsi_driver.c:84: usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer) { +; --------------------------------- +; Function usb_scsi_write +; --------------------------------- +_usb_scsi_write: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/scsi-drv/scsi_driver.c:86: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config + pop bc + push de +;source-doc/scsi-drv/scsi_driver.c:88: memset(&cbw, 0, sizeof(cbw_scsi_read_write)); + ld de,_cbw + ld l, e + ld h, d + ld b,$0e + jr l_usb_scsi_write_00113 +l_usb_scsi_write_00112: + ld (hl),$00 + inc hl +l_usb_scsi_write_00113: + ld (hl),$00 + inc hl + djnz l_usb_scsi_write_00112 +;source-doc/scsi-drv/scsi_driver.c:89: cbw.cbw = scsi_cmd_blk_wrap; + ld bc,$000f + ld hl,_scsi_cmd_blk_wrap + ldir +;source-doc/scsi-drv/scsi_driver.c:91: cbw.cbw.bCBWLUN = 0; + ld hl,_cbw + 13 + ld (hl),$00 +;source-doc/scsi-drv/scsi_driver.c:92: cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write); + ld hl,_cbw + 14 + ld (hl),$0c +;source-doc/scsi-drv/scsi_driver.c:93: cbw.cbw.dCBWDataTransferLength = 512; + ld hl,$0200 + ld (_cbw + 8),hl + ld h, l + ld (_cbw + 8 + 2),hl +;source-doc/scsi-drv/scsi_driver.c:95: cbw.scsi_cmd.operation_code = $2A; // write operation + ld hl,_cbw + 15 + ld (hl),$2a +;source-doc/scsi-drv/scsi_driver.c:96: cbw.scsi_cmd.transfer_len[1] = 1; + ld hl,_cbw + 23 + ld (hl),$01 +;source-doc/scsi-drv/scsi_driver.c:97: cbw.scsi_cmd.lba[0] = dev->current_lba >> 24; + pop hl + push hl + ld de,$000c + add hl, de + push hl + inc hl + inc hl + inc hl + ld a, (hl) + ld ((_cbw + 17)),a + pop hl +;source-doc/scsi-drv/scsi_driver.c:98: cbw.scsi_cmd.lba[1] = dev->current_lba >> 16; + push hl + inc hl + inc hl + ld a, (hl) + ld ((_cbw + 18)),a + pop hl +;source-doc/scsi-drv/scsi_driver.c:99: cbw.scsi_cmd.lba[2] = dev->current_lba >> 8; + push hl + inc hl + ld a, (hl) + ld ((_cbw + 19)),a + pop hl +;source-doc/scsi-drv/scsi_driver.c:100: cbw.scsi_cmd.lba[3] = dev->current_lba; + ld bc,_cbw + 20 + ld a, (hl) + ld (bc), a +;source-doc/scsi-drv/scsi_driver.c:102: result = do_scsi_cmd(dev, &cbw.cbw, buffer, true); + ld c,(ix+6) + ld b,(ix+7) + push hl + ld a,$01 + push af + inc sp + push bc + ld de,_cbw + push de + ld e,(ix-2) + ld d,(ix-1) + push de + call _do_scsi_cmd + pop af + pop af + pop af + inc sp + ld a, l + pop hl + ld (ix-1),a +;source-doc/scsi-drv/scsi_driver.c:104: if (result == USB_ERR_OK) + or a + jr NZ,l_usb_scsi_write_00102 +;source-doc/scsi-drv/scsi_driver.c:105: dev->current_lba++; + ld c,(hl) + push hl + inc hl + ld b, (hl) + inc hl + ld e, (hl) + inc hl + ld d, (hl) + pop hl + inc c + jr NZ,l_usb_scsi_write_00114 + inc b + jr NZ,l_usb_scsi_write_00114 + inc de +l_usb_scsi_write_00114: + ld (hl), c + inc hl + ld (hl), b + inc hl + ld (hl), e + inc hl + ld (hl), d +l_usb_scsi_write_00102: +;source-doc/scsi-drv/scsi_driver.c:106: return result; + ld l,(ix-1) +;source-doc/scsi-drv/scsi_driver.c:107: } + ld sp, ix + pop ix + ret +_scsi_pkt_read_cap: + DEFB +$25 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +_cbw: + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB +$00,$00, +$00, +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB $00 + DEFB +$00 + DEFB $00 + DEFB $00 + DEFB +$00 + DEFB $00 + DEFB $00 diff --git a/Source/HBIOS/ch376-native/source-doc/.clang-format b/Source/HBIOS/ch376-native/source-doc/.clang-format new file mode 100644 index 00000000..74924c0f --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/.clang-format @@ -0,0 +1,13 @@ +BasedOnStyle: LLVM +IndentWidth: 2 +AlignConsecutiveMacros: true +ColumnLimit: 132 +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: true +AlignConsecutiveMacros: true +AlignEscapedNewlines: Right +BinPackArguments: true +BinPackParameters: false +IncludeBlocks: Preserve +SortIncludes: CaseInsensitive diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/ch376.c b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376.c new file mode 100644 index 00000000..6b81ed30 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376.c @@ -0,0 +1,242 @@ +#include "ch376.h" + +#include "ez80-helpers.h" +#include "print.h" + +void ch_command(const uint8_t command) __z88dk_fastcall { + uint8_t counter = 255; + while ((CH376_COMMAND_PORT & PARA_STATE_BUSY) && --counter != 0) + ; + + // if (counter == 0) { + // It appears that the Ch376 has become blocked + // command will fail and timeout will eventually be returned by the ch_xxx_wait_int_and_get_status + // todo consider a return value to allow callers to respond appropriately + // Experimentation would indicate that USB_RESET_ALL will still work to reset chip + // return; + // } + + CH376_COMMAND_PORT = command; +} + +extern usb_error ch_wait_and_get_status(const int16_t timeout) __z88dk_fastcall; + +usb_error ch_long_get_status(void) { return ch_wait_and_get_status(5000); } + +usb_error ch_short_get_status(void) { return ch_wait_and_get_status(100); } + +usb_error ch_very_short_status(void) { return ch_wait_and_get_status(10); } + +usb_error ch_get_status(void) { + ch_command(CH_CMD_GET_STATUS); + uint8_t ch_status = CH376_DATA_PORT; + + if (ch_status >= USB_FILERR_MIN && ch_status <= USB_FILERR_MAX) + return ch_status; + + if (ch_status == CH_CMD_RET_SUCCESS) + return USB_ERR_OK; + + if (ch_status == CH_USB_INT_SUCCESS) + return USB_ERR_OK; + + if (ch_status == CH_USB_INT_CONNECT) + return USB_INT_CONNECT; + + if (ch_status == CH_USB_INT_DISK_READ) + return USB_ERR_DISK_READ; + + if (ch_status == CH_USB_INT_DISK_WRITE) + return USB_ERR_DISK_WRITE; + + if (ch_status == CH_USB_INT_DISCONNECT) { + ch_cmd_set_usb_mode(5); + return USB_ERR_NO_DEVICE; + } + + if (ch_status == CH_USB_INT_BUF_OVER) + return USB_ERR_DATA_ERROR; + + ch_status &= 0x2F; + + if (ch_status == 0x2A) + return USB_ERR_NAK; + + if (ch_status == 0x2E) + return USB_ERR_STALL; + + ch_status &= 0x23; + + if (ch_status == 0x20) + return USB_ERR_TIMEOUT; + + if (ch_status == 0x23) + return USB_TOKEN_OUT_OF_SYNC; + + return USB_ERR_UNEXPECTED_STATUS_FROM_HOST; +} + +void ch_cmd_reset_all(void) { ch_command(CH_CMD_RESET_ALL); } + +inline uint8_t ch_cmd_check_exist(void) { + uint8_t complement; + ch_command(CH_CMD_CHECK_EXIST); + CH376_DATA_PORT = (uint8_t)~0x55; + delay(); + complement = CH376_DATA_PORT; + return complement == 0x55; + // if (complement != 0x55) + // return false; + + // ch_command(CH_CMD_CHECK_EXIST); + // CH376_DATA_PORT = (uint8_t)~0x89; + // delay(); + // complement = CH376_DATA_PORT; + // return complement == 0x89; +} + +uint8_t ch_probe(void) { + uint8_t i = 5; + do { + if (ch_cmd_check_exist()) + return true; + + delay_medium(); + } while (--i != 0); + + return false; +} + +usb_error ch_cmd_set_usb_mode(const uint8_t mode) __z88dk_fastcall { + uint8_t result = 0; + + CH376_COMMAND_PORT = CH_CMD_SET_USB_MODE; + delay(); + CH376_DATA_PORT = mode; + delay(); + + uint8_t count = 127; + + while (result != CH_CMD_RET_SUCCESS && result != CH_CMD_RET_ABORT && --count != 0) { + result = CH376_DATA_PORT; + delay(); + } + + return (result == CH_CMD_RET_SUCCESS) ? USB_ERR_OK : USB_ERR_FAIL; +} + +uint8_t ch_cmd_get_ic_version(void) { + ch_command(CH_CMD_GET_IC_VER); + return CH376_DATA_PORT & 0x1f; +} + +void ch_issue_token(const uint8_t toggle_bit, const uint8_t endpoint, const ch376_pid pid) { + ch_command(CH_CMD_ISSUE_TKN_X); + CH376_DATA_PORT = toggle_bit; + CH376_DATA_PORT = endpoint << 4 | pid; +} + +void ch_issue_token_in(const endpoint_param *const endpoint) __z88dk_fastcall { + ch_issue_token(endpoint->toggle ? 0x80 : 0x00, endpoint->number, CH_PID_IN); +} + +void ch_issue_token_out(const endpoint_param *const endpoint) __z88dk_fastcall { + ch_issue_token(endpoint->toggle ? 0x40 : 0x00, endpoint->number, CH_PID_OUT); +} + +void ch_issue_token_out_ep0(void) { ch_issue_token(0x40, 0, CH_PID_OUT); } + +void ch_issue_token_in_ep0(void) { ch_issue_token(0x80, 0, CH_PID_IN); } + +void ch_issue_token_setup(void) { ch_issue_token(0, 0, CH_PID_SETUP); } + +usb_error ch_data_in_transfer(uint8_t *buffer, int16_t buffer_size, endpoint_param *const endpoint) { + uint8_t count; + usb_error result; + + if (buffer_size == 0) + return USB_ERR_OK; + + USB_MODULE_LEDS = 0x01; + do { + ch_issue_token_in(endpoint); + + result = ch_long_get_status(); + CHECK(result); + + endpoint->toggle = !endpoint->toggle; + + count = ch_read_data(buffer); + + if (count == 0) { + USB_MODULE_LEDS = 0x00; + return USB_ERR_DATA_ERROR; + } + + buffer += count; + buffer_size -= count; + } while (buffer_size > 0); + + USB_MODULE_LEDS = 0x00; + return USB_ERR_OK; + +done: + USB_MODULE_LEDS = 0x00; + return result; +} + +// TODO: review: does buffer_size need to be signed? +usb_error ch_data_in_transfer_n(uint8_t *const buffer, uint8_t *const buffer_size, endpoint_param *const endpoint) { + uint8_t count; + usb_error result; + + USB_MODULE_LEDS = 0x01; + + ch_issue_token_in(endpoint); + + CHECK(ch_long_get_status()); + + endpoint->toggle = !endpoint->toggle; + + count = ch_read_data(buffer); + + *buffer_size = count; + + USB_MODULE_LEDS = 0x00; + + return USB_ERR_OK; +done: + USB_MODULE_LEDS = 0x00; + return result; +} + +usb_error ch_data_out_transfer(const uint8_t *buffer, int16_t buffer_length, endpoint_param *const endpoint) { + usb_error result; + const uint8_t number = endpoint->number; + const uint8_t max_packet_size = calc_max_packet_size(endpoint->max_packet_sizex); + + USB_MODULE_LEDS = 0x02; + + while (buffer_length > 0) { + const uint8_t size = max_packet_size < buffer_length ? max_packet_size : buffer_length; + buffer = ch_write_data(buffer, size); + buffer_length -= size; + ch_issue_token_out(endpoint); + + CHECK(ch_long_get_status()); + + endpoint->toggle = !endpoint->toggle; + } + + USB_MODULE_LEDS = 0x00; + return USB_ERR_OK; + +done: + USB_MODULE_LEDS = 0x00; + return result; +} + +void ch_set_usb_address(const uint8_t device_address) __z88dk_fastcall { + ch_command(CH_CMD_SET_USB_ADDR); + CH376_DATA_PORT = device_address; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/ch376.h b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376.h new file mode 100644 index 00000000..125ee6d1 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376.h @@ -0,0 +1,176 @@ + +#ifndef __CH376 +#define __CH376 + +#include "ch376inc.h" +#include "delay.h" +#include +#include + +typedef enum { + USB_ERR_OK = 0, + USB_ERR_NAK = 1, + USB_ERR_STALL = 2, + USB_ERR_TIMEOUT = 3, + USB_ERR_DATA_ERROR = 4, + USB_ERR_NO_DEVICE = 5, + USB_ERR_PANIC_BUTTON_PRESSED = 6, + USB_TOKEN_OUT_OF_SYNC = 7, + USB_ERR_UNEXPECTED_STATUS_FROM_HOST = 8, + USB_ERR_CODE_EXCEPTION = 9, + USB_ERR_MEDIA_CHANGED = 10, + USB_ERR_MEDIA_NOT_PRESENT = 11, + USB_ERR_CH376_BLOCKED = 12, + USB_ERR_CH376_TIMEOUT = 13, + USB_ERR_FAIL = 14, + USB_ERR_MAX = 14, + USB_ERR_OTHER = 15, + USB_ERR_DISK_READ = 0x1D, + USB_ERR_DISK_WRITE = 0x1E, + USB_FILERR_MIN = 0x41, + USB_ERR_OPEN_DIR = 0x41, + USB_ERR_MISS_FILE = 0x42, + USB_FILERR_MAX = 0xB4, + USB_INT_CONNECT = 0x81, + USB_BAD_ADDRESS = 0x82, + USB_ERR_OUT_OF_MEMORY = 0x83, + USB_ERR_BUFF_TO_LARGE = 0x84, + USB_ERROR_DEVICE_NOT_FOUND = 0x85, +} usb_error; + +typedef enum { CH_NAK_RETRY_DONT = 0b00, CH_NAK_RETRY_INDEFINITE = 0b10, CH_NAK_RETRY_3S = 0b11 } ch_nak_retry_type; + +typedef enum { + USB_NOT_SUPPORTED = 0, + USB_IS_FLOPPY = 1, + USB_IS_MASS_STORAGE = 2, + USB_IS_CDC = 3, + USB_IS_KEYBOARD = 4, + USB_IS_UNKNOWN = 6, + _USB_LAST_DEVICE_TYPE, + USB_IS_HUB = 15 + +} usb_device_type; // 4 bits only + +typedef enum { ENDPOINT_BULK_OUT = 0, ENDPOINT_BULK_IN = 1, ENDPOINT_INTERRUPT_IN = 2 } usb_endpoint_type; + +extern int printf(const char *msg, ...); + +#if STACK_TRACE_ENABLED + +#define trace_printf printf + +#define CHECK(fn) \ + { \ + result = fn; \ + if (result != USB_ERR_OK && result != USB_ERR_STALL) { \ + if (result != USB_TOKEN_OUT_OF_SYNC) \ + printf("Error: %s:%d %d\r\n", __FILE__, __LINE__, result); \ + return result; \ + } \ + } + +#define RETURN_CHECK(fn) \ + { \ + result = fn; \ + if (result != USB_ERR_OK && result != USB_ERR_STALL) { \ + if (result != USB_TOKEN_OUT_OF_SYNC) \ + printf("Error: %s:%d %d\r\n", __FILE__, __LINE__, result); \ + return result; \ + } \ + return result; \ + } + +#define TRACE_USB_ERROR(result) \ + { \ + if (result != USB_ERR_OK) { \ + printf("USB: %s:%d %d\r\n", __FILE__, __LINE__, result); \ + } \ + } + +#else + +#define trace_printf(...) + +#define CHECK(fn) \ + { \ + result = fn; \ + if (result != USB_ERR_OK) \ + goto done; \ + } + +#define RETURN_CHECK(fn) \ + { \ + result = fn; \ + goto done; \ + } + +#define TRACE_USB_ERROR(result) + +#endif + +#define calc_max_packet_sizex(packet_size) (packet_size & 0x3FF) +#define calc_max_packet_size(packet_sizex) packet_sizex + +typedef struct { + uint8_t toggle : 1; + uint8_t number : 3; + uint16_t max_packet_sizex : 10; +} endpoint_param; + +#define CH_SPEED_FULL \ + 0 /* 12Mbps full speed FullSpeed ​​(default value) \ + */ +#define CH_SPEED_LOW_FREQ 1 /* 1.5Mbps (modify frequency only) */ +#define CH_SPEED_LOW 2 /* 1.5Mbps low speed LowSpeed */ + +#define CH_MODE_HOST_RESET 7 +#define CH_MODE_HOST 6 + +typedef enum _ch376_pid { CH_PID_SETUP = DEF_USB_PID_SETUP, CH_PID_IN = DEF_USB_PID_IN, CH_PID_OUT = DEF_USB_PID_OUT } ch376_pid; + +extern __sfr __banked CH376_DATA_PORT; +extern __sfr __banked CH376_COMMAND_PORT; + +extern __sfr __banked USB_MODULE_LEDS; + +extern void delay_20ms(void); +extern void delay_short(void); +extern void delay_medium(void); + +extern void ch_command(const uint8_t command) __z88dk_fastcall; +extern usb_error ch_get_status(void); +extern usb_error ch_long_get_status(void); +extern usb_error ch_short_get_status(void); +extern usb_error ch_very_short_status(void); +extern uint8_t ch_read_data(uint8_t *buffer) __sdcccall(1); +extern void ch_cmd_reset_all(void); +extern uint8_t ch_probe(void); +extern usb_error ch_cmd_set_usb_mode(const uint8_t mode) __z88dk_fastcall; +extern uint8_t ch_cmd_get_ic_version(void); +extern const uint8_t *ch_write_data(const uint8_t *buffer, uint8_t length); + +extern void ch_set_usb_address(const uint8_t device_address) __z88dk_fastcall; + +extern usb_error ch_control_transfer_request_descriptor(const uint8_t descriptor_type) __z88dk_fastcall; +extern usb_error ch_control_transfer_set_address(const uint8_t device_address) __z88dk_fastcall; +extern usb_error ch_control_transfer_set_config(const uint8_t config_value) __z88dk_fastcall; +extern usb_error ch_data_in_transfer(uint8_t *buffer, int16_t data_length, endpoint_param *const endpoint); +extern usb_error ch_data_in_transfer_n(uint8_t *buffer, uint8_t *const buffer_size, endpoint_param *const endpoint); +extern usb_error ch_data_out_transfer(const uint8_t *buffer, int16_t buffer_length, endpoint_param *const endpoint); + +inline void ch_configure_nak_retry(const ch_nak_retry_type retry, const uint8_t number_of_retries) { + ch_command(CH_CMD_WRITE_VAR8); + CH376_DATA_PORT = CH_VAR_RETRY_TIMES; + CH376_DATA_PORT = retry << 6 | (number_of_retries & 0x1F); +} + +#define ch_configure_nak_retry_indefinite() ch_configure_nak_retry(CH_NAK_RETRY_INDEFINITE, 0x1F) +#define ch_configure_nak_retry_disable() ch_configure_nak_retry(CH_NAK_RETRY_DONT, 0x1F) +#define ch_configure_nak_retry_3s() ch_configure_nak_retry(CH_NAK_RETRY_3S, 0x1F) + +extern void ch_issue_token_setup(void); +extern void ch_issue_token_out_ep0(void); +extern void ch_issue_token_in_ep0(void); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/ch376_init.c b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376_init.c new file mode 100644 index 00000000..4a3dc18c --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376_init.c @@ -0,0 +1,90 @@ +#include "print.h" +#include "usb-base-drv.h" + +static uint16_t wait_for_state(const uint8_t loop_counter, uint8_t state, const uint8_t desired_state) __sdcccall(1) { + uint16_t r = state; + + for (uint8_t i = 0; i < loop_counter; i++) { + if (state == desired_state) + break; + + if (i & 1) + print_string("\b $"); + else + print_string("\b*$"); + + r = usb_init(state); + state = r & 255; + } + + return r; +} + +extern const char ch376_driver_version[]; + +extern uint8_t CH376_DAT_PORT_ADDR; +extern uint8_t CH376_CMD_PORT_ADDR; +extern uint8_t USB_MOD_LEDS_ADDR; + +// there is a weird bug with the compilier - somtimes string literals containing +// a dollar sign -- the dollar sign is ignored! +const char comma_0_x_dollar[] = {' ', '0', 'x', '$'}; + +static void _chnative_init(bool forced) { + uint8_t state = 0; + uint16_t r; + const uint8_t loop_counter = forced ? 40 : 5; + + print_string("\r\nCH376: IO=0x$"); + print_hex((uint8_t)&CH376_DAT_PORT_ADDR); + print_string(comma_0_x_dollar); + print_hex((uint8_t)&CH376_CMD_PORT_ADDR); + print_string(comma_0_x_dollar); + print_hex((uint8_t)&USB_MOD_LEDS_ADDR); + print_string(" *$"); + + r = wait_for_state(loop_counter, state, 1); + state = r & 255; + + print_string("\bPRESENT (VER $"); + + r = usb_init(state); + state = r & 255; + if (state != 2) { + print_string("\rCH376: $"); + print_string("VERSION FAILURE\r\n$"); + return; + } + + print_hex(r >> 8); + print_string(ch376_driver_version); + + print_string("USB: *$"); + + r = wait_for_state(loop_counter, state, 3); + state = r & 255; + + if (state == 2) { + print_string("\bDISCONNECTED$"); + return; + } + + print_string("\bCONNECTED$"); + + // enumerate.... + r = usb_init(state); + state = r & 255; + + for (uint8_t i = 0; i < loop_counter; i++) { + if (r >> 8 != 0) + break; + + print_string(".$"); + r = usb_init(state); + state = r & 255; + } +} + +void chnative_init_force(void) { _chnative_init(true); } + +void chnative_init(void) { _chnative_init(false); } diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/ch376inc.h b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376inc.h new file mode 100644 index 00000000..ec760bca --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/ch376inc.h @@ -0,0 +1,1323 @@ +/* C Define for CH376 */ +/* Website: http://wch.cn */ +/* Email: tech@wch.cn */ +/* Author: W.ch 2008.10 */ +/* V1.0 for CH376 */ + +/* Oringinal file at + * https://github.com/changleo828/BOSSEN_USB_FOR_WT/blob/master/code/CH376INC.H + */ +/* google translated */ +/* other changes by Dean Netherton, 2022 */ + +#ifndef _CH376INC_H__ +#define _CH376INC_H__ + +#ifdef _cplusplus +extern " C " { +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Common types and constant definitions */ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#ifndef NULL +#define NULL 0 +#endif + +#ifndef UINT8 +typedef unsigned char UINT8; +#endif +#ifndef UINT16 +typedef unsigned short UINT16; +#endif +#ifndef UINT32 +typedef unsigned long UINT32; +#endif +#ifndef PUINT8 +typedef unsigned char *PUINT8; +#endif +#ifndef PUINT16 +typedef unsigned short *PUINT16; +#endif +#ifndef PUINT32 +typedef unsigned long *PUINT32; +#endif +#ifndef UINT8V +typedef unsigned char volatile UINT8V; +#endif +#ifndef PUINT8V +typedef unsigned char volatile *PUINT8V; +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Hardware features */ + +/* USB single data packet, the maximum length of the data block, the length of + * the default buffer */ + +#define CH376_DAT_BLOCK_LEN 0x40 + +/* ************************************************ + * **************************************************** ***************** */ +/* command code */ +/* Some commands are compatible with CH375 chip, but the input data or output + * data may be partially different) */ +/* A command sequence of operations consists of: + * A command code (for the serial port mode, two synchronization codes are + * required before the command code), Several input data (can be 0), Generate an + * interrupt notification or several output data (can be 0), choose one of the + * two, if there is an interrupt notification, there must be no output data, and + * if there is output data, no interrupt will be generated Only the + * CMD01_WR_REQ_DATA command is an exception, the sequence includes: one command + * code, one output data, several input data Command code naming rules: + * CMDxy_NAME Where x and y are numbers, x indicates the minimum number of input + * data (bytes), y indicates the minimum output data (bytes), if y is H, it + * indicates that an interrupt notification is generated, Some commands can read + * and write data blocks of 0 to multiple bytes, and the number of bytes of the + * data block itself is not included in the above x or y */ +/* This file will also provide a command code format compatible with the CH375 + * chip command code by default (that is, after removing x and y). If you don't + * need it, you can defineNO_CH375_COMPATIBLE_prohibit */ + +/* ************************************************ + * **************************************************** ***************** */ +/* Main commands (manual 1), commonly used */ + +/* Get the chip and firmware version + * Output: version number (bit 7 is 0, bit 6 is 1, bit 5~bit 0 is the version + * number) The value of the version number returned by CH376 is 041H, that is, + * the version number is 01H */ +#define CMD01_GET_IC_VER 0x01 + +/* Serial port mode: set the serial port communication baud rate (the default + baud rate after power-on or reset is 9600bps, selected by D4/D5/D6 pins) + * input: baud rate division factor, baud rate division constant + * output: operation status (CMD_RET_SUCCESS or CMD_RET_ABORT, other values + ​​indicate that the operation is not + * completed) */ +#define CMD21_SET_BAUDRATE 0x02 + +/* Enter sleep state */ +#define CMD00_ENTER_SLEEP 0x03 + +/* perform a hardware reset */ +#define CMD00_RESET_ALL 0x05 + +/* Test the communication interface and working status + * input: any data + * output: bitwise negation of the input data */ +#define CMD11_CHECK_EXIST 0x06 + +/* Device mode: set the way to check the USB bus suspend state + * Input: data 10H, check method + * 00H=do not check for USB suspend, 04H=check for USB suspend at 50mS + * intervals, 05H=check for USB suspend at 10mS intervals + */ +#define CMD20_CHK_SUSPEND 0x0B + +#define CMD20_SET_SDO_INT 0x0B /* SPI interface mode: set the interrupt mode of the SDO pin of SPI */ +/* input: data 16H, interrupt mode */ +/* 10H=SDO pin is disabled for interrupt output, tri-state output is disabled + * when SCS chip selection is invalid, 90H=SDO pin is also used as interrupt + * request output when SCS chip selection is invalid */ + +#define CMD14_GET_FILE_SIZE 0x0C /* Host file mode: get current file length */ +/* input: data 68H */ +/* Output: current file length (total length 32 bits, low byte first) */ + +#define CMD50_SET_FILE_SIZE 0x0D /* host file mode: set current file length */ +/* Input: data 68H, current file length (total length 32 bits, low byte first) + */ + +/* Set USB working mode + * input: mode code + * 00H=Device mode not enabled + * 01H=Device mode enabled and using external firmware mode (serial port not + * supported) 02H=Device mode enabled and using built-in firmware mode 03H=SD + * card host mode/inactive host mode, used to manage and access files in SD card + * 04H=Host mode not enabled + * 05H=Host mode enabled + * 06H=Host mode enabled and SOF packet generated automatically + * 07H=Host mode enabled and USB bus reset + * output: operation status (CMD_RET_SUCCESS or CMD_RET_ABORT, other values + * ​​indicate that the operation is not completed) */ +#define CMD11_SET_USB_MODE 0x15 + +#define CMD01_GET_STATUS 0x22 /* Get interrupt status and cancel interrupt request */ +/* output: interrupt status */ + +#define CMD00_UNLOCK_USB \ + 0x23 /* Device mode: release the current USB buffer \ + */ + +#define CMD01_RD_USB_DATA0 \ + 0x27 /* Read data block from current USB interrupt endpoint buffer or host \ + endpoint receive buffer */ +/* output: length, data stream */ + +#define CMD01_RD_USB_DATA \ + 0x28 /* Device mode: read the data block from the endpoint buffer of the \ + current USB interrupt, and release the buffer, equivalent to \ + CMD01_RD_USB_DATA0 + CMD00_UNLOCK_USB */ +/* output: length, data stream */ + +#define CMD10_WR_USB_DATA7 \ + 0x2B /* Device mode: write data block to the send buffer of USB endpoint 2 \ + */ +/* input: length, data stream */ + +#define CMD10_WR_HOST_DATA 0x2C /* Write a data block to the send buffer of the USB host endpoint */ +/* input: length, data stream */ + +#define CMD01_WR_REQ_DATA 0x2D /* Write the requested data block to the internal specified buffer */ +/* output: length */ +/* input: data stream */ + +#define CMD20_WR_OFS_DATA \ + 0x2E /* Write a data block to the specified offset address in the internal \ + buffer */ +/* input: offset, length, stream */ + +#define CMD10_SET_FILE_NAME 0x2F /* Host file mode: set the filename of the file to be operated on */ +/* Input: 0-terminated string (no more than 14 characters including terminator + * 0) */ + +/* ************************************************ + * **************************************************** ***************** */ +/* Main command (Manual 1), commonly used, the following commands always + * generate an interrupt notification at the end of the operation, and there is + * always no output data */ + +#define CMD0H_DISK_CONNECT \ + 0x30 /* host file mode / SD card not supported: check if disk is connected \ + */ +/* output interrupt */ + +#define CMD0H_DISK_MOUNT 0x31 /* host file mode: initialize disk and test if disk is ready */ +/* output interrupt */ + +/* Host file mode : open files or directories(folders), or enumerate files and + * directories(folders) output interrupt */ +#define CMD0H_FILE_OPEN 0x32 + +#define CMD0H_FILE_ENUM_GO \ + 0x33 /* Host file mode: continue enumerating files and directories (folders) \ + */ +/* output interrupt */ + +#define CMD0H_FILE_CREATE \ + 0x34 /* Host file mode: create a new file, if the file already exists, \ + delete it first */ +/* output interrupt */ + +#define CMD0H_FILE_ERASE \ + 0x35 /* Host file mode: delete the file, if it is already opened, delete it \ + directly, otherwise the file will be opened first and then deleted, \ + and the subdirectory must be opened first */ +/* output interrupt */ + +#define CMD1H_FILE_CLOSE \ + 0x36 /* Host file mode: close the currently opened file or directory \ + (folder) */ +/* input: whether to allow to update file length */ +/* 00H=Disable update length, 01H=Allow update length */ +/* output interrupt */ + +#define CMD1H_DIR_INFO_READ 0x37 /* Host file mode: read file directory information */ +/* Input: Specify the index number of the directory information structure to be + * read in the sector */ +/* The range of the index number is 00H~0FH, and the index number 0FFH is the + * currently opened file */ +/* output interrupt */ + +#define CMD0H_DIR_INFO_SAVE \ + 0x38 /*Host file mode : save file directory information */ /* output \ + interrupt */ + +#define CMD4H_BYTE_LOCATE 0x39 /* host file mode: move current file pointer in bytes */ +/* Input: offset bytes (total length 32 bits, low byte first) */ +/* output interrupt */ + +#define CMD2H_BYTE_READ 0x3A /* host file mode: read data block from current position in bytes */ +/* Input: The number of bytes requested to be read (total length is 16 bits, low + * byte first) */ +/* output interrupt */ + +#define CMD0H_BYTE_RD_GO 0x3B /* host file mode: continue byte read */ +/* output interrupt */ + +#define CMD2H_BYTE_WRITE 0x3C /* Host file mode: write data block to current location in bytes */ +/* Input: The number of bytes requested to be written (total length is 16 bits, + * low byte first) */ +/* output interrupt */ + +#define CMD0H_BYTE_WR_GO 0x3D /* host file mode: continue byte write */ +/* output interrupt */ + +#define CMD0H_DISK_CAPACITY 0x3E /* host file mode: query disk physical capacity */ +/* output interrupt */ + +#define CMD0H_DISK_QUERY \ + 0x3F /* Host file mode: query disk space information \ + */ +/* output interrupt */ + +#define CMD0H_DIR_CREATE \ + 0x40 /* Host file mode: create a new directory (folder) and open it, if the \ + * directory already exists, open it directly \ + */ +/* output interrupt */ + +#define CMD4H_SEC_LOCATE 0x4A /* Host file mode: move the current file pointer in sectors */ +/* Input: number of offset sectors (total length 32 bits, low byte first) */ +/* output interrupt */ + +#define CMD1H_SEC_READ \ + 0x4B /* host file mode / SD card not supported: read data blocks from \ + current location in sectors */ +/* input: the number of sectors requested to be read */ +/* output interrupt */ + +#define CMD1H_SEC_WRITE \ + 0x4C /* host file mode/SD card not supported: write data block at current \ + location in sectors */ +/* input: the number of sectors requested to be written */ +/* output interrupt */ + +#define CMD0H_DISK_BOC_CMD \ + 0x50 /* host mode/SD card not supported: command to execute BulkOnly \ + * transfer protocol for USB storage \ + */ +/* output interrupt */ + +#define CMD5H_DISK_READ \ + 0x54 /* host mode/SD card not supported: read physical sectors from USB \ + storage */ +/* Input: LBA physical sector address (total length 32 bits, low byte first), + * sector number (01H~FFH) */ +/* output interrupt */ + +#define CMD0H_DISK_RD_GO \ + 0x55 /* Host mode/SD card not supported: continue to perform physical sector \ + read operation of USB storage */ +/* output interrupt */ + +#define CMD5H_DISK_WRITE \ + 0x56 /* Host mode/SD card not supported: write physical sector to USB \ + storage */ +/* Input: LBA physical sector address (total length 32 bits, low byte first), + * sector number (01H~FFH) */ +/* output interrupt */ + +#define CMD0H_DISK_WR_GO \ + 0x57 /* Host mode/SD card not supported: continue to perform physical sector \ + write operation of USB storage */ +/* output interrupt */ + +/* ************************************************ + * **************************************************** ***************** */ +/* Auxiliary command (manual 2), not commonly used or for compatibility with + * CH375 and CH372 */ + +#define CMD10_SET_USB_SPEED \ + 0x04 /* Set the USB bus speed, it will automatically return to 12Mbps full \ + speed every time CMD11_SET_USB_MODE sets the USB working mode */ +/* input: bus speed code */ +/* 00H=12Mbps full speed FullSpeed ​​(default value), 01H=1.5Mbps (modify + * frequency only), 02H=1.5Mbps low speed LowSpeed ​​*/ + +#define CMD11_GET_DEV_RATE \ + 0x0A /* Host mode: Get the data rate type of the currently connected USB \ + device */ +/* input: data 07H */ +/* output: data rate type */ +/* If bit 4 is 1, it is a 1.5Mbps low-speed USB device, otherwise it is a 12Mbps + * full-speed USB device */ + +#define CMD11_GET_TOGGLE 0x0A /* Get the synchronization status of the OUT transaction */ +/* input: data 1AH */ +/* output: sync status */ +/* If bit 4 is 1, the OUT transaction is synchronized, otherwise the OUT + * transaction is not synchronized */ + +#define CMD11_READ_VAR8 \ + 0x0A /* Read the specified 8-bit file system variable \ + */ +/* input: variable address */ +/* output: data */ + +/* #define CMD11_GET_MAX_LUN = CMD11_READ_VAR8( VAR_UDISK_LUN ) */ +/* Host mode: Get the maximum and current logical unit number of USB storage */ + +#define CMD20_SET_RETRY \ + 0x0B /* Host mode: set the number of retries for USB transaction operations \ + */ +/* Input: data 25H, number of retries */ +/* Bit 7 is 0, no retry when receiving NAK, + bit 7 is 1, bit 6 is 0, infinite retry when receiving NAK, + bit 7 is 1, bit 6 is 1, retry for up to 3 seconds when receiving NAK, + bit 5~bit 0 is the number of retries after timeout */ + +#define CMD20_WRITE_VAR8 \ + 0x0B /* Set the specified 8-bit file system variable \ + */ +/* input: variable address, data */ + +/* #define CMD20_SET_DISK_LUN = CMD20_WRITE_VAR8( VAR_UDISK_LUN ) */ +/* Host mode: set the current logical unit number of the USB memory */ + +#define CMD14_READ_VAR32 0x0C /* Read the specified 32-bit file system variable */ +/* input: variable address */ +/* output: data (total length 32 bits, low byte first) */ + +#define CMD50_WRITE_VAR32 0x0D /* Set the specified 32-bit file system variable */ +/* Input: variable address, data (total length 32 bits, low byte first) */ + +#define CMD01_DELAY_100US 0x0F /* Delay 100uS (serial port not supported) */ +/* Output: output 0 during the delay, output non-0 after the delay */ + +#define CMD40_SET_USB_ID 0x12 /* Device Mode: Set USB Vendor VID and Product PID */ +/* Input: Manufacturer ID low byte, Manufacturer ID high byte, Product ID low + * byte, Product ID high byte */ + +#define CMD10_SET_USB_ADDR 0x13 /* Set USB address */ +/* input: address value */ + +#define CMD01_TEST_CONNECT \ + 0x16 /* host mode/SD card not supported: check USB device connection status \ + */ +/* output: status (USB_INT_CONNECT or USB_INT_DISCONNECT or USB_INT_USB_READY, + * other values ​​indicate that the operation is not complete) */ + +#define CMD00_ABORT_NAK 0x17 /* Host mode: Abort current NAK retry */ + +#define CMD10_SET_ENDP2 \ + 0x18 /* Device mode (serial port not supported): set the receiver for USB \ + endpoint 0 */ +/* input: how it works */ +/* If bit 7 is 1, bit 6 is the synchronization trigger bit, otherwise the + * synchronization trigger bit remains unchanged */ +/* Bit 3~Bit 0 is the transaction response mode: 0000-ready ACK, 1110-busy NAK, + * 1111-error STALL */ + +#define CMD10_SET_ENDP3 \ + 0x19 /* Device mode (serial port not supported): set the transmitter of USB \ + endpoint 0 */ +/* input: how it works */ +/* If bit 7 is 1, bit 6 is the synchronization trigger bit, otherwise the + * synchronization trigger bit remains unchanged */ +/* Bit 3~Bit 0 is the transaction response mode: 0000~1000-Ready ACK, 1110-Busy + * NAK, 1111-Error STALL */ + +#define CMD10_SET_ENDP4 \ + 0x1A /*Device mode(serial port not supported) : set the receiver of USB endpoint 1 */ /* input: how it works */ +/* If bit 7 is 1, bit 6 is the synchronization trigger bit, otherwise the + * synchronization trigger bit remains unchanged */ +/* Bit 3~Bit 0 is the transaction response mode: 0000-ready ACK, 1110-busy NAK, + * 1111-error STALL */ + +#define CMD10_SET_ENDP5 \ + 0x1B /* Device mode (serial port not supported): set the transmitter of USB \ + endpoint 1 */ +/* input: how it works */ +/* If bit 7 is 1, bit 6 is the synchronization trigger bit, otherwise the + * synchronization trigger bit remains unchanged */ +/* Bit 3~Bit 0 is the transaction response mode: 0000~1000-Ready ACK, 1110-Busy + * NAK, 1111-Error STALL */ + +#define CMD10_SET_ENDP6 0x1C /* Set the receiver for USB endpoint 2/host endpoint */ +/* input: how it works */ +/* If bit 7 is 1, bit 6 is the synchronization trigger bit, otherwise the + * synchronization trigger bit remains unchanged */ +/* Bit 3~Bit 0 is the transaction response mode: 0000-ready ACK, 1101-ready but + * not returning ACK, 1110-busy NAK, 1111-error STALL */ + +#define CMD10_SET_ENDP7 0x1D /* Set the transmitter for USB endpoint 2/host endpoint */ +/* input: how it works */ +/* If bit 7 is 1, bit 6 is the synchronization trigger bit, otherwise the + * synchronization trigger bit remains unchanged */ +/* Bit 3~Bit 0 is the transaction response mode: 0000-ready ACK, 1101-ready but + * no response, 1110-busy NAK, 1111-error STALL + */ + +#define CMD00_DIRTY_BUFFER 0x25 /* Host file mode: clear internal disk and file buffers */ + +#define CMD10_WR_USB_DATA3 \ + 0x29 /* Device mode (serial port not supported): write data block to the \ + * send buffer of USB endpoint 0 \ + */ +/* input: length, data stream */ + +#define CMD10_WR_USB_DATA5 \ + 0x2A /* Device mode (serial port not supported): write data block to the \ + * send buffer of USB endpoint 1 \ + */ +/* input: length, data stream */ + +/* ************************************************ + * **************************************************** ***************** */ +/* Auxiliary commands (manual 2), not commonly used or for compatibility with + * CH375 and CH372, the following commands always generate an interrupt + * notification at the end of the operation, and always have no output data */ + +#define CMD1H_CLR_STALL 0x41 /* host mode: control transfer - clear endpoint error */ +/* input: endpoint number */ +/* output interrupt */ + +#define CMD1H_SET_ADDRESS 0x45 /* host mode: control transfer - set usb address */ +/* input: address value */ +/* output interrupt */ + +#define CMD1H_GET_DESCR \ + 0x46 /* host mode: control transfer - get descriptor \ + */ +/* input: descriptor type */ +/* output interrupt */ + +#define CMD1H_SET_CONFIG 0x49 /* host mode: control transfer - set usb configuration */ +/* input: config value */ +/* output interrupt */ + +#define CMD0H_AUTO_SETUP 0x4D /* host mode/SD card not supported: auto configure USB device */ +/* output interrupt */ + +#define CMD2H_ISSUE_TKN_X \ + 0x4E /* Host mode: issue sync token, execute transaction, this command can \ + replace CMD10_SET_ENDP6/CMD10_SET_ENDP7 + CMD1H_ISSUE_TOKEN */ +/* input: sync flag, transaction attributes */ +/* Bit 7 of the synchronization flag is the synchronization trigger bit of the + * host endpoint IN, bit 6 is the synchronization trigger bit of the host + * endpoint OUT, bit 5~bit 0 must be 0 */ +/* The lower 4 bits of the transaction attribute are the token, and the upper 4 + * bits are the endpoint number */ +/* output interrupt */ + +#define CMD1H_ISSUE_TOKEN \ + 0x4F /* Host mode: issue token, execute transaction, it is recommended to \ + * use CMD2H_ISSUE_TKN_X command \ + */ +/* input: transaction properties */ +/* The lower 4 bits are the token, the upper 4 bits are the endpoint number */ +/* output interrupt */ + +#define CMD0H_DISK_INIT 0x51 /* host mode/SD card not supported: initialize USB storage */ +/* output interrupt */ + +#define CMD0H_DISK_RESET \ + 0x52 /* host mode/SD card not supported: control transfer - reset usb \ + storage */ +/* output interrupt */ + +#define CMD0H_DISK_SIZE 0x53 /* Host mode/SD card not supported: Get the capacity of USB storage */ +/* output interrupt */ + +#define CMD0H_DISK_INQUIRY \ + 0x58 /* host mode/SD card not supported: query USB storage characteristics \ + */ +/* output interrupt */ + +#define CMD0H_DISK_READY 0x59 /* host mode/SD card not supported: check usb storage ready */ +/* output interrupt */ + +#define CMD0H_DISK_R_SENSE 0x5A /* host mode /SD card not supported: check usb storage error */ +/* output interrupt */ + +#define CMD0H_RD_DISK_SEC \ + 0x5B /* Host file mode: read one sector of data from disk into internal \ + buffer */ +/* output interrupt */ + +#define CMD0H_WR_DISK_SEC \ + 0x5C /* Host file mode: write data of one sector of internal buffer to disk \ + */ +/* output interrupt */ + +#define CMD0H_DISK_MAX_LUN \ + 0x5D /* Host mode: control transfer - get the maximum logical unit number of \ + USB storage */ +/* output interrupt */ + +/* ************************************************ + * **************************************************** ***************** */ +/* The following definitions are only for compatibility with the command name + * format in the INCLUDE file of CH375 */ + +#ifndef NO_CH375_COMPATIBLE_ +#define CH_CMD_GET_IC_VER CMD01_GET_IC_VER +#define CH_CMD_SET_BAUDRATE CMD21_SET_BAUDRATE +#define CH_CMD_ENTER_SLEEP CMD00_ENTER_SLEEP +#define CH_CMD_RESET_ALL CMD00_RESET_ALL +#define CH_CMD_CHECK_EXIST CMD11_CHECK_EXIST +#define CH_CMD_CHK_SUSPEND CMD20_CHK_SUSPEND +#define CH_CMD_SET_SDO_INT CMD20_SET_SDO_INT +#define CH_CMD_GET_FILE_SIZE CMD14_GET_FILE_SIZE +#define CH_CMD_SET_FILE_SIZE CMD50_SET_FILE_SIZE +#define CH_CMD_SET_USB_MODE CMD11_SET_USB_MODE +#define CH_CMD_GET_STATUS CMD01_GET_STATUS +#define CH_CMD_UNLOCK_USB CMD00_UNLOCK_USB +#define CH_CMD_RD_USB_DATA0 CMD01_RD_USB_DATA0 +#define CH_CMD_RD_USB_DATA CMD01_RD_USB_DATA +#define CH_CMD_WR_USB_DATA7 CMD10_WR_USB_DATA7 +#define CH_CMD_WR_HOST_DATA CMD10_WR_HOST_DATA +#define CH_CMD_WR_REQ_DATA CMD01_WR_REQ_DATA +#define CH_CMD_WR_OFS_DATA CMD20_WR_OFS_DATA +#define CH_CMD_SET_FILE_NAME CMD10_SET_FILE_NAME +#define CH_CMD_DISK_CONNECT CMD0H_DISK_CONNECT +#define CH_CMD_DISK_MOUNT CMD0H_DISK_MOUNT +#define CH_CMD_FILE_OPEN CMD0H_FILE_OPEN +#define CH_CMD_FILE_ENUM_GO CMD0H_FILE_ENUM_GO +#define CH_CMD_FILE_CREATE CMD0H_FILE_CREATE +#define CH_CMD_FILE_ERASE CMD0H_FILE_ERASE +#define CH_CMD_FILE_CLOSE CMD1H_FILE_CLOSE +#define CH_CMD_DIR_INFO_READ CMD1H_DIR_INFO_READ +#define CH_CMD_DIR_INFO_SAVE CMD0H_DIR_INFO_SAVE +#define CH_CMD_BYTE_LOCATE CMD4H_BYTE_LOCATE +#define CH_CMD_BYTE_READ CMD2H_BYTE_READ +#define CH_CMD_BYTE_RD_GO CMD0H_BYTE_RD_GO +#define CH_CMD_BYTE_WRITE CMD2H_BYTE_WRITE +#define CH_CMD_BYTE_WR_GO CMD0H_BYTE_WR_GO +#define CH_CMD_DISK_CAPACITY CMD0H_DISK_CAPACITY +#define CH_CMD_DISK_QUERY CMD0H_DISK_QUERY +#define CH_CMD_DIR_CREATE CMD0H_DIR_CREATE +#define CH_CMD_SEC_LOCATE CMD4H_SEC_LOCATE +#define CH_CMD_SEC_READ CMD1H_SEC_READ +#define CH_CMD_SEC_WRITE CMD1H_SEC_WRITE +#define CH_CMD_DISK_BOC_CMD CMD0H_DISK_BOC_CMD +#define CH_CMD_DISK_READ CMD5H_DISK_READ +#define CH_CMD_DISK_RD_GO CMD0H_DISK_RD_GO +#define CH_CMD_DISK_WRITE CMD5H_DISK_WRITE +#define CH_CMD_DISK_WR_GO CMD0H_DISK_WR_GO +#define CH_CMD_SET_USB_SPEED CMD10_SET_USB_SPEED +#define CH_CMD_GET_DEV_RATE CMD11_GET_DEV_RATE +#define CH_CMD_GET_TOGGLE CMD11_GET_TOGGLE +#define CH_CMD_READ_VAR8 CMD11_READ_VAR8 +#define CH_CMD_SET_RETRY CMD20_SET_RETRY +#define CH_CMD_WRITE_VAR8 CMD20_WRITE_VAR8 +#define CH_CMD_READ_VAR32 CMD14_READ_VAR32 +#define CH_CMD_WRITE_VAR32 CMD50_WRITE_VAR32 +#define CH_CMD_DELAY_100US CMD01_DELAY_100US +#define CH_CMD_SET_USB_ID CMD40_SET_USB_ID +#define CH_CMD_SET_USB_ADDR CMD10_SET_USB_ADDR +#define CH_CMD_TEST_CONNECT CMD01_TEST_CONNECT +#define CH_CMD_ABORT_NAK CMD00_ABORT_NAK +#define CH_CMD_SET_ENDP2 CMD10_SET_ENDP2 +#define CH_CMD_SET_ENDP3 CMD10_SET_ENDP3 +#define CH_CMD_SET_ENDP4 CMD10_SET_ENDP4 +#define CH_CMD_SET_ENDP5 CMD10_SET_ENDP5 +#define CH_CMD_SET_ENDP6 CMD10_SET_ENDP6 +#define CH_CMD_SET_ENDP7 CMD10_SET_ENDP7 +#define CH_CMD_DIRTY_BUFFER CMD00_DIRTY_BUFFER +#define CH_CMD_WR_USB_DATA3 CMD10_WR_USB_DATA3 +#define CH_CMD_WR_USB_DATA5 CMD10_WR_USB_DATA5 +#define CH_CMD_CLR_STALL CMD1H_CLR_STALL +#define CH_CMD_SET_ADDRESS CMD1H_SET_ADDRESS +#define CH_CMD_GET_DESCR CMD1H_GET_DESCR +#define CH_CMD_SET_CONFIG CMD1H_SET_CONFIG +#define CH_CMD_AUTO_SETUP CMD0H_AUTO_SETUP +#define CH_CMD_ISSUE_TKN_X CMD2H_ISSUE_TKN_X +#define CH_CMD_ISSUE_TOKEN CMD1H_ISSUE_TOKEN +#define CH_CMD_DISK_INIT CMD0H_DISK_INIT +#define CH_CMD_DISK_RESET CMD0H_DISK_RESET +#define CH_CMD_DISK_SIZE CMD0H_DISK_SIZE +#define CH_CMD_DISK_INQUIRY CMD0H_DISK_INQUIRY +#define CH_CMD_DISK_READY CMD0H_DISK_READY +#define CH_CMD_DISK_R_SENSE CMD0H_DISK_R_SENSE +#define CH_CMD_RD_DISK_SEC CMD0H_RD_DISK_SEC +#define CH_CMD_WR_DISK_SEC CMD0H_WR_DISK_SEC +#define CH_CMD_DISK_MAX_LUN CMD0H_DISK_MAX_LUN +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Parallel port mode, bit definition of status port (read command port) */ +#ifndef PARA_STATE_INTB +#define PARA_STATE_INTB 0x80 /* Bit 7 of parallel port status port: interrupt flag, active low */ +#define PARA_STATE_BUSY 0x10 /* Bit 4 of parallel port status port: busy flag, active high */ +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Serial mode, boot synchronization code before the operation command */ +#ifndef SER_CMD_TIMEOUT +#define SER_CMD_TIMEOUT \ + 32 /* Serial command timeout time, the unit is mS, the interval between \ + synchronization codes and between synchronization codes and command \ + codes should be as short as possible, and the processing method after \ + timeout is to discard */ +#define SER_SYNC_CODE1 0x57 /* The first serial port synchronization code to start the operation */ +#define SER_SYNC_CODE2 \ + 0xAB /* The second serial port synchronization code to start the operation \ + */ +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Operation status */ + +#ifndef CH_CMD_RET_SUCCESS +#define CH_CMD_RET_SUCCESS 0x51 /* Command operation succeeded */ +#define CH_CMD_RET_ABORT 0x5F /* Command operation failed */ +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* USB interrupt status */ + +#ifndef USB_INT_EP0_SETUP + +/* The following status codes are special event interrupts, if the USB bus + * suspend check is enabled through CMD20_CHK_SUSPEND, then the interrupt status + * of USB bus suspend and sleep wakeup must be handled */ +#define USB_INT_USB_SUSPEND 0x05 /* USB bus suspend event */ +#define USB_INT_WAKE_UP 0x06 /* Wake from sleep event */ + +/* The following status code 0XH is used for USB device mode */ +/* Only need to process in built-in firmware mode: USB_INT_EP1_OUT, + * USB_INT_EP1_IN, USB_INT_EP2_OUT, USB_INT_EP2_IN */ +/* bit 7 - bit 4 is 0000 */ +/* Bit 3-Bit 2 indicates the current transaction, 00=OUT, 10=IN, 11=SETUP */ +/* Bit 1-Bit 0 indicates the current endpoint, 00=Endpoint 0, 01=Endpoint 1, + * 10=Endpoint 2, 11=USB bus reset */ +#define USB_INT_EP0_SETUP 0x0C /* SETUP for USB endpoint 0 */ +#define USB_INT_EP0_OUT 0x00 /* OUT of USB endpoint 0 */ +#define USB_INT_EP0_IN 0x08 /* IN for USB endpoint 0 */ +#define USB_INT_EP1_OUT 0x01 /* OUT of USB endpoint 1 */ +#define USB_INT_EP1_IN 0x09 /* IN for USB endpoint 1 */ +#define USB_INT_EP2_OUT 0x02 /* OUT of USB endpoint 2 */ +#define USB_INT_EP2_IN 0x0A /* IN for USB endpoint 2 */ +/* USB_INT_BUS_RESET 0x0000XX11B */ +/* USB bus reset */ +#define USB_INT_BUS_RESET1 0x03 /* USB bus reset */ +#define USB_INT_BUS_RESET2 0x07 /* USB bus reset */ +#define USB_INT_BUS_RESET3 0x0B /* USB bus reset */ +#define USB_INT_BUS_RESET4 0x0F /* USB bus reset */ + +#endif + +/* The following status codes 2XH-3XH are used for communication failure codes + * in USB host mode */ +/* bit 7 - bit 6 is 00 */ +/* bit 5 is 1 */ +/* Bit 4 indicates whether the currently received packet is synchronized */ +/* Bit 3-Bit 0 indicates the response from the USB device when communication + * failed: 0010=ACK, 1010=NAK, 1110=STALL, 0011=DATA0, 1011=DATA1, XX00=timeout + */ +/* USB_INT_RET_ACK 0x001X0010B */ +/* ERROR: return ACK for IN transaction */ +/* USB_INT_RET_NAK 0x001X1010B */ +/* Error: return NAK */ +/* USB_INT_RET_STALL 0x001X1110B */ +/* Error: return STALL */ +/* USB_INT_RET_DATA0 0x001X0011B */ +/* Error: DATA0 returned for OUT/SETUP transactions */ +/* USB_INT_RET_DATA1 0x001X1011B */ +/* ERROR: DATA1 returned for OUT/SETUP transactions */ +/* USB_INT_RET_TOUT 0x001XXX00B */ +/* Error: return timeout */ +/* USB_INT_RET_TOGX 0x0010X011B */ +/* Error: return data out of sync for IN transaction */ +/* USB_INT_RET_PID 0x001XXXXXB */ +/* ERROR: undefined */ + +/* The following status code 1XH is used for the operation status code of USB + * host mode */ +#ifndef CH_USB_INT_SUCCESS + +/* USB transaction or transfer operation succeeded */ +#define CH_USB_INT_SUCCESS 0x14 + +/* A USB device connection event is detected, it may be a new connection or + * reconnection after disconnection */ +#define CH_USB_INT_CONNECT 0x15 + +/* USB device disconnection event detected */ +#define CH_USB_INT_DISCONNECT 0x16 + +/* The data transmitted by USB is wrong or the buffer overflows due to too much + * data */ +#define CH_USB_INT_BUF_OVER 0x17 + +/* USB device has been initialized (USB address has been assigned) */ +#define CH_USB_INT_USB_READY 0x18 + +/* USB storage request data read */ +#define CH_USB_INT_DISK_READ 0x1D + +/* USB storage request data write */ +#define CH_USB_INT_DISK_WRITE 0x1E + +/* USB storage operation failed */ +#define CH_USB_INT_DISK_ERR 0x1F +#endif + +/* The following status codes are used for file system error codes in host file + * mode */ +#ifndef ERR_DISK_DISCON + +/* The disk has not been connected, maybe the disk has been disconnected */ +#define ERR_DISK_DISCON 0x82 + +/*The sector of the disk is too large, only 512 bytes per sector are supported */ +#define ERR_LARGE_SECTOR 0x84 + +/* The disk partition type is not supported, only FAT12/FAT16/BigDOS/FAT32 is supported, it needs to be re-partitioned by the disk + * management tool */ +#define ERR_TYPE_ERROR 0x92 + +/* The disk has not been formatted, or the parameters are wrong and need to be reformatted by WINDOWS with default parameters */ +#define ERR_BPB_ERROR 0xA1 + +/* The disk file is too full, the remaining space is too little or there is no more, and disk defragmentation is required */ +#define ERR_DISK_FULL 0xB1 + +/* There are too many files in the directory(folder), there is no free directory entry, the number of files in the FAT12 / FAT16 + * root directory should be less than 512, and disk defragmentation is required */ +#define ERR_FDT_OVER 0xB2 + +/*The file has been closed, it should be reopened if needed */ +#define ERR_FILE_CLOSE 0xB4 + +/* The directory (folder) of the specified path is opened */ +#define ERR_OPEN_DIR 0x41 + +/* The file in the specified path is not found, maybe the file name is wrong */ +#define ERR_MISS_FILE 0x42 + +/* Search for a matching file name, or ask to open a directory (folder) but the actual result opens the file */ + +/* The following file system error codes are used for file system subroutines */ +#define ERR_FOUND_NAME 0x43 + +/* A subdirectory(folder) of the specified path is not found, maybe the directory name is wrong */ +#define ERR_MISS_DIR 0xB3 + +/* long file buffer overflow */ +#define ERR_LONG_BUF_OVER 0x48 + +/* The short file name does not have a corresponding long file name or the long file name is wrong */ +#define ERR_LONG_NAME_ERR 0x49 + +/* A short file with the same name already exists, it is recommended to regenerate another short file name */ +#define ERR_NAME_EXIST 0x4A + +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* The following status codes are used for disk and file status in host file + * mode, VAR_DISK_STATUS */ +#ifndef DEF_DISK_UNKNOWN + +/*Not initialized, unknown state */ +#define DEF_DISK_UNKNOWN 0x00 + +/* The disk is not connected or has been disconnected */ +#define DEF_DISK_DISCONN 0x01 + +/* The disk is connected, but it has not been initialized or the disk cannot be recognized */ +#define DEF_DISK_CONNECT 0x02 + +/* The disk has been initialized successfully, but the file system has not been analyzed or the file system does not support */ +#define DEF_DISK_MOUNTED 0x03 + +/* The file system of the disk has been analyzed and can support */ +#define DEF_DISK_READY 0x10 + +/* The root directory has been opened and must be closed after use. Note that the FAT12/FAT16 root directory is a fixed length */ +#define DEF_DISK_OPEN_ROOT 0x12 + +/* A subdirectory (folder) has been opened */ +#define DEF_DISK_OPEN_DIR 0x13 + +/* The file has been opened */ +#define DEF_DISK_OPEN_FILE 0x14 +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Common definitions of file system */ + +#ifndef DEF_SECTOR_SIZE +/* The default physical sector size of U disk or SD card */ +#define DEF_SECTOR_SIZE 512 +#endif + +#ifndef DEF_WILDCARD_CHAR +#define DEF_WILDCARD_CHAR 0x2A /* Wildcard '*' for pathname */ +#define DEF_SEPAR_CHAR1 0x5C /* The path name separator '\' */ +#define DEF_SEPAR_CHAR2 0x2F /* The delimiter of the path name '/' */ +#define DEF_FILE_YEAR 2004 /* Default file date: 2004 */ +#define DEF_FILE_MONTH 1 /* Default file date: January */ +#define DEF_FILE_DATE 1 /* Default file date: 1st */ +#endif + +#ifndef ATTR_DIRECTORY + +/* File directory information in FAT data area */ +typedef struct FAT_DIR_INFO { + UINT8 DIR_Name[11]; /* 00H, file name, a total of 11 bytes, fill in blanks */ + UINT8 DIR_Attr; /* 0BH, file attribute, refer to the following description */ + UINT8 DIR_NTRes; /* 0CH */ + UINT8 DIR_CrtTimeTenth; /* 0DH, the time of file creation, counted in 0.1 + second units */ + UINT16 DIR_CrtTime; /* 0EH, file creation time */ + UINT16 DIR_CrtDate; /* 10H, the date the file was created */ + UINT16 DIR_LstAccDate; /* 12H, the date of the last access operation */ + UINT16 DIR_FstClusHI; /* 14H */ + UINT16 DIR_WrtTime; /* 16H, file modification time, refer to the previous + macro MAKE_FILE_TIME */ + UINT16 DIR_WrtDate; /* 18H, file modification date, refer to the previous + macro MAKE_FILE_DATE */ + UINT16 DIR_FstClusLO; /* 1AH */ + UINT32 DIR_FileSize; /* 1CH, file length */ +} FAT_DIR_INFO, *P_FAT_DIR_INFO; /* 20H */ + +/* file attributes */ +#define ATTR_READ_ONLY 0x01 /* The file is read-only */ +#define ATTR_HIDDEN 0x02 /* file is a hidden attribute */ +#define ATTR_SYSTEM 0x04 /* The file is a system attribute */ +#define ATTR_VOLUME_ID 0x08 /* Volume label */ +#define ATTR_DIRECTORY 0x10 /* subdirectories (folders) */ +#define ATTR_ARCHIVE 0x20 /* file is archive attribute */ +#define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID) /* long filename attribute */ +#define ATTR_LONG_NAME_MASK (ATTR_LONG_NAME | ATTR_DIRECTORY | ATTR_ARCHIVE) +/* file attribute UINT8 */ +/* bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7 */ +/* Only hidden volume is undefined */ +/* Read the Tibetan standard record file */ +/* file time UINT16 */ +/* Time = (Hour<<11) + (Minute<<5) + (Second>>1) */ +#define MAKE_FILE_TIME \ + (h, m, s)((h << 11) + (m << 5) + (s >> 1)) /* Generate file time data of specified \ + hours, minutes and seconds */ +/* file date UINT16 */ +/* Date = ((Year-1980)<<9) + (Month<<5) + Day */ +#define MAKE_FILE_DATE \ + (y, m, d)(((y - 1980) << 9) + (m << 5) + d) /* Generate the file date data of the \ + specified year, month and day */ + +#define LONE_NAME_MAX_CHAR (255 * 2) /* The maximum number of characters/bytes of the long file name */ +#define LONG_NAME_PER_DIR \ + (13 * 2) /* The number of characters/bytes of the long file name in the \ + directory information structure of each file */ + +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* SCSI command and data input and output structures */ + +#ifndef SPC_CMD_INQUIRY + +/* SCSI command code */ +#define SPC_CMD_INQUIRY 0x12 +#define SPC_CMD_READ_CAPACITY 0x25 +#define SPC_CMD_READ10 0x28 +#define SPC_CMD_WRITE10 0x2A +#define SPC_CMD_TEST_READY 0x00 +#define SPC_CMD_REQUEST_SENSE 0x03 +#define SPC_CMD_MODESENSE6 0x1A +#define SPC_CMD_MODESENSE10 0x5A +#define SPC_CMD_START_STOP 0x1B + +/* BulkOnly protocol command block */ +typedef struct BULK_ONLY_CBW { + UINT32 CBW_Sig; + UINT32 CBW_Tag; + UINT8 CBW_DataLen0; /* 08H, input: data transmission length, the valid value + for input data is 0 to 48, and the valid value for + output data is 0 to 33 */ + UINT8 CBW_DataLen1; + UINT16 CBW_DataLen2; + UINT8 CBW_Flag; /* 0CH, input: transmission direction and other flags, if bit + 7 is 1, input data, if bit 0, output data or no data */ + UINT8 CBW_LUN; + UINT8 CBW_CB_Len; /* 0EH, input: the length of the command block, valid values + ​​are 1 to 16 */ + UINT8 CBW_CB_Buf[16]; /* 0FH, input: command block, the buffer is up to 16 + bytes */ +} BULK_ONLY_CBW, *P_BULK_ONLY_CBW; /* BulkOnly protocol command block, input CBW structure */ + +/* INQUIRY command return data */ +typedef struct INQUIRY_DATA { + UINT8 DeviceType; /* 00H, device type */ + UINT8 RemovableMedia; /* 01H, if bit 7 is 1, it means removable storage */ + UINT8 Versions; /* 02H, protocol version */ + UINT8 DataFormatAndEtc; /* 03H, specify the return data format */ + UINT8 AdditionalLength; /* 04H, the length of subsequent data */ + UINT8 Reserved1; + UINT8 Reserved2; + UINT8 MiscFlag; /* 07H, some control flags */ + UINT8 VendorIdStr[8]; /* 08H, Vendor information */ + UINT8 ProductIdStr[16]; /* 10H, product information */ + UINT8 ProductRevStr[4]; /* 20H, product version */ +} INQUIRY_DATA, *P_INQUIRY_DATA; /* 24H */ + +/* REQUEST SENSE command return data */ +typedef struct SENSE_DATA { + UINT8 ErrorCode; /* 00H, error code and valid bits */ + UINT8 SegmentNumber; + UINT8 SenseKeyAndEtc; /* 02H, primary key code */ + UINT8 Information0; + UINT8 Information1; + UINT8 Information2; + UINT8 Information3; + UINT8 AdditSenseLen; /* 07H, the length of subsequent data */ + UINT8 CmdSpecInfo[4]; + UINT8 AdditSenseCode; /* 0CH, additional key code */ + UINT8 AddSenCodeQual; /* 0DH, detailed additional key code */ + UINT8 FieldReplaUnit; + UINT8 SenseKeySpec[3]; +} SENSE_DATA, *P_SENSE_DATA; /* 12H */ + +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Data input and output structures in host file mode */ + +#ifndef MAX_FILE_NAME_LEN + +#define MAX_FILE_NAME_LEN \ + (13 + 1) /* The maximum length of the file name, the maximum length is 1 \ + root directory character + 8 main file names + 1 decimal point + \ + 3 type names + terminator = 14 */ + +/* Command input data and output data */ +typedef union CH376_CMD_DATA { + struct { + UINT8 mBuffer[MAX_FILE_NAME_LEN]; + } Default; + + INQUIRY_DATA DiskMountInq; /* Return: return data of INQUIRY command */ + /* CMD0H_DISK_MOUNT: Initialize the disk and test if the disk is ready, when + * executed for the first time */ + + FAT_DIR_INFO OpenDirInfo; /* Return: Enumerated file directory information */ + /* CMD0H_FILE_OPEN: Enumerate files and directories (folders) */ + + FAT_DIR_INFO EnumDirInfo; /* Return: Enumerated file directory information */ + /* CMD0H_FILE_ENUM_GO: Continue to enumerate files and directories (folders) + */ + + struct { + UINT8 mUpdateFileSz; /* Input parameter: whether to allow the file length to + be updated, or 0 to prohibit the update of the + length */ + } FileCLose; /* CMD1H_FILE_CLOSE: close the currently opened file */ + + struct { + UINT8 mDirInfoIndex; /* Input parameters: specify the index number of the + directory information structure to be read in the + sector, 0FFH is the currently opened file */ + } DirInfoRead; /* CMD1H_DIR_INFO_READ: read the directory information of the + file */ + + union { + UINT32 mByteOffset; /* Input parameter: number of offset bytes, offset in + bytes (total length 32 bits, low byte first) */ + UINT32 + mSectorLba; /* Return: the absolute linear sector number corresponding + to the current file pointer, 0FFFFFFFFH has reached the + end of the file (total length 32 bits, low byte first) */ + } ByteLocate; /* CMD4H_BYTE_LOCATE: move the current file pointer in bytes */ + + struct { + UINT16 + mByteCount; /* Input parameter: the number of bytes requested to be read + (total length is 16 bits, low byte first) */ + } ByteRead; /* CMD2H_BYTE_READ: read data block from current position in bytes + */ + + struct { + UINT16 mByteCount; /* Input parameter: the number of bytes requested to be + written (total length is 16 bits, low byte first) */ + } ByteWrite; /* CMD2H_BYTE_WRITE: Write a block of data to the current + location in bytes */ + + union { + UINT32 mSectorOffset; /* Input parameter: number of offset sectors, offset + in sector (total length 32 bits, low byte first) */ + UINT32 + mSectorLba; /* Return: the absolute linear sector number corresponding + to the current file pointer, 0FFFFFFFFH has reached the + end of the file (total length 32 bits, low byte first) */ + } SectorLocate; /* CMD4H_SEC_LOCATE: move the current file pointer in sectors + */ + + struct { + UINT8 mSectorCount; /* Input parameters: the number of sectors requested to + be read */ + /* return: the number of sectors allowed to be read */ + UINT8 mReserved1; + UINT8 mReserved2; + UINT8 mReserved3; + UINT32 mStartSector; /* Return: The starting absolute linear sector number + of the sector block allowed to be read (total length + 32 bits, low byte first) */ + } SectorRead; /* CMD1H_SEC_READ: Read the data block from the current position + in sectors */ + + struct { + UINT8 mSectorCount; /* Input parameters: the number of sectors requested to + be written */ + /* return: the number of sectors allowed to be written */ + UINT8 mReserved1; + UINT8 mReserved2; + UINT8 mReserved3; + UINT32 mStartSector; /* Return: the starting absolute linear sector number + of the sector block allowed to be written (total + length 32 bits, low byte first) */ + } SectorWrite; /* CMD1H_SEC_WRITE: Write a data block at the current location + in sectors */ + + struct { + UINT32 + mDiskSizeSec; /* Return: the total number of sectors of the entire + physical disk (total length 32 bits, low byte first) */ + } DiskCapacity; /* CMD0H_DISK_CAPACITY: Query the physical capacity of the + disk */ + + struct { + UINT32 mTotalSector; /* Return: the total number of sectors of the current + logical disk (total length is 32 bits, low byte + first) */ + UINT32 mFreeSector; /* Return: the number of remaining sectors of the + current logical disk (total length is 32 bits, low + byte first) */ + UINT8 mDiskFat; /* Return: FAT type of the current logical disk, 1-FAT12, + 2-FAT16, 3-FAT32 */ + } DiskQuery; /* CMD_DiskQuery, query disk information */ + + BULK_ONLY_CBW DiskBocCbw; /* Input parameters: CBW command structure */ + /* CMD0H_DISK_BOC_CMD: command to execute BulkOnly transfer protocol to USB + * memory */ + + struct { + UINT8 mMaxLogicUnit; /* return: the maximum logic unit number of the USB + memory */ + } DiskMaxLun; /* CMD0H_DISK_MAX_LUN: Control transfer - get the maximum + logical unit number of USB memory */ + + INQUIRY_DATA DiskInitInq; /* Return: return data of INQUIRY command */ + /* CMD0H_DISK_INIT: Initialize USB storage */ + + INQUIRY_DATA DiskInqData; /* Return: return data of INQUIRY command */ + /* CMD0H_DISK_INQUIRY: Query USB storage characteristics */ + + SENSE_DATA ReqSenseData; /* Return: REQUEST SENSE command return data */ + /* CMD0H_DISK_R_SENSE: Check for USB storage errors */ + + struct { + UINT32 mDiskSizeSec; /* Return: the total number of sectors of the entire + physical disk (total length is 32 bits, high byte + first) */ + } DiskSize; /* CMD0H_DISK_SIZE: Get the capacity of the USB memory */ + + struct { + UINT32 mStartSector; /* Input parameters: LBA sector address (total length + 32 bits, low byte first) */ + UINT8 mSectorCount; /* Input parameters: the number of sectors requested to + be read */ + } DiskRead; /* CMD5H_DISK_READ: Read data blocks from USB memory (in sectors) + */ + + struct { + UINT32 mStartSector; /* Input parameters: LBA sector address (total length + 32 bits, low byte first) */ + UINT8 mSectorCount; /* Input parameters: the number of sectors requested to + be written */ + } DiskWrite; /* CMD5H_DISK_WRITE: Write data block to USB memory (in sectors) + */ +} CH376_CMD_DATA, *P_CH376_CMD_DATA; + +#endif + +/* ************************************************ + * **************************************************** ***************** */ +/* Address of filesystem variable in host file mode */ + +#ifndef VAR_FILE_SIZE + +/* 8-bit/single-byte variable */ + +/* Basic information of the current system + * Bit 6 is used to indicate the subclass SubClass-Code of the USB storage + * device. If bit 6 is 0, it means that the subclass is 6, and if bit 6 is 1, it + * means that the subclass is other than 6 Bit 5 is used to indicate the USB + * configuration status in USB device mode and the USB device connection status + * in USB host mode In USB device mode, if bit 5 is 1, the USB configuration is + * complete, and if bit 5 is 0, it has not yet been configured In USB host mode, + * if bit 5 is 1, there is a USB device on the USB port, and if bit 5 is 0, + * there is no USB device on the USB port Bit 4 is used to indicate the buffer + * lock state in USB device mode. If bit 4 is 1, it means that the USB buffer is + * in a locked state. If bit 6 is 1, it means it has been released Other bits, + * reserved, do not modify */ +#define CH_VAR_SYS_BASE_INFO 0x20 + +/* The number of retries for the USB transaction operation + * If bit 7 is 0, it will not retry when receiving NAK, if bit 7 is 1, if bit 6 + * is 0, it will retry infinitely when receiving NAK (you can use CMD_ABORT_NAK + * command to give up retry), if bit 7 is 1, bit 6 is 1 Retry for up to 3 + * seconds when NAK is received Bit 5~Bit 0 is the number of retries after + * timeout */ +#define CH_VAR_RETRY_TIMES 0x25 + +/* Bit flag in host file mode + * Bit 1 and bit 0, FAT file system flag of the logical disk, 00-FAT12, + * 01-FAT16, 10-FAT32, 11-Illegal Bit 2, whether the FAT table data in the + * current buffer has been modified, 0-unmodified, 1-modified Bit 3, the file + * length needs to be modified flag, the current file is appended with data, + * 0-no modification is required if it is not appended, 1-modification is + * required if it has been appended Other bits, reserved, do not modify */ +#define CH_VAR_FILE_BIT_FLAG 0x26 + +/* Disk and file status in host file mode */ +#define CH_VAR_DISK_STATUS 0x2B + +/* Bit flag of SD card in host file mode + * Bit 0, SD card version, 0-only supports SD first version, 1-supports SD + * second version bit 1, auto-identification, 0-SD card, 1-MMC card Bit 2, + * automatic identification, 0-standard capacity SD card, 1-high capacity SD + * card (HC-SD) bit 4, ACMD41 command timeout bit 5, CMD1 command timeout bit 6, + * CMD58 command timeout Other bits, reserved, do not modify */ +#define CH_VAR_SD_BIT_FLAG 0x30 + +/* Sync flag for BULK-IN/BULK-OUT endpoint of USB storage device + * bit 7, sync flag for Bulk-In endpoint + * bit 6, sync flag for Bulk-In endpoint + * Bit 5~Bit 0, must be 0 */ +#define CH_VAR_UDISK_TOGGLE 0x31 + +/* The logical unit number of the USB storage device + * Bit 7~Bit 4, the current logical unit number of the USB storage device, after + * CH376 initializes the USB storage device, the default is to access the 0# + * logical unit Bit 3~Bit 0, the maximum logical unit number of the USB storage + * device, plus 1 equals the number of logical units */ +#define CH_VAR_UDISK_LUN 0x34 + +/* Number of sectors per cluster of logical disk */ +#define CH_VAR_SEC_PER_CLUS 0x38 + +/* The index number of the current file directory information in the sector */ +#define CH_VAR_FILE_DIR_INDEX 0x3B + +/* The sector offset of the current file pointer in the cluster, if it is 0xFF, + * it points to the end of the file and the end of the cluster */ +#define CH_VAR_CLUS_SEC_OFS 0x3C + +/* 32-bit/4-byte variable + * For FAT16 disk, it is the number of sectors occupied by the root directory, + * and for FAT32 disk, it is the starting cluster number of the root directory + * (total length 32 bits, low byte first) */ +#define CH_VAR_DISK_ROOT 0x44 + +/* The total number of clusters of the logical disk(total length is 32 bits, low + * byte first) */ +#define CH_VAR_DSK_TOTAL_CLUS 0x48 + +/* The starting absolute sector number LBA of the logical disk(total length is + * 32 bits, low byte first) */ +#define CH_VAR_DSK_START_LBA 0x4C + +/* The starting LBA of the data area of ​​the logical disk (total length is + * 32 bits, low byte first) */ +#define CH_VAR_DSK_DAT_START 0x50 + +/* The LBA corresponding to the data in the current disk data buffer (total + * length is 32 bits, low byte first) */ +#define CH_VAR_LBA_BUFFER 0x54 + +/* The current read and write disk start LBA address (total length 32 bits, low + * byte first) */ +#define CH_VAR_LBA_CURRENT 0x58 + +/* LBA address of the sector where the current file directory information is + * located (total length 32 bits, low byte first) + */ +#define CH_VAR_FAT_DIR_LBA 0x5C + +/* The starting cluster number of the current file or directory (folder) (total + * length 32 bits, low byte first) */ +#define CH_VAR_START_CLUSTER 0x60 + +/* The current cluster number of the current file (total length is 32 bits, low + * byte first) */ +#define CH_VAR_CURRENT_CLUST 0x64 + +/* The length of the current file (total length is 32 bits, low byte first) */ +#define CH_VAR_FILE_SIZE 0x68 + +/* The current file pointer, the byte offset of the current read and write + * position(total length 32 bits, low byte first) */ +#define CH_VAR_CURRENT_OFFSET 0x6C + +#endif + +/* ******************************************************************************************************************/ +/* Common USB definitions */ + +/* USB packet identification PID, the host mode may be used */ +#ifndef DEF_USB_PID_SETUP +#define DEF_USB_PID_NULL 0x00 /* PID reserved, undefined */ +#define DEF_USB_PID_SOF 0x05 +#define DEF_USB_PID_SETUP 0x0D +#define DEF_USB_PID_IN 0x09 +#define DEF_USB_PID_OUT 0x01 +#define DEF_USB_PID_ACK 0x02 +#define DEF_USB_PID_NAK 0x0A +#define DEF_USB_PID_STALL 0x0E +#define DEF_USB_PID_DATA0 0x03 +#define DEF_USB_PID_DATA1 0x0B +#define DEF_USB_PID_PRE 0x0C +#endif + +/* USB request type, may be used in external firmware mode */ +#ifndef DEF_USB_REQ_TYPE +#define DEF_USB_REQ_READ 0x80 /* Control read operation */ +#define DEF_USB_REQ_WRITE 0x00 /* Control write operation */ +#define DEF_USB_REQ_TYPE 0x60 /* Control request type */ +#define DEF_USB_REQ_STAND 0x00 /* Standard Request */ +#define DEF_USB_REQ_CLASS 0x20 /* Device class request */ +#define DEF_USB_REQ_VENDOR 0x40 /* Vendor Request */ +#define DEF_USB_REQ_RESERVE 0x60 /* Reservation Request */ +#endif + +/* USB standard device request, Bit 6 of RequestType 5=00 (Standard), external + * firmware mode may be used */ +#ifndef DEF_USB_GET_DESCR +#define DEF_USB_CLR_FEATURE 0x01 +#define DEF_USB_SET_FEATURE 0x03 +#define DEF_USB_GET_STATUS 0x00 +#define DEF_USB_SET_ADDRESS 0x05 +#define DEF_USB_GET_DESCR 0x06 +#define DEF_USB_SET_DESCR 0x07 +#define DEF_USB_GET_CONFIG 0x08 +#define DEF_USB_SET_CONFIG 0x09 +#define DEF_USB_GET_INTERF 0x0A +#define DEF_USB_SET_INTERF 0x0B +#define DEF_USB_SYNC_FRAME 0x0C +#endif + +// desscriptor types for CMD1H_GET_DESCR +#ifndef CH375_USB_DEVICE_DESCRIPTOR +#define CH375_USB_DEVICE_DESCRIPTOR 0x01 +#define CH375_USB_CONFIGURATION_DESCRIPTOR 0x02 +#define CH375_USB_INTERFACE_DESCRIPTOR 0x04 +#define CH375_USB_ENDPOINT_DESCRIPTOR 0x05 +#endif + +/* ************************************************ + * **************************************************** ***************** */ + +#ifdef _cplusplus +} +#endif + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.c b/Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.c new file mode 100644 index 00000000..7fdc71b5 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.c @@ -0,0 +1,9 @@ +#include "class_hub.h" +#include "protocol.h" +#include "usb_state.h" + +const setup_packet cmd_get_hub_descriptor = {RT_DEVICE_TO_HOST | RT_CLASS | RT_DEVICE, 6, {0, 0x29}, {0, 0}, 8}; + +usb_error hub_get_descriptor(const device_config_hub *const hub_config, hub_descriptor *const hub_description) __sdcccall(1) { + return usb_control_transfer(&cmd_get_hub_descriptor, hub_description, hub_config->address, hub_config->max_packet_size); +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.h b/Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.h new file mode 100644 index 00000000..73d05184 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/class_hub.h @@ -0,0 +1,62 @@ +#ifndef __CLASS_HUB +#define __CLASS_HUB + +#include "ch376.h" +#include "protocol.h" +#include + +/* +wHubCharacteristics: + D1...D0: Logical Power Switching Mode + 00: Ganged power switching (all ports power at once) + 01: Individual port power switching + 1X: Reserved. Used only on 1.0 compliant hubs that implement no power switching + + D2: Identifies a Compound Device + 0: Hub is not part of a compound device. + 1: Hub is part of a compound device. + + D4...D3: Logical Power Switching Mode + 00: Global Over-current Protection. The hub reports over-current as a summation + of all ports’ current draw, without a breakdown of individual port + over-current status. + 01: Individual Port Over-current Protection. The hub reports over-current on a + per-port basis. Each port has an over-current status. + 1X: No Over-current Protection. This option is allowed only for bus-powered +*/ + +typedef struct { + uint8_t bDescLength; + uint8_t bDescriptorType; /* HUB Descriptor Type 0x29 */ + uint8_t bNbrPorts; /* Number of ports */ + uint16_t wHubCharacteristics; /* Bitmap Hub Characteristics (see above) */ + uint8_t bPwrOn2PwrGood; /* Time (*2 ms) from port power on to power good */ + uint8_t bHubContrCurrent; /* Maximum current used by hub controller (mA).*/ + uint8_t DeviceRemovable[1]; /* bits indicating deviceRemovable and portPwrCtrlMask */ +} hub_descriptor; + +typedef struct { + uint16_t wPortStatus; + uint16_t wPortChange; +} hub_port_status; + +#define PORT_STAT_CONNECTION 0x0001 +#define PORT_STAT_ENABLE 0x0002 +#define PORT_STAT_SUSPEND 0x0004 +#define PORT_STAT_OVERCURRENT 0x0008 +#define PORT_STAT_RESET 0x0010 +#define PORT_STAT_POWER 0x0100 +#define PORT_STAT_LOW_SPEED 0x0200 +#define PORT_STAT_HIGH_SPEED 0x0400 +#define PORT_STAT_TEST 0x0800 +#define PORT_STAT_INDICATOR 0x1000 + +#define PORT_STAT_C_CONNECTION 0x0001 +#define PORT_STAT_C_ENABLE 0x0002 +#define PORT_STAT_C_SUSPEND 0x0004 +#define PORT_STAT_C_OVERCURRENT 0x0008 +#define PORT_STAT_C_RESET 0x0010 + +usb_error hub_get_descriptor(const device_config_hub *const hub_config, hub_descriptor *const hub_description) __sdcccall(1); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.c b/Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.c new file mode 100644 index 00000000..37ad03b2 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.c @@ -0,0 +1,8 @@ +#include "critical-section.h" +#include + +uint8_t in_critical_usb_section = 0; + +void critical_begin() { in_critical_usb_section++; } + +void critical_end() { in_critical_usb_section--; } diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.h b/Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.h new file mode 100644 index 00000000..2ddb3961 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/critical-section.h @@ -0,0 +1,13 @@ +#ifndef __CRITICAL_BLOCKS_H__ +#define __CRITICAL_BLOCKS_H__ + +#include + +extern uint8_t in_critical_usb_section; + +void critical_begin(); +void critical_end(); + +#define is_in_critical_section() (in_critical_usb_section != 0) + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/delay.h b/Source/HBIOS/ch376-native/source-doc/base-drv/delay.h new file mode 100644 index 00000000..05f9d1bf --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/delay.h @@ -0,0 +1,11 @@ +#ifndef __DELAY +#define __DELAY + +#include + +extern void delay(void); +extern void delay_20ms(void); +extern void delay_short(void); +extern void delay_medium(void); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.c b/Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.c new file mode 100644 index 00000000..4bfc0bbc --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.c @@ -0,0 +1,106 @@ +/** + * @file transfers.c + * @author Dean Netherton + * @brief A simplest implementation of common usb transfer functions, based on the CH376S chip + * @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml + * @version 1.0 + * @date 2023-09-22 + * + * @copyright Copyright (c) 2023 + * + */ + +#include "dev_transfers.h" +#include "ch376.h" +#include "critical-section.h" +#include "delay.h" +#include "ez80-helpers.h" +#include "protocol.h" +#include + +/** + * @brief Perform a USB control transfer (in or out) + * See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer + * + * @param device the usb device + * @param cmd_packet Pointer to the setup packet - top bit of bmRequestType indicate data direction + * @param buffer Pointer of data to send or receive into + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error usbdev_control_transfer(device_config *const device, const setup_packet *const cmd_packet, uint8_t *const buffer) { + return usb_control_transfer(cmd_packet, buffer, device->address, device->max_packet_size); +} + +usb_error usbdev_blk_out_trnsfer(device_config *const dev, const uint8_t *const buffer, const uint16_t buffer_size) { + usb_error result; + + endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_OUT]; + + result = usb_data_out_transfer(buffer, buffer_size, dev->address, endpoint); + + if (result == USB_ERR_STALL) { + usbtrn_clr_ep_halt(endpoint->number, dev->address, dev->max_packet_size); + endpoint->toggle = 0; + return USB_ERR_STALL; + } + + RETURN_CHECK(result); + +done: + return result; +} + +usb_error usbdev_bulk_in_transfer(device_config *const dev, uint8_t *const buffer, uint8_t *const buffer_size) { + usb_error result; + + endpoint_param *const endpoint = &dev->endpoints[ENDPOINT_BULK_IN]; + + result = usb_data_in_transfer_n(buffer, buffer_size, dev->address, endpoint); + + if (result == USB_ERR_STALL) { + usbtrn_clr_ep_halt(endpoint->number, dev->address, dev->max_packet_size); + endpoint->toggle = 0; + return USB_ERR_STALL; + } + + RETURN_CHECK(result); +done: + return result; +} + +usb_error usbdev_dat_in_trnsfer(device_config *const device, + uint8_t *const buffer, + const uint16_t buffer_size, + const usb_endpoint_type endpoint_type) { + usb_error result; + + endpoint_param *const endpoint = &device->endpoints[endpoint_type]; + + result = usb_data_in_transfer(buffer, buffer_size, device->address, endpoint); + + if (result == USB_ERR_STALL) { + usbtrn_clr_ep_halt(endpoint->number, device->address, device->max_packet_size); + endpoint->toggle = 0; + return USB_ERR_STALL; + } + + RETURN_CHECK(result); +done: + return result; +} + +usb_error usbdev_dat_in_trnsfer_0(device_config *const device, uint8_t *const buffer, const uint8_t buffer_size) { + usb_error result; + + endpoint_param *const endpoint = &device->endpoints[0]; + + result = usb_data_in_transfer(buffer, buffer_size, device->address, endpoint); + + if (result == USB_ERR_STALL) { + usbtrn_clr_ep_halt(endpoint->number, device->address, device->max_packet_size); + endpoint->toggle = 0; + return USB_ERR_STALL; + } + + return result; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.h b/Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.h new file mode 100644 index 00000000..54342438 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/dev_transfers.h @@ -0,0 +1,66 @@ +/** + * @file transfer.h + * @author Dean Netherton + * @brief A simplest implementation of common usb transfer functions, based on the CH376S chip + * @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml + * @version 1.0 + * @date 2023-09-22 + * + * @copyright Copyright (c) 2023 + * + */ + +#ifndef __USBDEV_TRANSFERS +#define __USBDEV_TRANSFERS + +#include "ch376.h" +#include "transfers.h" +#include + +typedef struct { + + uint8_t number : 3; + uint16_t max_packet_sizex : 10; +} endpoint; + +// 3 bytes +#define COMMON_DEVICE_CONFIG \ + usb_device_type type : 4; \ + uint8_t address : 4; \ + uint8_t max_packet_size; \ + uint8_t interface_number; + +typedef struct { + COMMON_DEVICE_CONFIG + endpoint_param endpoints[3]; // bulk in/out and interrupt +} device_config; + +typedef struct { + COMMON_DEVICE_CONFIG // bytes: 0-2 + endpoint_param endpoints[3]; // bytes: 3-5, 6-8, 9-11 bulk in/out and interrupt + uint32_t current_lba; // bytes 12-15 +} device_config_storage; + +typedef struct { + COMMON_DEVICE_CONFIG +} device_config_hub; + +typedef struct { + COMMON_DEVICE_CONFIG + endpoint_param endpoints[1]; // Isochronous +} device_config_keyboard; + +extern usb_error usbdev_control_transfer(device_config *const device, const setup_packet *const cmd, uint8_t *const buffer); + +extern usb_error usbdev_blk_out_trnsfer(device_config *const device, const uint8_t *const buffer, const uint16_t buffer_size); + +extern usb_error usbdev_bulk_in_transfer(device_config *const dev, uint8_t *const buffer, uint8_t *const buffer_size); + +extern usb_error usbdev_dat_in_trnsfer(device_config *const device, + uint8_t *const buffer, + const uint16_t buffer_size, + const usb_endpoint_type endpoint_type); + +extern usb_error usbdev_dat_in_trnsfer_0(device_config *const device, uint8_t *const buffer, const uint8_t buffer_size); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.c b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.c new file mode 100644 index 00000000..a9e6dc5e --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.c @@ -0,0 +1,262 @@ +#include "enumerate.h" +#include "enumerate_hub.h" +#include "enumerate_storage.h" +#include "protocol.h" +#include "work-area.h" +#include + +#include "print.h" + +usb_error op_id_class_drv(_working *const working) __sdcccall(1); +usb_error op_parse_endpoint(_working *const working) __sdcccall(1); + +static usb_error adv_to_next_desc(_working *const working, const uint8_t descriptor_type) __sdcccall(1) { + usb_descriptor_t *d; + const uint8_t *buffer_end = working->config.buffer + MAX_CONFIG_SIZE; + + if (working->ptr >= buffer_end) + return USB_ERR_BUFF_TO_LARGE; + + d = (usb_descriptor_t *)working->ptr; + + do { + working->ptr += d->bLength; + + if (working->ptr >= buffer_end) + return USB_ERR_BUFF_TO_LARGE; + + d = (usb_descriptor_t *)working->ptr; + } while (d->bDescriptorType != descriptor_type); + + if (working->ptr + d->bLength >= buffer_end) + return USB_ERR_BUFF_TO_LARGE; + + return USB_ERR_OK; +} + +void parse_endpoint_keyboard(device_config_keyboard *const keyboard_config, const endpoint_descriptor const *pEndpoint) + __sdcccall(1) { + endpoint_param *const ep = &keyboard_config->endpoints[0]; + ep->number = pEndpoint->bEndpointAddress; + ep->toggle = 0; + ep->max_packet_sizex = calc_max_packet_sizex(pEndpoint->wMaxPacketSize); +} + +usb_device_type identify_class_driver(_working *const working) { + const interface_descriptor *const p = (const interface_descriptor *)working->ptr; + if (p->bInterfaceClass == 2) + return USB_IS_CDC; + + if (p->bInterfaceClass == 8 && (p->bInterfaceSubClass == 6 || p->bInterfaceSubClass == 5) && p->bInterfaceProtocol == 80) + return USB_IS_MASS_STORAGE; + + if (p->bInterfaceClass == 8 && p->bInterfaceSubClass == 4 && p->bInterfaceProtocol == 0) + return USB_IS_FLOPPY; + + if (p->bInterfaceClass == 9 && p->bInterfaceSubClass == 0 && p->bInterfaceProtocol == 0) + return USB_IS_HUB; + + if (p->bInterfaceClass == 3) + return USB_IS_KEYBOARD; + + return USB_IS_UNKNOWN; +} + +usb_error op_interface_next(_working *const working) __z88dk_fastcall { + uint8_t result; + + if (--working->interface_count == 0) + return USB_ERR_OK; + + CHECK(adv_to_next_desc(working, USB_DESCR_INTERFACE)); + return op_id_class_drv(working); + +done: + return result; +} + +usb_error op_endpoint_next(_working *const working) __sdcccall(1) { + usb_error result; + + if (working->endpoint_count != 0 && --working->endpoint_count > 0) { + CHECK(adv_to_next_desc(working, USB_DESCR_ENDPOINT)); + return op_parse_endpoint(working); + } + + return op_interface_next(working); + +done: + return result; +} + +usb_error op_parse_endpoint(_working *const working) __sdcccall(1) { + const endpoint_descriptor *endpoint = (endpoint_descriptor *)working->ptr; + device_config *const device = working->p_current_device; + + switch (working->usb_device) { + case USB_IS_FLOPPY: + case USB_IS_MASS_STORAGE: { + parse_endpoints((device_config_storage *)device, endpoint); + break; + } + + case USB_IS_KEYBOARD: { + parse_endpoint_keyboard((device_config_keyboard *)device, endpoint); + break; + } + } + + return op_endpoint_next(working); +} + +usb_error +configure_device(const _working *const working, const interface_descriptor *const interface, device_config *const dev_cfg) { + dev_cfg->interface_number = interface->bInterfaceNumber; + dev_cfg->max_packet_size = working->desc.bMaxPacketSize0; + dev_cfg->address = working->current_device_address; + dev_cfg->type = working->usb_device; + + return usbtrn_set_config(dev_cfg->address, dev_cfg->max_packet_size, working->config.desc.bConfigurationvalue); +} + +usb_error op_cap_hub_drv_intf(_working *const working) __sdcccall(1) { + const interface_descriptor *const interface = (interface_descriptor *)working->ptr; + + usb_error result; + device_config_hub hub_config; + working->hub_config = &hub_config; + + hub_config.type = USB_IS_HUB; + CHECK(configure_device(working, interface, (device_config *const)&hub_config)); + RETURN_CHECK(configure_usb_hub(working)); +done: + return result; +} + +usb_error op_cap_drv_intf(_working *const working) __z88dk_fastcall { + usb_error result; + _usb_state *const work_area = get_usb_work_area(); + const interface_descriptor *const interface = (interface_descriptor *)working->ptr; + + working->endpoint_count = interface->bNumEndpoints; + if (working->endpoint_count > 0) + CHECK(adv_to_next_desc(working, USB_DESCR_ENDPOINT)); + working->p_current_device = NULL; + + switch (working->usb_device) { + case USB_IS_HUB: { + CHECK(op_cap_hub_drv_intf(working)) + break; + } + + case USB_IS_UNKNOWN: { + device_config unkown_dev_cfg; + memset(&unkown_dev_cfg, 0, sizeof(device_config)); + working->p_current_device = &unkown_dev_cfg; + CHECK(configure_device(working, interface, &unkown_dev_cfg)); + break; + } + + default: { + device_config *dev_cfg = find_first_free(); + if (dev_cfg == NULL) + return USB_ERR_OUT_OF_MEMORY; + working->p_current_device = dev_cfg; + CHECK(configure_device(working, interface, dev_cfg)); + break; + } + } + + return op_parse_endpoint(working); + +done: + return result; +} + +usb_error op_id_class_drv(_working *const working) __sdcccall(1) { + const interface_descriptor *const ptr = (const interface_descriptor *)working->ptr; + + if (ptr->bDescriptorType != USB_DESCR_INTERFACE) + return USB_ERR_FAIL; + + working->usb_device = identify_class_driver(working); + + return op_cap_drv_intf(working); +} + +usb_error op_get_cfg_desc(_working *const working) __sdcccall(1) { + usb_error result; + + const uint8_t max_packet_size = working->desc.bMaxPacketSize0; + + memset(working->config.buffer, 0, MAX_CONFIG_SIZE); + working->ptr = working->config.buffer; + + CHECK(usbtrn_gfull_cfg_desc(working->config_index, working->current_device_address, max_packet_size, MAX_CONFIG_SIZE, + working->config.buffer)); + + CHECK(adv_to_next_desc(working, USB_DESCR_INTERFACE)); + working->interface_count = working->config.desc.bNumInterfaces; + + return op_id_class_drv(working); + +done: + return result; +} + +usb_error read_all_configs(enumeration_state *const state) { + uint8_t result; + _usb_state *const work_area = get_usb_work_area(); + + _working working; + memset(&working, 0, sizeof(_working)); + working.state = state; + + CHECK(usbtrn_get_descriptor(&working.desc)); + + state->next_device_address++; + working.current_device_address = state->next_device_address; + CHECK(usbtrn_set_address(working.current_device_address)); + + for (uint8_t config_index = 0; config_index < working.desc.bNumConfigurations; config_index++) { + working.config_index = config_index; + + CHECK(op_get_cfg_desc(&working)); + } + + return USB_ERR_OK; +done: + return result; +} + +usb_error enumerate_all_devices(void) { + _usb_state *const work_area = get_usb_work_area(); + enumeration_state state; + memset(&state, 0, sizeof(enumeration_state)); + + usb_error result = read_all_configs(&state); + + work_area->count_of_detected_usb_devices = state.next_device_address; + +done: + return result; +} + +/* + enumerate_all_devices + -> read_all_configs + -> parse_config + -> op_get_cfg_desc + -> op_id_class_drv + -> op_cap_drv_intf (increment index) + -> op_parse_endpoint + -> parse_endpoints + -> parse_endpoint_hub + -> op_endpoint_next + -> op_parse_endpoint -^ (install driver endpoint) + -> op_interface_next + -> return + -> op_id_class_drv -^ + + +*/ diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.h b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.h new file mode 100644 index 00000000..f057a5ce --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate.h @@ -0,0 +1,39 @@ +#ifndef __USB_ENUMERATE +#define __USB_ENUMERATE + +#include "ch376.h" +#include "protocol.h" +#include "usb_state.h" + +#define MAX_CONFIG_SIZE 140 + +typedef struct { + uint8_t next_device_address; /* Track the count of installed usb devices*/ + uint8_t storage_count; /* Track the count of storage devices (scsi, ufi) */ +} enumeration_state; + +typedef struct __working { + enumeration_state *state; + + usb_device_type usb_device; + device_descriptor desc; + uint8_t config_index; + uint8_t interface_count; + uint8_t endpoint_count; + uint8_t current_device_address; + device_config_hub *hub_config; + + uint8_t *ptr; + device_config *p_current_device; + + union { + uint8_t buffer[MAX_CONFIG_SIZE]; + config_descriptor desc; + } config; + +} _working; + +extern usb_error read_all_configs(enumeration_state *const state); +extern usb_error enumerate_all_devices(void); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.c b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.c new file mode 100644 index 00000000..1db8ddb2 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.c @@ -0,0 +1,82 @@ +#include "enumerate_hub.h" +#include "class_hub.h" +#include "delay.h" +#include "protocol.h" +#include "work-area.h" +#include + +const setup_packet cmd_set_feature = {RT_HOST_TO_DEVICE | RT_CLASS | RT_OTHER, SET_FEATURE, {FEAT_PORT_POWER, 0}, {1, 0}, 0}; +const setup_packet cmd_clear_feature = {RT_HOST_TO_DEVICE | RT_CLASS | RT_OTHER, CLEAR_FEATURE, {FEAT_PORT_POWER, 0}, {1, 0}, 0}; +const setup_packet cmd_get_status_port = { + RT_DEVICE_TO_HOST | RT_CLASS | RT_OTHER, GET_STATUS, {0, 0}, {1, 0}, sizeof(hub_port_status)}; + +usb_error hub_set_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) { + setup_packet set_feature; + set_feature = cmd_set_feature; + + set_feature.bValue[0] = feature; + set_feature.bIndex[0] = index; + return usb_control_transfer(&set_feature, 0, hub_config->address, hub_config->max_packet_size); +} + +usb_error hub_clear_feature(const device_config_hub *const hub_config, const uint8_t feature, const uint8_t index) { + setup_packet clear_feature; + clear_feature = cmd_clear_feature; + + clear_feature.bValue[0] = feature; + clear_feature.bIndex[0] = index; + return usb_control_transfer(&clear_feature, 0, hub_config->address, hub_config->max_packet_size); +} + +usb_error hub_get_status_port(const device_config_hub *const hub_config, const uint8_t index, hub_port_status *const port_status) { + setup_packet get_status_port; + get_status_port = cmd_get_status_port; + + get_status_port.bIndex[0] = index; + return usb_control_transfer(&get_status_port, port_status, hub_config->address, hub_config->max_packet_size); +} + +usb_error configure_usb_hub(_working *const working) __z88dk_fastcall { + _usb_state *const work_area = get_usb_work_area(); + + usb_error result; + hub_descriptor hub_description; + hub_port_status port_status; + const device_config_hub *const hub_config = working->hub_config; + + CHECK(hub_get_descriptor(hub_config, &hub_description)); + + uint8_t i = hub_description.bNbrPorts; + do { + CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i)); + + CHECK(hub_set_feature(hub_config, FEAT_PORT_POWER, i)); + + hub_clear_feature(hub_config, FEAT_PORT_RESET, i); + + CHECK(hub_set_feature(hub_config, FEAT_PORT_RESET, i)); + + CHECK(hub_get_status_port(hub_config, i, &port_status)); + + if (port_status.wPortStatus & PORT_STAT_CONNECTION) { + CHECK(hub_clear_feature(hub_config, HUB_FEATURE_PORT_CONNECTION_CHANGE, i)); + + CHECK(hub_clear_feature(hub_config, FEAT_PORT_ENABLE_CHANGE, i)); + + CHECK(hub_clear_feature(hub_config, FEAT_PORT_RESET_CHANGE, i)); + delay_short(); + + CHECK(hub_get_status_port(hub_config, i, &port_status)); + delay_short(); + + CHECK(read_all_configs(working->state)); + + } else { + CHECK(hub_clear_feature(hub_config, FEAT_PORT_POWER, i)); + } + } while (--i != 0); + + return USB_ERR_OK; +done: + return result; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.h b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.h new file mode 100644 index 00000000..32be6558 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_hub.h @@ -0,0 +1,10 @@ +#ifndef __USB_ENUMERATE_HUB +#define __USB_ENUMERATE_HUB + +#include "enumerate.h" +#include "protocol.h" +#include "usb_state.h" + +extern usb_error configure_usb_hub(_working *const working) __z88dk_fastcall; + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.c b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.c new file mode 100644 index 00000000..b2ab79ef --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.c @@ -0,0 +1,27 @@ +#include "enumerate_storage.h" +#include "protocol.h" +#include + +void parse_endpoints(device_config_storage *const storage_dev, const endpoint_descriptor const *pEndpoint) { + + if (!(pEndpoint->bmAttributes & 0x02)) + return; + + const uint8_t x = calc_max_packet_sizex(pEndpoint->wMaxPacketSize); + endpoint_param *const eps = storage_dev->endpoints; + endpoint_param *ep; + + if (pEndpoint->bmAttributes & 0x01) { // 3 -> Interrupt + if (!(pEndpoint->bEndpointAddress & 0x80)) + return; + + ep = &eps[ENDPOINT_INTERRUPT_IN]; + + } else { + ep = (pEndpoint->bEndpointAddress & 0x80) ? &eps[ENDPOINT_BULK_IN] : &eps[ENDPOINT_BULK_OUT]; + } + + ep->number = pEndpoint->bEndpointAddress & 0x07; + ep->toggle = 0; + ep->max_packet_sizex = x; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.h b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.h new file mode 100644 index 00000000..17f81a8a --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/enumerate_storage.h @@ -0,0 +1,9 @@ +#ifndef __USB_ENUMERATE_STORAGE +#define __USB_ENUMERATE_STORAGE + +#include "dev_transfers.h" +#include "protocol.h" + +extern void parse_endpoints(device_config_storage *const storage_dev, const endpoint_descriptor const *pEndpoint); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/ez80-helpers.h b/Source/HBIOS/ch376-native/source-doc/base-drv/ez80-helpers.h new file mode 100644 index 00000000..02240c95 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/ez80-helpers.h @@ -0,0 +1 @@ +#define debugger() __asm__("PUSH AF \n PUSH BC \n XOR A \n LD B, 7 \n .DB 0x49, 0xD7 \n POP BC \n POP AF") diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.c b/Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.c new file mode 100644 index 00000000..51295550 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.c @@ -0,0 +1,11 @@ +#include "hbios-driver-storage.h" + +hbios_storage_device_t hbios_usbstore_devs[MAX_NUMBER_OF_DEVICES] = {{NULL}}; + +uint8_t find_storage_dev(void) { + for (uint8_t i = 0; i < MAX_NUMBER_OF_DEVICES; i++) + if (hbios_usbstore_devs[i].drive_index == 0) + return i; + + return -1; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.h b/Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.h new file mode 100644 index 00000000..253a681e --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/hbios-driver-storage.h @@ -0,0 +1,15 @@ +#ifndef __HBIOS_DRIVER_STORAGE +#define __HBIOS_DRIVER_STORAGE + +#include "usb_state.h" + +typedef struct _hbios_storage_device { + uint8_t drive_index; + uint8_t usb_device; +} hbios_storage_device_t; + +extern hbios_storage_device_t hbios_usbstore_devs[MAX_NUMBER_OF_DEVICES]; + +uint8_t find_storage_dev(void); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/hbios.h b/Source/HBIOS/ch376-native/source-doc/base-drv/hbios.h new file mode 100644 index 00000000..3c4c83e8 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/hbios.h @@ -0,0 +1,6 @@ +#ifndef _HBIOS_H_ +#define _HBIOS_H_ + +extern void dio_add_entry(const uint16_t fnc_table[], const void *const storage_device) __sdcccall(1); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/print.h b/Source/HBIOS/ch376-native/source-doc/base-drv/print.h new file mode 100644 index 00000000..df7491b3 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/print.h @@ -0,0 +1,11 @@ +#ifndef __XPRINT +#define __XPRINT + +#include +#include + +extern void print_hex(const char c) __z88dk_fastcall; +extern void print_string(const char *p) __z88dk_fastcall; +extern void print_uint16(const uint16_t n) __z88dk_fastcall; + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/protocol.c b/Source/HBIOS/ch376-native/source-doc/base-drv/protocol.c new file mode 100644 index 00000000..289e7f6f --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/protocol.c @@ -0,0 +1,159 @@ +/** + * @file protocol.c + * @author Dean Netherton + * @brief A simplest implementation of common usb transfer functions, based on the CH376S chip + * @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml + * @version 1.0 + * @date 2023-09-22 + * + * @copyright Copyright (c) 2023 + * + */ + +#include "protocol.h" +#include "ch376.h" +#include "delay.h" +#include + +#include "ez80-helpers.h" +#include "print.h" + +const setup_packet cmd_get_dev_descriptr = {0x80, 6, {0, 1}, {0, 0}, 8}; + +/** + * @brief Issue GET_DESCRIPTOR request to retrieve the device descriptor for usb device at address 0 + * + * @param buffer the buffer to store the device descriptor in + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error usbtrn_get_descriptor(device_descriptor *const buffer) { + usb_error result; + setup_packet cmd; + cmd = cmd_get_dev_descriptr; + cmd.wLength = 8; + + result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, 8); + + CHECK(result); + + cmd = cmd_get_dev_descriptr; + cmd.wLength = 18; + result = usb_control_transfer(&cmd, (uint8_t *)buffer, 0, buffer->bMaxPacketSize0); + + RETURN_CHECK(result); + +done: + return result; +} + +/** + * @brief Issue GET_DESCRIPTOR request to retrieve the device descriptor for usb device at the specified address + * + * @param buffer the buffer to store the device descriptor in + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error usbtrn_get_descriptor2(device_descriptor *const buffer, const uint8_t device_address) { + usb_error result; + + setup_packet cmd; + cmd = cmd_get_dev_descriptr; + cmd.wLength = 8; + + result = usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, 8); + + CHECK(result); + + cmd = cmd_get_dev_descriptr; + cmd.wLength = 18; + RETURN_CHECK(usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, buffer->bMaxPacketSize0)); +done: + return result; +} + +const setup_packet cmd_set_device_address = {0x00, 5, {0, 0}, {0, 0}, 0}; + +/** + * @brief configure device at address 0 to be assigned a new device address + * + * @param device_address the new device address + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error usbtrn_set_address(const uint8_t device_address) __z88dk_fastcall { + setup_packet cmd; + cmd = cmd_set_device_address; + cmd.bValue[0] = device_address; + + return usb_control_transfer(&cmd, 0, 0, 0); +} + +const setup_packet cmd_set_configuration = {0x00, 9, {0, 0}, {0, 0}, 0}; + +/** + * @brief configure device at address 0 to be assigned a new configuration + * + * @param config the device to be configured + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error usbtrn_set_config(const uint8_t device_address, const uint8_t max_packet_size, const uint8_t configuration) { + setup_packet cmd; + cmd = cmd_set_configuration; + cmd.bValue[0] = configuration; + + return usb_control_transfer(&cmd, 0, device_address, max_packet_size); +} + +const setup_packet cmd_get_config_desc = {0x80, 6, {0, 2}, {0, 0}, 0}; + +/** + * @brief request the config descriptor for the specific config index of the specified device + * + * @param buffer the buffer to store the config descriptor in + * @param config_index the index of the config descriptor to retrieve + * @param buffer_size the size of the buffer + * @param device_address the usb address of the device + * @param max_packet_size the max packet size for control transfers (endpoint 0) + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error usbtrn_get_config_desc(config_descriptor *const buffer, + const uint8_t config_index, + const uint8_t buffer_size, + const uint8_t device_address, + const uint8_t max_packet_size) { + setup_packet cmd; + cmd = cmd_get_config_desc; + cmd.bValue[0] = config_index; + cmd.wLength = (uint16_t)buffer_size; + + return usb_control_transfer(&cmd, (uint8_t *)buffer, device_address, max_packet_size); +} + +usb_error usbtrn_gfull_cfg_desc(const uint8_t config_index, + const uint8_t device_address, + const uint8_t max_packet_size, + const uint8_t max_buffer_size, + uint8_t *const buffer) { + usb_error result; + + CHECK(usbtrn_get_config_desc((config_descriptor *)buffer, config_index, sizeof(config_descriptor), device_address, + max_packet_size)); + + uint8_t max_length = ((config_descriptor *)buffer)->wTotalLength; + if (max_length > max_buffer_size) + max_length = max_buffer_size; + + CHECK(usbtrn_get_config_desc((config_descriptor *)buffer, config_index, max_length, device_address, max_packet_size)); + + return USB_ERR_OK; +done: + return result; +} + +const setup_packet usb_cmd_clr_ep_halt = {2, 1, {0, 0}, {255, 0}, 0}; // ;byte 4 is the endpoint to be cleared + +usb_error usbtrn_clr_ep_halt(const uint8_t endpoint_number, const uint8_t device_address, const uint8_t max_packet_size) { + setup_packet cmd; + cmd = usb_cmd_clr_ep_halt; + cmd.bIndex[0] = endpoint_number; + + return usb_control_transfer(&cmd, (uint8_t *)0, device_address, max_packet_size); +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/protocol.h b/Source/HBIOS/ch376-native/source-doc/base-drv/protocol.h new file mode 100644 index 00000000..bacddb1a --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/protocol.h @@ -0,0 +1,95 @@ +#ifndef __HW +#define __HW + +#include "ch376.h" +#include "dev_transfers.h" +#include "transfers.h" +#include + +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; +} usb_descriptor_t; + +#define USB_DESCR_DEVICE 1 +#define USB_DESCR_CONFIGURATION 2 +#define USB_DESCR_STRING 3 +#define USB_DESCR_INTERFACE 4 +#define USB_DESCR_ENDPOINT 5 +#define USB_DESCR_DEV_QUALIFIER 6 +#define USB_DESCR_OTHER_SPEED 7 +#define USB_DESCR_HID 33 +#define USB_DESCR_HID_REPORT 34 +#define USB_DESCR_HID_PHYSICAL_DESC 35 + +typedef struct _device_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} device_descriptor; + +typedef struct _config_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationvalue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; +} config_descriptor; + +typedef struct _interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} interface_descriptor, *p_interface_descriptor; + +typedef struct _endpoint_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +} endpoint_descriptor; + +extern usb_error usbtrn_get_descriptor(device_descriptor *const buffer); +extern usb_error usbtrn_get_descriptor2(device_descriptor *const buffer, const uint8_t device_address); + +extern usb_error usbtrn_get_config_desc(config_descriptor *const buffer, + const uint8_t config_index, + const uint8_t buffer_size, + const uint8_t device_address, + const uint8_t max_packet_size); + +extern usb_error usbtrn_gfull_cfg_desc(const uint8_t config_index, + const uint8_t device_address, + const uint8_t max_packet_size, + const uint8_t max_buffer_size, + uint8_t *const buffer); + +extern usb_error usbtrn_set_config(const uint8_t device_address, const uint8_t max_packet_size, const uint8_t configuration); + +extern usb_error usbtrn_set_address(const uint8_t device_address) __z88dk_fastcall; + +extern usb_error usbtrn_clr_ep_halt(const uint8_t endpoint_number, const uint8_t device_address, const uint8_t max_packet_size); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/transfers.c b/Source/HBIOS/ch376-native/source-doc/base-drv/transfers.c new file mode 100644 index 00000000..38955680 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/transfers.c @@ -0,0 +1,152 @@ +/** + * @file transfers.c + * @author Dean Netherton + * @brief A simplest implementation of common usb transfer functions, based on the CH376S chip + * @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml + * @version 1.0 + * @date 2023-09-22 + * + * @copyright Copyright (c) 2023 + * + */ + +#include "transfers.h" +#include "ch376.h" +#include "critical-section.h" +#include "delay.h" +#include "ez80-helpers.h" +#include "print.h" +#include + +/** + * @brief Perform a USB control transfer (in or out) + * See https://www.beyondlogic.org/usbnutshell/usb4.shtml for a description of the USB control transfer + * + * @param cmd_packet Pointer to the setup packet - top bit of bmRequestType indicate data direction + * @param buffer Pointer of data to send or receive into + * @param device_address usb device address + * @param max_packet_size Maximum packet size for endpoint + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error usb_control_transfer(const setup_packet *const cmd_packet, + void *const buffer, + const uint8_t device_address, + const uint8_t max_packet_size) { + usb_error result; + endpoint_param endpoint = {1, 0, max_packet_size}; + + const uint8_t transferIn = (cmd_packet->bmRequestType & 0x80); + + if (transferIn && buffer == 0) + return USB_ERR_OTHER; + + critical_begin(); + + ch_set_usb_address(device_address); + + ch_write_data((const uint8_t *)cmd_packet, sizeof(setup_packet)); + ch_issue_token_setup(); + result = ch_short_get_status(); + CHECK(result); + + const uint16_t length = cmd_packet->wLength; + + result = length != 0 + ? (transferIn ? ch_data_in_transfer(buffer, length, &endpoint) : ch_data_out_transfer(buffer, length, &endpoint)) + : USB_ERR_OK; + + CHECK(result) + + if (transferIn) { + ch_command(CH_CMD_WR_HOST_DATA); + CH376_DATA_PORT = 0; + ch_issue_token_out_ep0(); + result = ch_long_get_status(); /* sometimes we get STALL here - seems to be ok to ignore */ + + if (result == USB_ERR_OK || result == USB_ERR_STALL) { + result = USB_ERR_OK; + goto done; + } + + RETURN_CHECK(result); + } + + ch_issue_token_in_ep0(); + result = ch_long_get_status(); + + RETURN_CHECK(result); + +done: + critical_end(); + return result; +} + +/** + * @brief Perform a USB data in on the specified endpoint + * + * @param buffer the buffer to receive the data + * @param buffer_size the maximum size of data to be received + * @param device_address the usb address of the device + * @param endpoint the usb endpoint to receive from (toggle of endpoint is updated) + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error +usb_data_in_transfer(uint8_t *buffer, const uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint) { + usb_error result; + critical_begin(); + + ch_set_usb_address(device_address); + + result = ch_data_in_transfer(buffer, buffer_size, endpoint); + + critical_end(); + + return result; +} + +/** + * @brief Perform a USB data in on the specified endpoint + * + * @param buffer the buffer to receive the data - must be 62 bytes + * @param buffer_size on exit the actual size of data received + * @param device_address the usb address of the device + * @param endpoint the usb endpoint to receive from (toggle of endpoint is updated) + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error +usb_data_in_transfer_n(uint8_t *buffer, uint8_t *const buffer_size, const uint8_t device_address, endpoint_param *const endpoint) { + usb_error result; + + critical_begin(); + + ch_set_usb_address(device_address); + + result = ch_data_in_transfer_n(buffer, buffer_size, endpoint); // does ch_data_in_transfer_n size need to be signed? + + critical_end(); + + return result; +} + +/** + * @brief Perform a USB data out on the specififed endpoint + * + * @param buffer the buffer to send the data from + * @param buffer_size the maximum size of data to be sent + * @param device_address the usb address of the device + * @param endpoint the usb endpoint to send to (toggle of endpoint is updated) + * @return usb_error USB_ERR_OK if all good, otherwise specific error code + */ +usb_error +usb_data_out_transfer(const uint8_t *buffer, uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint) { + usb_error result; + critical_begin(); + + ch_set_usb_address(device_address); + + result = ch_data_out_transfer(buffer, buffer_size, endpoint); + + critical_end(); + + return result; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/transfers.h b/Source/HBIOS/ch376-native/source-doc/base-drv/transfers.h new file mode 100644 index 00000000..b3d9d3ca --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/transfers.h @@ -0,0 +1,103 @@ +/** + * @file transfer.h + * @author Dean Netherton + * @brief A simplest implementation of common usb transfer functions, based on the CH376S chip + * @details For a basic walkthrough of the usb protocol see https://www.beyondlogic.org/usbnutshell/usb1.shtml + * @version 1.0 + * @date 2023-09-22 + * + * @copyright Copyright (c) 2023 + * + */ + +#ifndef __USB_TRANSFERS +#define __USB_TRANSFERS + +#include "ch376.h" +#include + +#define GET_STATUS 0 +#define CLEAR_FEATURE 1 +#define SET_FEATURE 3 +#define GET_DESCRIPTOR 6 +#define SET_DESCRIPTOR 7 +#define CLEAR_TT_BUFFER 8 +#define RESET_TT 9 +#define GET_TT_STATE 10 +#define CSTOP_TT 11 + +#define FEAT_PORT_POWER 8 +#define FEAT_PORT_RESET 4 +#define HUB_FEATURE_PORT_CONNECTION_CHANGE 16 +#define FEAT_PORT_ENABLE_CHANGE 17 +#define FEAT_PORT_RESET_CHANGE 20 + +// HUB_FEATURE_PORT_CONNECTION = 0, +// HUB_FEATURE_PORT_ENABLE = 1, +// HUB_FEATURE_PORT_SUSPEND = 2, +// HUB_FEATURE_PORT_OVER_CURRENT = 3, +// HUB_FEATURE_PORT_RESET = 4, + +// HUB_FEATURE_PORT_POWER = 8, +// HUB_FEATURE_PORT_LOW_SPEED = 9, + +// HUB_FEATURE_PORT_CONNECTION_CHANGE = 16, +// HUB_FEATURE_PORT_ENABLE_CHANGE = 17, +// HUB_FEATURE_PORT_SUSPEND_CHANGE = 18, +// HUB_FEATURE_PORT_OVER_CURRENT_CHANGE = 19, +// HUB_FEATURE_PORT_RESET_CHANGE = 20, +// HUB_FEATURE_PORT_TEST = 21, +// HUB_FEATURE_PORT_INDICATOR = 22 + +#define RT_HOST_TO_DEVICE 0b00000000 +#define RT_DEVICE_TO_HOST 0b10000000 +#define RT_STANDARD 0b00000000 +#define RT_CLASS 0b00100000 +#define RT_VENDOR 0b01000000 +#define RT_DEVICE 0b00000000 +#define RT_INTERFACE 0b00000001 +#define RT_ENDPOINT 0b00000010 +#define RT_OTHER 0b00000011 + +typedef struct _setup_packet { + uint8_t bmRequestType; + uint8_t bRequest; + uint8_t bValue[2]; + uint8_t bIndex[2]; + uint16_t wLength; +} setup_packet; + +enum libusb_request_type { + LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), + LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), + LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), + LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5), +}; + +enum libusb_request_recipient { + LIBUSB_RECIPIENT_DEVICE = 0x00, + LIBUSB_RECIPIENT_INTERFACE = 0x01, + LIBUSB_RECIPIENT_ENDPOINT = 0x02, + LIBUSB_RECIPIENT_OTHER = 0x03, +}; + +enum libusb_endpoint_direction { + LIBUSB_ENDPOINT_IN = 0x80, + LIBUSB_ENDPOINT_OUT = 0x00, +}; + +extern usb_error usb_control_transfer(const setup_packet *const cmd_packet, + void *const buffer, + const uint8_t device_address, + const uint8_t max_packet_size); + +extern usb_error +usb_data_in_transfer(uint8_t *buffer, const uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint); + +extern usb_error +usb_data_in_transfer_n(uint8_t *buffer, uint8_t *const buffer_size, const uint8_t device_address, endpoint_param *const endpoint); + +extern usb_error +usb_data_out_transfer(const uint8_t *buffer, uint16_t buffer_size, const uint8_t device_address, endpoint_param *const endpoint); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.c b/Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.c new file mode 100644 index 00000000..0dc59cc7 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.c @@ -0,0 +1,76 @@ +#include "usb-base-drv.h" +#include "ch376.h" +#include "enumerate.h" +#include "work-area.h" +#include + +static usb_error usb_host_bus_reset(void) { + ch_cmd_set_usb_mode(CH_MODE_HOST); + delay_20ms(); + + ch_cmd_set_usb_mode(CH_MODE_HOST_RESET); + delay_20ms(); + + ch_cmd_set_usb_mode(CH_MODE_HOST); + delay_20ms(); + + ch_configure_nak_retry_3s(); + + return USB_ERR_OK; +} + +#define ERASE_LINE "\x1B\x6C\r$" + +uint16_t usb_init(uint8_t state) __z88dk_fastcall { + uint8_t r; + + USB_MODULE_LEDS = 0x03; + + if (state == 0) { + ch_cmd_reset_all(); + delay_medium(); + + if (!ch_probe()) { + USB_MODULE_LEDS = 0x00; + return 0xFF00; + } + USB_MODULE_LEDS = 0x00; + return 1; + } + + if (state == 1) { + r = ch_cmd_get_ic_version(); + + USB_MODULE_LEDS = 0x00; + return (uint16_t)r << 8 | 2; + } + + if (state == 2) { + usb_host_bus_reset(); + + r = ch_very_short_status(); + + if (r != USB_INT_CONNECT) { + USB_MODULE_LEDS = 0x00; + return 2; + } + + return 3; + } + + memset(get_usb_work_area(), 0, sizeof(_usb_state)); + if (state != 2) { + usb_host_bus_reset(); + delay_medium(); + } + enumerate_all_devices(); + USB_MODULE_LEDS = 0x00; + return (uint16_t)count_of_devices() << 8 | 4; +} + +usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba) { + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + dev->current_lba = lba; + return USB_ERR_OK; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.h b/Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.h new file mode 100644 index 00000000..a2ab3b1a --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/usb-base-drv.h @@ -0,0 +1,14 @@ +#ifndef __USB_BASE_DRV +#define __USB_BASE_DRV + +#include "dev_transfers.h" +#include "usb_state.h" +#include + +extern uint16_t usb_init(uint8_t state) __z88dk_fastcall; + +// ufi_seek is an alias for scsi_seek +extern usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba); +extern usb_error ufi_seek(const uint16_t dev_index, const uint32_t lba); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.c b/Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.c new file mode 100644 index 00000000..28c2f9b0 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.c @@ -0,0 +1,97 @@ +#include "usb_state.h" +#include "ch376.h" +#include "work-area.h" + +extern device_config *first_device_config(const _usb_state *const p) __sdcccall(1); +extern device_config *next_device_config(const _usb_state *const usb_state, const device_config *const p) __sdcccall(1); + +const uint8_t device_config_sizes[_USB_LAST_DEVICE_TYPE] = { + 0, /* USB_NOT_SUPPORTED = 0 */ + sizeof(device_config_storage), /* USB_IS_FLOPPY = 1 */ + sizeof(device_config_storage), /* USB_IS_MASS_STORAGE = 2 */ + sizeof(device_config), /* USB_IS_CDC = 3 */ + sizeof(device_config_keyboard), /* USB_IS_KEYBOARD = 4 */ +}; + +// always usb work area +uint8_t count_of_devices(void) __sdcccall(1) { + _usb_state *const p = get_usb_work_area(); + + uint8_t count = 0; + + const device_config *p_config = first_device_config(p); + while (p_config) { + const uint8_t type = p_config->type; + + if (type != USB_IS_HUB && type) + count++; + ; + + p_config = next_device_config(p, p_config); + }; + + return count; +} + +// always search in boot +device_config *find_first_free(void) { + _usb_state *const boot_state = get_usb_work_area(); + + uint8_t c = 0; + device_config *p = first_device_config(boot_state); + while (p) { + if (p->type == 0) + return p; + + p = next_device_config(boot_state, p); + } + + return NULL; +} + +device_config *first_device_config(const _usb_state *const p) __sdcccall(1) { return (device_config *)&p->device_configs[0]; } + +device_config *next_device_config(const _usb_state *const usb_state, const device_config *const p) __sdcccall(1) { + if (p->type == 0) + return NULL; + + const uint8_t size = device_config_sizes[p->type]; + // TODO: bug when size is zero we dont increment the pointer + // but if we abort on size 0 - we fail to pick up other devices??? + // we should not get size of 0 unless the size entry is missing + // if (size == 0) + // return NULL; + + const uint8_t *_p = (uint8_t *)p; + device_config *const result = (device_config *)(_p + size); + + if (result >= (device_config *)&usb_state->device_configs_end) + return NULL; + + return result; +} + +device_config *get_usb_device_config(const uint8_t device_index) __sdcccall(1) { + const _usb_state *const usb_state = get_usb_work_area(); + + uint8_t counter = 1; + + for (device_config *p = first_device_config(usb_state); p; p = next_device_config(usb_state, p)) { + if (p->type != USB_NOT_SUPPORTED) { + if (counter == device_index) + return p; + counter++; + } + } + + return NULL; // is not a usb device +} + +usb_device_type usb_get_device_type(const uint16_t dev_index) { + const device_config *dev = get_usb_device_config(dev_index); + + if (dev == NULL) + return -1; + + return dev->type; +} diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.h b/Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.h new file mode 100644 index 00000000..c360f788 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/usb_state.h @@ -0,0 +1,26 @@ +#ifndef __USB_STATE +#define __USB_STATE + +#include "ch376.h" +#include "protocol.h" +#include + +#define MAX_NUMBER_OF_DEVICES 6 +#define DEVICE_CONFIG_STRUCT_SIZE sizeof(device_config_storage) /* Assumes is largest struct */ + +typedef struct __usb_state { + uint8_t active : 1; /* if true, a usb operation/interrupt handler is active, prevent re-entrant */ + uint8_t reserved : 7; + uint8_t count_of_detected_usb_devices; + uint8_t device_configs[DEVICE_CONFIG_STRUCT_SIZE * MAX_NUMBER_OF_DEVICES]; + + uint8_t device_configs_end; // always zero to mark end +} _usb_state; + +extern device_config *find_first_free(void); +extern uint8_t count_of_devices(void) __sdcccall(1); +extern device_config *get_usb_device_config(const uint8_t device_index) __sdcccall(1); + +extern usb_device_type usb_get_device_type(const uint16_t dev_index); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/work-area.c b/Source/HBIOS/ch376-native/source-doc/base-drv/work-area.c new file mode 100644 index 00000000..fb7f46bd --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/work-area.c @@ -0,0 +1,3 @@ +#include "usb_state.h" + +_usb_state x = {0, 0, 0}; diff --git a/Source/HBIOS/ch376-native/source-doc/base-drv/work-area.h b/Source/HBIOS/ch376-native/source-doc/base-drv/work-area.h new file mode 100644 index 00000000..354f0697 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/base-drv/work-area.h @@ -0,0 +1,54 @@ +#ifndef __WORK_AREA +#define __WORK_AREA + +#include "ch376.h" +#include "protocol.h" +#include "stdlib.h" +#include "usb_state.h" + +#define PRES_CF 1 /* BIT MASK FOR COMPACTFLASH PRESENT */ +#define PRES_MS 2 /* BIT MASK FOR MSX MUSIC NOR FLASH PRESENT */ +#define PRES_USB1 4 /* BIT MASK FOR USB1 STORAGE PRESENT AT BOOT UP */ +#define PRES_USB2 8 /* BIT MASK FOR USB2 STORAGE PRESENT AT BOOT UP */ +#define PRES_USB3 16 /* BIT MASK FOR USB3 STORAGE PRESENT AT BOOT UP */ +#define PRES_USB4 32 /* BIT MASK FOR USB4 STORAGE PRESENT AT BOOT UP */ +#define PRES_CH376 128 /* BIT MASK FOR CH376 PRESENT AT BOOT UP */ + +#define BIT_PRES_CF 0 /* BIT POSTION FOR COMPACTFLASH PRESENT */ +#define BIT_PRES_MS 1 /* BIT POSTION FOR MSX MUSIC NOR FLASH PRESENT */ +#define BIT_PRES_USB1 2 /* BIT POSTION FOR USB1 STORAGE PRESENT */ +#define BIT_PRES_USB2 3 /* BIT POSTION FOR USB2 STORAGE PRESENT */ +#define BIT_PRES_USB3 4 /* BIT POSTION FOR USB3 STORAGE PRESENT */ +#define BIT_PRES_USB4 5 /* BIT POSTION FOR USB4 STORAGE PRESENT */ +#define BIT_PRES_CH376 7 /* BIT POSTION FOR CH376 PRESENT */ + +typedef enum { + DEV_MAP_NONE = 0, + DEV_MAP_ROM = 1, + DEV_MAP_CF = 2, + DEV_MAP_MS = 3, + DEV_MAP_USB1 = 4, + DEV_MAP_USB2 = 5, + DEV_MAP_USB3 = 6, + DEV_MAP_USB4 = 7 +} device_map; + +typedef struct _work_area { + uint8_t read_count; /* COUNT OF SECTORS TO BE READ */ + uint16_t index; /* sector number to be read */ + uint8_t *dest; /* destination write address */ + uint8_t read_count_requested; /* number of sectors requested */ + uint8_t present; /* BIT FIELD FOR DETECTED DEVICES + (BIT 0 -> COMPACTFLASH/IDE, BIT 1-> MSX-MUSIC NOR FLASH, BITS 2-5 FOR USB)*/ + _usb_state ch376; +} work_area; + +// extern work_area *get_work_area(void); + +extern uint8_t get_number_of_usb_drives(void); + +extern _usb_state x; + +#define get_usb_work_area() (&x) + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/convert-for-uz80as.sh b/Source/HBIOS/ch376-native/source-doc/convert-for-uz80as.sh new file mode 100755 index 00000000..a5fa4047 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/convert-for-uz80as.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +# Check if exactly two arguments are provided +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +source_file="$1" +destination_file="$2" + +rm -f "$destination_file" + +# create a unique prefix for all generated labels +prefix=$(basename "$source_file" | cut -d. -f1 | tr '-' '_') + +sed -E \ + -e "1i\;\r\n; Generated from source-doc/${source_file} -- not to be modify directly\r\n;\r\n; " \ + -e '/SECTION IGNORE/d' \ + -e '/\sEXTERN\s/d' \ + -e '/\sGLOBAL\s/d' \ + -e '/SECTION .*/d' \ + -e 's/^IF 0/#IF 0/g' \ + -e 's/^ENDIF/#ENDIF/g' \ + -e 's/\s+cp\s+a,\((ix\+[0-9-]+)\)/\tcp\t\(\1\)/g' \ + -e 's/\s+sub\s+a,\((iy\+[0-9]+)\)/\tsub\t\(\1\)/g' \ + -e 's/\s+sub\s+a,\((ix\+[0-9]+)\)/\tsub\t\(\1\)/g' \ + -e 's/\s+sub\s+a,\((ix-[0-9]+)\)/\tsub\t\(\1\)/g' \ + -e 's/\s+or\s+a,\((ix\+[0-9-]+)\)/\tor\t\(\1\)/g' \ + -e 's/\s+or\s+a,\((ix\-[0-9-]+)\)/\tor\t\(\1\)/g' \ + -e 's/\s+or\s+a,\((iy\+[0-9-]+)\)/\tor\t\(\1\)/g' \ + -e 's/\s+or\s+a,\s*\((hl)\)/\tor\t\(\1\)/g' \ + -e 's/\s+sub\s+a,\s*\((hl)\)/\tsub\t\(\1\)/g' \ + -e 's/\s+cp\s+a,(0x[0-9A-Fa-f]{2})/\tcp\t\1/g' \ + -e 's/\s+or\s+a,(0x[0-9A-Fa-f]{2})/\tor\t\1/g' \ + -e 's/\s+xor\s+a,(0x[0-9A-Fa-f]{2})/\txor\t\1/g' \ + -e 's/\s+and\s+a,(0x[0-9A-Fa-f]{2})/\tand\t\1/g' \ + -e 's/\s+and\s+a,\s*a/\tand\ta/g' \ + -e 's/\s+and\s+a,\s*(b|c|d|e|h|l|iyl|iyh|ixl|ixh)/\tand\t\1/g' \ + -e 's/\s+sub\s+a,(0x[0-9A-Fa-f]{2})/\tsub\t\1/g' \ + -e 's/\s+cp\s+a,\s*a/\tcp\ta/g' \ + -e 's/\s+or\s+a,\s*a/\tor\ta/g' \ + -e 's/\s+xor\s+a,\s*a/\txor\ta/g' \ + -e 's/\s+or\s+a,\s*(b|c|d|e|h|l|iyl|iyh|ixl|ixh)/\tor\t\1/g' \ + -e 's/\s+sub\s+a,\s+(b|c|d|e|h|l|iyl|iyh|ixl|ixh)/\tsub\t\1/g' \ + -e 's/\b([a-zA-Z0-9_]{31})[a-zA-Z0-9_]+\b/\1/g' \ + -e 's/;\t+/; /g' \ + -e 's/defc\s+([a-zA-Z0-9_]+)\s*=\s*(0x[0-9A-Fa-f]+)/\1\t.EQU\t\2/' \ + -e "s/___str_([0-9]+)/${prefix}_str_\1/g" \ + -e 's/\b0x([0-9A-Fa-f]+)\b/\$\1/g' \ + "$source_file" > "$destination_file" + + + # -e '/IF 0/d' \ + # -e '/ENDIF/d' \ diff --git a/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.c b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.c new file mode 100644 index 00000000..e8c0a7b3 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.c @@ -0,0 +1,24 @@ +#include "class_hid.h" +#include + +const setup_packet cmd_hid_set = {0x21, HID_SET_PROTOCOL, {0, 0}, {0, 0}, 0}; + +usb_error hid_set_protocol(const device_config_keyboard *const dev, const uint8_t protocol) __sdcccall(1) { + setup_packet cmd; + cmd = cmd_hid_set; + + cmd.bRequest = HID_SET_PROTOCOL; + cmd.bValue[0] = protocol; + + return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size); +} + +usb_error hid_set_idle(const device_config_keyboard *const dev, const uint8_t duration) __sdcccall(1) { + setup_packet cmd; + cmd = cmd_hid_set; + + cmd.bRequest = HID_SET_IDLE; + cmd.bValue[0] = duration; + + return usb_control_transfer(&cmd, NULL, dev->address, dev->max_packet_size); +} diff --git a/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.h b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.h new file mode 100644 index 00000000..d3771b79 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid.h @@ -0,0 +1,21 @@ +#ifndef __CLASS_HID_H__ +#define __CLASS_HID_H__ + +#include "ch376.h" +#include "protocol.h" + +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B + +#define HID_BOOT_PROTOCOL 0x00 +#define HID_REPORT_PROTOCOL 0x01 + +extern usb_error hid_set_protocol(const device_config_keyboard *const dev, const uint8_t protocol) __sdcccall(1); +extern usb_error hid_set_idle(const device_config_keyboard *const dev, const uint8_t duration) __sdcccall(1); +extern usb_error hid_get_input_report(const device_config_keyboard *const dev, uint8_t const *report) __sdcccall(1); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.c b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.c new file mode 100644 index 00000000..a047f36a --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.c @@ -0,0 +1,377 @@ +#include "class_hid_keyboard.h" + +#define ESC 0x1B +/** + * scan codes sourced from https://deskthority.net/wiki/Scancode + * + */ +char scancodes_shift_table[128] = { + 0x00, /*Reserved*/ + 0x00, /*Reserved*/ + 0x00, /*Reserved*/ + 0x00, /*Reserved*/ + + /* 0x04 */ + 'A', + 'B', + 'C', + 'D', + 'E', + 'F', + 'G', + 'H', + + /* 0x0C */ + 'I', + 'J', + 'K', + 'L', + 'M', + 'N', + 'O', + 'P', + + /* 0X14 */ + 'Q', + 'R', + 'S', + 'T', + 'U', + 'V', + 'W', + 'X', + + /* 0X1C */ + 'Y', + 'Z', + '!', + '@', + '#', + '$', + '%', + '^', + + /* 0x24 */ + '&', + '*', + '(', + ')', + '\r', + ESC, + '\b', + '\t', + + /* 0x2C */ + ' ', + '_', + '+', + '{', + '}', + '|', + '~', + ':', + + /* 0x34 */ + '"', + '~', + '<', + '>', + '?', + 0x00 /*CAPSLOCK*/, + 0x00 /* F1 */, + 0x00 /* F2 */, + + /* 0x3C */ + 0x00 /* F3 */, + 0x00 /* F4 */, + 0x00 /* F5 */, + 0x00 /* F6 */, + 0x00 /* F7 */, + 0x00 /* F8 */, + 0x00 /* F9 */, + 0x00 /* F10 */, + + /* 0x44 */ + 0x00 /* F11 */, + 0x00 /* F12 */, + 0x00 /* PRINTSCREEN */, + 0x00 /* SCROLLLOCK */, + 0x00 /* PAUSE */, + 0x00 /* INSERT */, + 0x00 /* HOME */, + 0x00 /* PAGEUP */, + + /* 0x4C */ + 0x00 /* DELETE */, + 0x00 /* END */, + 0x00 /* PAGEDOWN */, + 0x00 /* RIGHT */, + 0x00 /* LEFT */, + 0x00 /* DOWN */, + 0x00 /* UP */, + 0x00 /* NUMLOCK */, + + /* 0x54 */ + '/' /* KP / */, + '*' /* KP * */, + '-' /* KP - */, + '+' /* KP + */, + '\r' /* KP ENTER */, + '1' /* KP 1 */, + '2' /* KP 2 */, + '3' /* KP 3 */, + + /* 0x5C */ + '4' /* KP 4 */, + '5' /* KP 5 */, + '6' /* KP 6 */, + '7' /* KP 7 */, + '8' /* KP 8 */, + '9' /* KP 9 */, + '0' /* KP 0 */, + '.' /* KP . */, + + /* 0x64 */ + '\\', + 0x00 /* MENU */, + 0x00 /* POWER */, + '=' /* KP = */, + 0x00 /* F13 */, + 0x00 /* F14 */, + 0x00 /* F15 */, + 0x00 /* F16 */, + + /* 0x6C */ + 0x00 /* F17 */, + 0x00 /* F18 */, + 0x00 /* F19 */, + 0x00 /* F20 */, + 0x00 /* F21 */, + 0x00 /* F22 */, + 0x00 /* F23 */, + 0x00 /* F24 */, + + /* 0x74 */ + 0x00 /* EXECUTE */, + 0x00 /* HELP */, + 0x00 /* MENU */, + 0x00 /* SELECT */, + 0x00 /* STOP */, + 0x00 /* AGAIN */, + 0x00 /* UNDO */, + 0x00 /* CUT */, + + /* 0x7C */ + 0x00 /* COPY */, + 0x00 /* PASTE */, + 0x00 /* FIND */, + 0x00 /* MUTE */, +}; + +char scancodes_table[128] = { + 0x00, /*Reserved*/ + 0x00, /*Reserved*/ + 0x00, /*Reserved*/ + 0x00, /*Reserved*/ + + /* 0x04 */ + 'a', + 'b', + 'c', + 'd', + 'e', + 'f', + 'g', + 'h', + + /* 0x0C */ + 'i', + 'j', + 'k', + 'l', + 'm', + 'n', + 'o', + 'p', + + /* 0x14 */ + 'q', + 'r', + 's', + 't', + 'u', + 'v', + 'w', + 'x', + + /* 0x1C */ + 'y', + 'z', + '1', + '2', + '3', + '4', + '5', + '6', + + /* 0x24 */ + '7', + '8', + '9', + '0', + '\r', + ESC, + '\b', + '\t', + + /* 0x2C */ + ' ', + '-', + '=', + '[', + ']', + '\\', + '#', + ';', + + /* 0x34 */ + '\'', + '`', + ',', + '.', + '/', + + /* 0x39 */ + 0x00 /*CAPSLOCK*/, + 0x00 /* F1 */, + 0x00 /* F2 */, + + /* 0x3C */ + 0x00 /* F3 */, + 0x00 /* F4 */, + 0x00 /* F5 */, + 0x00 /* F6 */, + 0x00 /* F7 */, + 0x00 /* F8 */, + 0x00 /* F9 */, + 0x00 /* F10 */, + + /* 0x44 */ + 0x00 /* F11 */, + 0x00 /* F12 */, + 0x00 /* PRINTSCREEN */, + 0x00 /* SCROLLLOCK */, + 0x00 /* PAUSE */, + 0x00 /* INSERT */, + 0x00 /* HOME */, + 0x00 /* PAGEUP */, + + /* 0x4C */ + 0x00 /* DELETE */, + 0x00 /* END */, + 0x00 /* PAGEDOWN */, + 0x00 /* RIGHT */, + 0x00 /* LEFT */, + 0x00 /* DOWN */, + 0x00 /* UP */, + 0x00 /* NUMLOCK */, + + /* 0x54 */ + '/' /* KP / */, + '*' /* KP * */, + '-' /* KP - */, + '+' /* KP + */, + '\r' /* KP ENTER */, + '1' /* KP 1 */, + '2' /* KP 2 */, + '3' /* KP 3 */, + + /* 0x5C */ + '4' /* KP 4 */, + '5' /* KP 5 */, + '6' /* KP 6 */, + '7' /* KP 7 */, + '8' /* KP 8 */, + '9' /* KP 9 */, + '0' /* KP 0 */, + '.' /* KP . */, + + /* 0x64 */ + '\\', + 0x00 /* MENU */, + 0x00 /* POWER */, + '=' /* KP = */, + 0x00 /* F13 */, + 0x00 /* F14 */, + 0x00 /* F15 */, + 0x00 /* F16 */, + + /* 0x6C */ + 0x00 /* F17 */, + 0x00 /* F18 */, + 0x00 /* F19 */, + 0x00 /* F20 */, + 0x00 /* F21 */, + 0x00 /* F22 */, + 0x00 /* F23 */, + 0x00 /* F24 */, + + /* 0x74 */ + 0x00 /* EXECUTE */, + 0x00 /* HELP */, + 0x00 /* MENU */, + 0x00 /* SELECT */, + 0x00 /* STOP */, + 0x00 /* AGAIN */, + 0x00 /* UNDO */, + 0x00 /* CUT */, + + /* 0x7C */ + 0x00 /* COPY */, + 0x00 /* PASTE */, + 0x00 /* FIND */, + 0x00 /* MUTE */, +}; + +static char char_with_caps_lock(const char c, const bool caps_lock_engaged) __sdcccall(1) { + if (!caps_lock_engaged) + return c; + + if (c >= 'A' && c <= 'Z') + return c - 'A' + 'a'; + + if (c >= 'a' && c <= 'z') + return c - 'a' + 'A'; + + return c; +} + +char scancode_to_char(const uint8_t modifier_keys, const uint8_t code, const bool caps_lock_engaged) __sdcccall(1) { + if ((modifier_keys & (KEY_MOD_LCTRL | KEY_MOD_RCTRL))) { + if (code >= 4 && code <= 0x1d) + return code - 3; + + if (code == 0x1F || code == 0x2C) //@ or SPACE + return 0; + + if (code == 0x2F) // [ + return 27; + + if (code == 0x31) // back slash + return 28; + + if (code == 0x30) // ] + return 29; + + if (code == 0x23) //^ + return 30; + + if (code == 0x2D) //_ + return 31; + } + + if (modifier_keys & (KEY_MOD_LSHIFT | KEY_MOD_RSHIFT)) + return char_with_caps_lock(scancodes_shift_table[code], caps_lock_engaged); + + return char_with_caps_lock(scancodes_table[code], caps_lock_engaged); +} diff --git a/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.h b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.h new file mode 100644 index 00000000..6243c437 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/keyboard/class_hid_keyboard.h @@ -0,0 +1,27 @@ +#ifndef __CLASS_HID_KEYBOARD_H__ +#define __CLASS_HID_KEYBOARD_H__ + +#include +#include + +typedef struct { + uint8_t bModifierKeys; + uint8_t bReserved; + uint8_t keyCode[6]; +} keyboard_report_t; + +#define KEY_MOD_LCTRL 0x01 +#define KEY_MOD_LSHIFT 0x02 +#define KEY_MOD_LALT 0x04 +#define KEY_MOD_LMETA 0x08 +#define KEY_MOD_RCTRL 0x10 +#define KEY_MOD_RSHIFT 0x20 +#define KEY_MOD_RALT 0x40 +#define KEY_MOD_RMETA 0x80 + +#define KEY_CODE_CAPS_LOCK 0x39 + +extern char scancodes_table[128]; +extern char scancode_to_char(const uint8_t modifier_keys, const uint8_t code, const bool caps_lock_engaged) __sdcccall(1); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/keyboard/kyb-init.c b/Source/HBIOS/ch376-native/source-doc/keyboard/kyb-init.c new file mode 100644 index 00000000..e33d6f71 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/keyboard/kyb-init.c @@ -0,0 +1,25 @@ +#include "kyb_driver.h" +#include +#include +#include + +uint8_t keyboard_init(void) __sdcccall(1) { + uint8_t index = 1; + + do { + usb_device_type t = usb_get_device_type(index); + + if (t == USB_IS_KEYBOARD) { + print_string("\r\nUSB: KEYBOARD @ $"); + print_uint16(index); + print_string(" $"); + + usb_kyb_init(index); + return 1; + } + } while (++index != MAX_NUMBER_OF_DEVICES + 1); + + print_string("\r\nUSB: KEYBOARD: NOT FOUND$"); + + return 0; +} diff --git a/Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.c b/Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.c new file mode 100644 index 00000000..17d5a015 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.c @@ -0,0 +1,136 @@ +#include "kyb_driver.h" +#include "class_hid.h" +#include "class_hid_keyboard.h" +#include +#include +#include +#include + +#define KEYBOARD_BUFFER_SIZE 8 +#define KEYBOARD_BUFFER_SIZE_MASK 7 + +static bool caps_lock_engaged = true; +static device_config_keyboard *keyboard_config = 0; + +static uint8_t buffer[KEYBOARD_BUFFER_SIZE] = {0}; +static uint8_t write_index = 0; +static uint8_t read_index = 0; + +static keyboard_report_t report = {0}; +static keyboard_report_t previous = {0}; + +#define DI __asm__("DI") +#define EI __asm__("EI") + +static uint8_t report_diff() __sdcccall(1) { + uint8_t *a = (uint8_t *)&report; + uint8_t *b = (uint8_t *)&previous; + + uint8_t i = sizeof(report); + do { + if (*a++ != *b++) + return true; + } while (--i != 0); + + return false; +} + +static void keyboard_buf_put(const uint8_t indx) __sdcccall(1) { + const uint8_t key_code = report.keyCode[indx]; + if (key_code >= 0x80 || key_code == 0) + return; // ignore ??? + + // if already reported, just skip it + if (previous.keyCode[indx] == key_code) + return; + + if (key_code == KEY_CODE_CAPS_LOCK) { + caps_lock_engaged = !caps_lock_engaged; + return; + } + + const unsigned char c = scancode_to_char(report.bModifierKeys, key_code, caps_lock_engaged); + + if (c == 0) + return; + + uint8_t next_write_index = (write_index + 1) & KEYBOARD_BUFFER_SIZE_MASK; + if (next_write_index != read_index) { // Check if buffer is not full + buffer[write_index] = c; + write_index = next_write_index; + } +} + +uint8_t usb_kyb_status() __sdcccall(1) { + DI; + + uint8_t size; + + if (write_index >= read_index) + size = write_index - read_index; + else + size = KEYBOARD_BUFFER_SIZE - read_index + write_index; + + EI; + return size; +} + +uint16_t usb_kyb_read() { + if (write_index == read_index) // Check if buffer is empty + return 0xFF00; // H = -1, L = 0 + + DI; + const uint8_t c = buffer[read_index]; + read_index = (read_index + 1) & KEYBOARD_BUFFER_SIZE_MASK; + EI; + + /* H = 0, L = ascii char */ + return c; +} + +uint8_t usb_kyb_flush() __sdcccall(1) { + DI; + write_index = read_index = 0; + + uint8_t i = sizeof(previous); + uint8_t *a = (uint8_t *)previous; + uint8_t *b = (uint8_t *)report; + do { + *a++ = 0; + *b++ = 0; + } while (--i != 0); + + EI; + + return 0; +} + +void usb_kyb_tick(void) { + usb_error result; + + if (is_in_critical_section()) + return; + + ch_configure_nak_retry_disable(); + result = usbdev_dat_in_trnsfer_0((device_config *)keyboard_config, (uint8_t *)&report, 8); + ch_configure_nak_retry_3s(); + if (result == 0) { + if (report_diff()) { + uint8_t i = 6; + do { + keyboard_buf_put(i - 1); + } while (--i != 0); + previous = report; + } + } +} + +void usb_kyb_init(const uint8_t dev_index) __sdcccall(1) { + keyboard_config = (device_config_keyboard *)get_usb_device_config(dev_index); + + if (keyboard_config == NULL) + return; + + hid_set_protocol(keyboard_config, 1); + hid_set_idle(keyboard_config, 0x80); +} diff --git a/Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.h b/Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.h new file mode 100644 index 00000000..c9a744f7 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/keyboard/kyb_driver.h @@ -0,0 +1,12 @@ +#ifndef __KYB_DRIVER__ +#define __KYB_DRIVER__ + +#include +#include + +extern void usb_kyb_init(const uint8_t dev_index) __sdcccall(1); +extern uint8_t usb_kyb_flush() __sdcccall(1); +extern uint8_t usb_kyb_status() __sdcccall(1); +extern uint16_t usb_kyb_read(); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.c b/Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.c new file mode 100644 index 00000000..0c14cb4e --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.c @@ -0,0 +1,77 @@ +#include "class_scsi.h" +#include +#include +#include +#include + +_scsi_command_block_wrapper scsi_cmd_blk_wrap = {{0x55, 0x53, 0x42, 0x43}, {0, 0}, 0, 0, 0, 0}; + +uint16_t next_tag = 0; + +usb_error do_scsi_cmd(device_config_storage *const dev, + _scsi_command_block_wrapper *const cbw, + void *const send_receive_buffer, + const bool send) { + + usb_error result; + _scsi_command_status_wrapper csw = {{{0}}}; + + cbw->dCBWTag[0] = next_tag++; + + if (!send) + cbw->bmCBWFlags = 0x80; + + critical_begin(); + + CHECK(usb_data_out_transfer((uint8_t *)cbw, sizeof(_scsi_command_block_wrapper) + 16, dev->address, + &dev->endpoints[ENDPOINT_BULK_OUT])); + + if (cbw->dCBWDataTransferLength != 0) { + if (!send) { + CHECK(usb_data_in_transfer(send_receive_buffer, (uint16_t)cbw->dCBWDataTransferLength, dev->address, + &dev->endpoints[ENDPOINT_BULK_IN])); + + } else { + CHECK(usb_data_out_transfer(send_receive_buffer, (uint16_t)cbw->dCBWDataTransferLength, dev->address, + &dev->endpoints[ENDPOINT_BULK_OUT])); + } + } + + CHECK( + usb_data_in_transfer((uint8_t *)&csw, sizeof(_scsi_command_status_wrapper), dev->address, &dev->endpoints[ENDPOINT_BULK_IN])); + + if (csw.bCSWStatus != 0 || csw.dCSWTag[0] != cbw->dCBWTag[0]) + result = USB_ERR_FAIL; + else + result = USB_ERR_OK; + +done: + critical_end(); + return result; +} + +usb_error scsi_test(device_config_storage *const dev) { + cbw_scsi_test cbw_scsi; + cbw_scsi.cbw = scsi_cmd_blk_wrap; + memset(&cbw_scsi.test, 0, sizeof(_scsi_packet_test)); + + cbw_scsi.cbw.bCBWLUN = 0; + cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_test); + cbw_scsi.cbw.dCBWDataTransferLength = 0; + + return do_scsi_cmd(dev, &cbw_scsi.cbw, 0, false); +} + +const _scsi_packet_request_sense scsi_pckt_req_sense = {0x03, 0, 0, 0, 18, 0, {0, 0, 0, 0, 0, 0}}; + +usb_error scsi_request_sense(device_config_storage *const dev, scsi_sense_result *const sens_result) { + cbw_scsi_request_sense cbw_scsi; + cbw_scsi.cbw = scsi_cmd_blk_wrap; + cbw_scsi.request_sense = scsi_pckt_req_sense; + + cbw_scsi.cbw.bCBWLUN = 0; + cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_request_sense); + cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_sense_result); + + return do_scsi_cmd(dev, &cbw_scsi.cbw, sens_result, false); +} diff --git a/Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.h b/Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.h new file mode 100644 index 00000000..8f59ef22 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/scsi-drv/class_scsi.h @@ -0,0 +1,196 @@ +#ifndef __CLASS_SCSI +#define __CLASS_SCSI + +#include + +typedef struct { + uint8_t dCBWSignature[4]; + uint16_t dCBWTag[2]; + uint32_t dCBWDataTransferLength; + uint8_t bmCBWFlags; + uint8_t bCBWLUN; + uint8_t bCBWCBLength; +} _scsi_command_block_wrapper; + +typedef struct { + uint8_t operation_code; + uint8_t lun; + uint8_t reserved1; + uint8_t reserved2; + uint8_t allocation_length; + uint8_t reserved3; + uint8_t pad[6]; +} _scsi_packet_request_sense; + +typedef struct { + _scsi_command_block_wrapper cbw; + _scsi_packet_request_sense request_sense; +} cbw_scsi_request_sense; + +typedef struct { + uint8_t operation_code; + + uint8_t IMMED : 1; + uint8_t reserved : 7; + + uint8_t reserved2; + + uint8_t power_condition_modifier : 4; + uint8_t reserved3 : 4; + + uint8_t start : 1; + uint8_t loej : 1; + uint8_t no_flush : 1; + uint8_t reserved4 : 1; + uint8_t power_condition : 4; + + uint8_t control; +} _scsi_packet_eject; + +typedef struct { + _scsi_command_block_wrapper cbw; + _scsi_packet_eject eject; +} cbw_scsi_eject; + +typedef struct { + uint8_t operation_code; + uint8_t lun; + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t reserved4; + uint8_t pad[6]; +} _scsi_packet_test; + +typedef struct { + _scsi_command_block_wrapper cbw; + _scsi_packet_test test; +} cbw_scsi_test; + +typedef struct { + uint8_t operation_code; + uint8_t lun; + uint8_t reserved[8]; + uint8_t pad[2]; +} _scsi_read_capacity; + +typedef struct { + _scsi_command_block_wrapper cbw; + _scsi_read_capacity read_capacity; +} cbw_scsi_read_capacity; + +typedef struct __scsi_packet_inquiry { // contains information about a specific device + uint8_t operation_code; + uint8_t lun; + uint8_t reserved1; + uint8_t reserved2; + uint8_t allocation_length; + uint8_t reserved3; + uint8_t pad[6]; +} _scsi_packet_inquiry; + +typedef struct { + _scsi_command_block_wrapper cbw; + _scsi_packet_inquiry inquiry; +} cbw_scsi_inquiry; + +typedef struct { + uint8_t device_type : 5; + uint8_t device_type_qualifier : 3; + uint8_t device_type_modifier : 7; + uint8_t removable_media : 1; + union { + uint8_t versions; + struct { + uint8_t ansi_version : 3; + uint8_t ecma_version : 3; + uint8_t iso_version : 2; + }; + }; + uint8_t response_data_format : 4; + uint8_t hi_support : 1; + uint8_t norm_aca : 1; + uint8_t terminate_task : 1; + uint8_t aerc : 1; + uint8_t additional_length; + uint8_t reserved; + uint8_t addr16 : 1; + uint8_t addr32 : 1; + uint8_t ack_req_q : 1; + uint8_t medium_changer : 1; + uint8_t multi_port : 1; + uint8_t reserved_bit2 : 1; + uint8_t enclosure_services : 1; + uint8_t reserved_bit3 : 1; + uint8_t soft_reset : 1; + uint8_t command_queue : 1; + uint8_t transfer_disable : 1; + uint8_t linked_commands : 1; + uint8_t synchronous : 1; + uint8_t wide16_bit : 1; + uint8_t wide32_bit : 1; + uint8_t relative_addressing : 1; + uint8_t vendor_information[8]; + uint8_t product_id[16]; + uint8_t product_revision[4]; + uint8_t vendor_specific[20]; + uint8_t reserved3[40]; +} scsi_inquiry_result; + +typedef struct __scsi_command_status_wrapper { + uint8_t dCSWSignature[4]; + uint16_t dCSWTag[2]; + uint8_t dCSWDataResidue[4]; + uint8_t bCSWStatus; +} _scsi_command_status_wrapper; + +typedef struct { + uint8_t number_of_blocks[4]; + uint8_t block_size[4]; +} scsi_read_capacity_result; + +typedef struct { + uint8_t error_code : 7; + uint8_t valid : 1; + uint8_t segment_number; + uint8_t sense_key : 4; + uint8_t reserved : 1; + uint8_t incorrect_length : 1; + uint8_t end_of_media : 1; + uint8_t file_mark : 1; + uint8_t information[4]; + uint8_t additional_sense_length; + uint8_t command_specific_information[4]; + uint8_t additional_sense_code; + uint8_t additional_sense_code_qualifier; + uint8_t field_replaceable_unit_code; + uint8_t sense_key_specific[3]; +} scsi_sense_result; + +typedef struct { + uint8_t operation_code; + uint8_t lun; + uint8_t lba[4]; // high-endian block number + uint8_t reserved1; + uint8_t transfer_len[2]; // high-endian in blocks of block_len (see scsi_capacity) + uint8_t reserved2; + uint8_t pad[2]; +} _scsi_packet_read_write; + +typedef struct { + _scsi_command_block_wrapper cbw; + _scsi_packet_read_write scsi_cmd; +} cbw_scsi_read_write; + +extern _scsi_command_block_wrapper scsi_cmd_blk_wrap; + +extern usb_error do_scsi_cmd(device_config_storage *const dev, + _scsi_command_block_wrapper *const cbw, + void *const send_receive_buffer, + const bool send); + +extern usb_error scsi_test(device_config_storage *const dev); + +extern usb_error scsi_request_sense(device_config_storage *const dev, scsi_sense_result *const sens_result); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi-init.c b/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi-init.c new file mode 100644 index 00000000..c6769e29 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi-init.c @@ -0,0 +1,30 @@ +#include "hbios-driver-storage.h" +#include "scsi_driver.h" +#include +#include +#include + +extern const uint16_t const ch_scsi_fntbl[]; + +void chscsi_init(void) { + uint8_t index = 1; + do { + usb_device_type t = usb_get_device_type(index); + + if (t == USB_IS_MASS_STORAGE) { + const uint8_t dev_index = find_storage_dev(); // index == -1 (no more left) should never happen + + hbios_usbstore_devs[dev_index].drive_index = dev_index + 1; + hbios_usbstore_devs[dev_index].usb_device = index; + + print_string("\r\nUSB: MASS STORAGE @ $"); + print_uint16(index); + print_string(":$"); + print_uint16(dev_index); + print_string(" $"); + usb_scsi_init(index); + dio_add_entry(ch_scsi_fntbl, &hbios_usbstore_devs[dev_index]); + } + + } while (++index != MAX_NUMBER_OF_DEVICES + 1); +} diff --git a/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.c b/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.c new file mode 100644 index 00000000..bb003236 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.c @@ -0,0 +1,123 @@ +#include "scsi_driver.h" +#include "class_scsi.h" +#include +#include +#include +#include + +usb_error usb_scsi_init(const uint16_t dev_index) { + usb_error result; + + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + scsi_sense_result response; + uint8_t counter = 3; + + critical_begin(); + while ((result = scsi_test(dev)) && --counter > 0) + scsi_request_sense(dev, &response); + critical_end(); + + return result; +} + +_scsi_read_capacity scsi_pkt_read_cap = {0x25, 0, {0, 0, 0, 0, 0, 0, 0, 0}, {0, 0}}; + +usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *cap_result) { + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + cbw_scsi_read_capacity cbw_scsi; + cbw_scsi.cbw = scsi_cmd_blk_wrap; + cbw_scsi.read_capacity = scsi_pkt_read_cap; + + cbw_scsi.cbw.bCBWLUN = 0; + cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_read_capacity); + cbw_scsi.cbw.dCBWDataTransferLength = sizeof(scsi_read_capacity_result); + + return do_scsi_cmd(dev, &cbw_scsi.cbw, cap_result, false); +} + +// _scsi_packet_inquiry scsi_packet_inquiry = {0x12, 0, 0, 0, 0x24, 0, {0, 0, 0, 0, 0, 0}}; + +// usb_error usb_scsi_inquiry(const uint16_t dev_index, scsi_inquiry_result *inq_result) { +// device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + +// cbw_scsi_inquiry cbw_scsi; +// cbw_scsi.cbw = scsi_cmd_blk_wrap; +// cbw_scsi.inquiry = scsi_packet_inquiry; + +// cbw_scsi.cbw.bCBWLUN = 0; +// cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_inquiry); +// cbw_scsi.cbw.dCBWDataTransferLength = 0x24; + +// return do_scsi_cmd(dev, &cbw_scsi.cbw, inq_result, false); +// } + +static cbw_scsi_read_write cbw = {{{0}}}; + +usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer) { + usb_error result; + + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + memset(&cbw, 0, sizeof(cbw_scsi_read_write)); + cbw.cbw = scsi_cmd_blk_wrap; + + cbw.cbw.bCBWLUN = 0; + cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write); + cbw.cbw.dCBWDataTransferLength = 512; + + cbw.scsi_cmd.operation_code = 0x28; // read operation + cbw.scsi_cmd.transfer_len[1] = 1; + cbw.scsi_cmd.lba[0] = dev->current_lba >> 24; + cbw.scsi_cmd.lba[1] = dev->current_lba >> 16; + cbw.scsi_cmd.lba[2] = dev->current_lba >> 8; + cbw.scsi_cmd.lba[3] = dev->current_lba; + + result = do_scsi_cmd(dev, &cbw.cbw, buffer, false); + + if (result == USB_ERR_OK) + dev->current_lba++; + return result; +} + +usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer) { + usb_error result; + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + memset(&cbw, 0, sizeof(cbw_scsi_read_write)); + cbw.cbw = scsi_cmd_blk_wrap; + + cbw.cbw.bCBWLUN = 0; + cbw.cbw.bCBWCBLength = sizeof(_scsi_packet_read_write); + cbw.cbw.dCBWDataTransferLength = 512; + + cbw.scsi_cmd.operation_code = 0x2A; // write operation + cbw.scsi_cmd.transfer_len[1] = 1; + cbw.scsi_cmd.lba[0] = dev->current_lba >> 24; + cbw.scsi_cmd.lba[1] = dev->current_lba >> 16; + cbw.scsi_cmd.lba[2] = dev->current_lba >> 8; + cbw.scsi_cmd.lba[3] = dev->current_lba; + + result = do_scsi_cmd(dev, &cbw.cbw, buffer, true); + + if (result == USB_ERR_OK) + dev->current_lba++; + return result; +} + +// usb_error scsi_eject(device_config_storage *const dev) { +// cbw_scsi_eject cbw_scsi; +// cbw_scsi.cbw = scsi_cmd_blk_wrap; + +// memset(&cbw_scsi.eject, 0, sizeof(_scsi_packet_eject)); + +// cbw_scsi.eject.operation_code = 0x1B; +// cbw_scsi.eject.loej = 1; + +// cbw_scsi.cbw.bCBWLUN = 0; +// cbw_scsi.cbw.bCBWCBLength = sizeof(_scsi_packet_eject); +// cbw_scsi.cbw.dCBWDataTransferLength = 0; + +// return do_scsi_cmd(dev, &cbw_scsi.cbw, 0, false); +// } diff --git a/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.h b/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.h new file mode 100644 index 00000000..92e57912 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/scsi-drv/scsi_driver.h @@ -0,0 +1,14 @@ +#ifndef __SCSI_DRIVER__ +#define __SCSI_DRIVER__ + +#include "class_scsi.h" +#include +#include + +extern usb_error usb_scsi_init(const uint16_t dev_index); +extern usb_error usb_scsi_read_capacity(const uint16_t dev_index, scsi_read_capacity_result *result); +extern usb_error usb_scsi_read(const uint16_t dev_index, uint8_t *const buffer); +extern usb_error usb_scsi_write(const uint16_t dev_index, uint8_t *const buffer); +extern usb_error usb_scsi_seek(const uint16_t dev_index, const uint32_t lba); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.c b/Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.c new file mode 100644 index 00000000..c859e7cb --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.c @@ -0,0 +1,179 @@ +#include "class_ufi.h" +#include +#include +#include +#include +#include + +const ufi_request_sense_command _ufi_cmd_request_sense = {0x03, 0, 0, 0, 18, {0, 0, 0, 0, 0, 0, 0}}; +const ufi_read_format_capacities_command _ufi_cmd_rd_fmt_caps = {0x23, 0, {0, 0, 0, 0, 0}, {0, 12}, {0, 0, 0}}; +const ufi_inquiry_command _ufi_cmd_inquiry = {0x12, 0, 0, 0, 0x24, {0, 0, 0, 0, 0, 0, 0}}; +const ufi_format_command _ufi_cmd_format = {0x04, 7 | 1 << 4, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0, 0}}; +const ufi_send_diagnostic_command _ufi_cmd_send_diag = {0x1D, 1 << 2, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; + +uint8_t wait_for_device_ready(device_config *const storage_device, uint8_t timeout_counter) { + usb_error result; + ufi_request_sense_response sense; + + do { + memset(&sense, 0, sizeof(sense)); + result = ufi_test_unit_ready(storage_device, &sense); + + if ((result == USB_ERR_OK && (sense.sense_key & 15) == 0) || timeout_counter-- == 0) + break; + + delay_medium(); + + } while (true); + + return result | (sense.sense_key & 15); +} + +usb_error ufi_test_unit_ready(device_config *const storage_device, ufi_request_sense_response const *response) { + usb_error result; + ufi_test_unit_ready_command ufi_cmd_request_test_unit_ready; + memset(&ufi_cmd_request_test_unit_ready, 0, sizeof(ufi_test_unit_ready_command)); + + usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_test_unit_ready, false, 0, NULL, NULL); + + ufi_request_sense_command ufi_cmd_request_sense; + ufi_cmd_request_sense = _ufi_cmd_request_sense; + + result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_sense, false, sizeof(ufi_request_sense_response), + (uint8_t *)response, NULL); + RETURN_CHECK(result); +done: + return result; +} + +usb_error ufi_request_sense(device_config *const storage_device, ufi_request_sense_response const *response) { + ufi_request_sense_command ufi_cmd_request_sense; + ufi_cmd_request_sense = _ufi_cmd_request_sense; + + usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_sense, false, sizeof(ufi_request_sense_response), + (uint8_t *)response, NULL); + + RETURN_CHECK(result); +done: + return result; +} + +usb_error ufi_read_frmt_caps(device_config *const storage_device, ufi_format_capacities_response const *response) { + usb_error result; + ufi_read_format_capacities_command ufi_cmd_read_format_capacities; + + ufi_cmd_read_format_capacities = _ufi_cmd_rd_fmt_caps; + result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_read_format_capacities, false, 12, (uint8_t *)response, NULL); + + TRACE_USB_ERROR(result); + CHECK(result); + + const uint8_t available_length = response->capacity_list_length; + + const uint8_t max_length = + available_length > sizeof(ufi_format_capacities_response) ? sizeof(ufi_format_capacities_response) : available_length; + + ufi_read_format_capacities_command cmd; + memcpy(&cmd, &ufi_cmd_read_format_capacities, sizeof(cmd)); + cmd.allocation_length[1] = max_length; + + result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, false, max_length, (uint8_t *)response, NULL); + + TRACE_USB_ERROR(result); + RETURN_CHECK(result); +done: + return result; +} + +usb_error ufi_inquiry(device_config *const storage_device, ufi_inquiry_response const *response) { + ufi_inquiry_command ufi_cmd_inquiry; + ufi_cmd_inquiry = _ufi_cmd_inquiry; + + usb_error result = + usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_inquiry, false, sizeof(ufi_inquiry_response), (uint8_t *)response, NULL); + + RETURN_CHECK(result); +done: + return result; +} + +usb_error ufi_read_write_sector(device_config *const storage_device, + const bool send, + const uint16_t sector_number, + const uint8_t sector_count, + uint8_t *const buffer, + uint8_t *const sense_codes) { + ufi_read_write_command cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.operation_code = send ? 0x2A : 0x28; + cmd.lba[2] = sector_number >> 8; + cmd.lba[3] = sector_number & 0xFF; + cmd.transfer_length[1] = sector_count; + + usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, send, 512 * sector_count, (uint8_t *)buffer, sense_codes); + + RETURN_CHECK(result); +done: + return result; +} + +/** + * Medium | Medium Type Code | Capacity | Tracks | Heads | Sectors/Track | Total Blocks | Block Length | + * DD | 1Eh | 720 KB | 80 | 2 | 9 | 1440 05A0h | 512 0200h | + * HD | 93h | 1.25 MB | 77 | 2 | 8 | 1232 04D0h | 1024 0400h | + * HD | 94h | 1.44 MB | 80 | 2 | 18 | 2880 0B40h | 512 0200h | + */ + +usb_error ufi_format(device_config *const storage_device, + const uint8_t side, + const uint8_t track_number, + const ufi_format_capacity_descriptor *const format) { + ufi_interrupt_status sense_codes; + + ufi_format_parameter_list parameter_list; + memset(¶meter_list, 0, sizeof(parameter_list)); + + ufi_format_command cmd; + cmd = _ufi_cmd_format; + // memcpy(&cmd, &_ufi_cmd_format, sizeof(cmd)); + + cmd.track_number = track_number; + cmd.interleave[1] = 0; + cmd.parameter_list_length[1] = sizeof(parameter_list); + + parameter_list.defect_list_header.status = + FMT_DEFECT_STATUS_FOV | FMT_DEFECT_STATUS_DCRT | FMT_DEFECT_STATUS_SINGLE_TRACK | (side & 1); + parameter_list.defect_list_header.defect_list_length_msb = 0; + parameter_list.defect_list_header.defect_list_length_lsb = 8; + memcpy(¶meter_list.format_descriptor, (void *)format, sizeof(ufi_format_capacity_descriptor)); + + usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, true, sizeof(parameter_list), (uint8_t *)¶meter_list, + (void *)&sense_codes); + + // trace_printf("ufi_format: %d, %02X %02X (len: %d)\r\n", result, sense_codes.bASC, sense_codes.bASCQ, sizeof(parameter_list)); + + RETURN_CHECK(result); +done: + return result; +} + +usb_error ufi_send_diagnostics(device_config *const storage_device) { + ufi_send_diagnostic_command ufi_cmd_send_diagnostic; + + ufi_cmd_send_diagnostic = _ufi_cmd_send_diag; + + return usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_send_diagnostic, true, 0, NULL, NULL); +} + +uint32_t convert_from_msb_first(const uint8_t *const buffer) { + uint32_t result; + uint8_t *p_output = ((uint8_t *)&result); + const uint8_t *p_input = buffer + 3; + + *p_output++ = *p_input--; + *p_output++ = *p_input--; + *p_output++ = *p_input--; + *p_output = *p_input--; + + return result; +} diff --git a/Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.h b/Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.h new file mode 100644 index 00000000..58df1c6e --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/ufi-drv/class_ufi.h @@ -0,0 +1,186 @@ +#ifndef __CLASS_UFI2 +#define __CLASS_UFI2 + +#include "ch376.h" +#include "protocol.h" +#include "usb_cbi.h" +#include "usb_state.h" +#include + +typedef struct { + uint8_t bASC; + uint8_t bASCQ; +} ufi_interrupt_status; + +typedef struct { + uint8_t operation_code; + uint8_t lun; // in top 3 bits + uint8_t reserved1[5]; + uint8_t allocation_length[2]; + uint8_t reserved[3]; +} ufi_read_format_capacities_command; + +typedef enum { UNFORMATTED_MEDIA = 1, FORMATTED_MEDIA = 2, NO_MEDIA = 3 } UFI_DESCRIPTOR_CODE; + +#define UFI_DESCRIPTOR_CODE_UNFORMATTED_MEDIA 1 +#define UFI_DESCRIPTOR_CODE_FORMATTED_MEDIA 2 +#define UFI_DESCRIPTOR_CODE_NO_MEDIA 3 + +typedef struct { + uint8_t number_of_blocks[4]; + uint8_t descriptor_codex; // UFI_DESCRIPTOR_CODE + uint8_t block_size[3]; +} ufi_format_capacity_descriptor; + +typedef struct { + uint8_t reserved1[3]; + uint8_t capacity_list_length; + ufi_format_capacity_descriptor descriptors[4]; // support upto +} ufi_format_capacities_response; + +typedef struct { + uint8_t operation_code; + uint8_t lun; + uint8_t reserved[10]; +} ufi_test_unit_ready_command; + +typedef struct { + uint8_t operation_code; + uint8_t lun_and_evpd; + uint8_t page_code; + uint8_t reserved3; + uint8_t allocation_length; + uint8_t reserved4[7]; +} ufi_inquiry_command; + +typedef struct { + uint8_t operation_code; + uint8_t lun; // top 3 bits + uint8_t reserved2; + uint8_t reserved3; + uint8_t allocation_length; + uint8_t reserved4[7]; +} ufi_request_sense_command; + +typedef struct { + uint8_t error_code; + uint8_t reserved1; + uint8_t sense_key; // lower 4 bits + uint8_t information[4]; + uint8_t additional_length; + uint8_t reserved3[4]; + uint8_t asc; // Additional Sense Code + uint8_t ascq; // Additional Sense Code Qualifier + uint8_t reserved4[4]; +} ufi_request_sense_response; + +typedef struct { + // device_type: identifies the device currently connected to the requested logical unit. + // 00h Direct-access device (floppy) + // 1Fh none (no FDD connected to the requested logical unit) + uint8_t device_type; // lower 5 bits + + // Removable Media Bit: this shall be set to one to indicate removable media. + uint8_t removable_media; // top bit + + // ANSI Version: must contain a zero to comply with this version of the Specification. + // ISO/ECMA: These fields shall be zero for the UFI device. + uint8_t version; + + // Response Data Format: a value of 01h shall be used for UFI device + uint8_t response_data_format; // lower 4 bits + + // The Additional Length field shall specify the length in bytes of the parameters. If the Allocation Length of the + // Command Packet is too small to transfer all of the parameters, the Additional Length shall not be adjusted to + // reflect the truncation. The UFI device shall set this field to 1Fh. + uint8_t additional_length; + uint8_t reserved4[3]; + + // The Vendor Identification field contains 8 bytes of ASCII data identifying the vendor of the product. The data + // shall be left aligned within this field. + char vendor_information[8]; + + // The Product Identification field contains 16 bytes of ASCII data as defined by the vendor. The data shall be + // left-aligned within this field. + char product_id[16]; + + // The Product Revision Level field contains 4 bytes of ASCII data as defined by the vendor. + char product_revision[4]; +} ufi_inquiry_response; + +typedef struct { + uint8_t operation_code; /*0*/ + uint8_t byte_1; /*1*/ + /* [7:5] lun, [4] dpo, [3] fua, [0]rel_adr*/ + uint8_t lba[4]; /*2, 3, 4, 5*/ + uint8_t reserved2; /*6*/ + uint8_t transfer_length[2]; /*7, 8*/ + uint8_t reserved3[3]; /*9, 10, 11*/ +} ufi_read_write_command; + +typedef struct { + struct { + uint8_t reserved1; + /* [7] FOV, [6] Extend, [5] DCRT, [4] SingleTrack, [1] Immediate, [0] Side*/ + uint8_t status; + uint8_t defect_list_length_msb; + uint8_t defect_list_length_lsb; + } defect_list_header; + + ufi_format_capacity_descriptor format_descriptor; +} ufi_format_parameter_list; + +#define FMT_DEFECT_STATUS_FOV 0x80 +#define FMT_DEFECT_STATUS_EXTEND 0x40 +#define FMT_DEFECT_STATUS_DCRT 0x20 +#define FMT_DEFECT_STATUS_SINGLE_TRACK 0x10 +#define FMT_DEFECT_STATUS_IMMEDIATE 0x02 +#define FMT_DEFECT_STATUS_SIDE 0x01 + +typedef struct { + uint8_t operation_code; /* 0x04 */ + /* [7:5] lun, [4]format_data, [3]cmp_list, [2:0] defect_list_format*/ + uint8_t status; + uint8_t track_number; + uint8_t interleave[2]; + uint8_t reserved1[2]; + uint8_t parameter_list_length[2]; + uint8_t reserved2[3]; +} ufi_format_command; + +typedef struct { + uint8_t operation_code; /*0x1D*/ + /* [7:5] lun, [4] pf, [2] self test, [1] def of l [0] unit of l*/ + uint8_t status; + uint8_t reserved[10]; +} ufi_send_diagnostic_command; + +extern usb_error ufi_request_sense(device_config *const storage_device, ufi_request_sense_response const *response); + +extern usb_error ufi_read_frmt_caps(device_config *const storage_device, ufi_format_capacities_response const *response); + +extern usb_error ufi_test_unit_ready(device_config *const storage_device, ufi_request_sense_response const *response); + +extern usb_error ufi_inquiry(device_config *const storage_device, ufi_inquiry_response const *response); + +extern usb_error ufi_read_write_sector(device_config *const storage_device, + const bool send, + const uint16_t sector_number, + const uint8_t sector_count, + const uint8_t *const buffer, + uint8_t *const sense_codes); + +uint8_t wait_for_device_ready(device_config *const storage_device, uint8_t timeout_counter); + +usb_error ufi_format(device_config *const storage_device, + const uint8_t side, + const uint8_t track_number, + const ufi_format_capacity_descriptor *const format); + +usb_error ufi_send_diagnostics(device_config *const storage_device); + +uint32_t convert_from_msb_first(const uint8_t *const buffer); + +extern usb_error ufi_seek(const uint16_t dev_index, const uint32_t lba); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi-init.c b/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi-init.c new file mode 100644 index 00000000..63969756 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi-init.c @@ -0,0 +1,29 @@ +#include "hbios-driver-storage.h" +#include +#include +#include + +extern const uint16_t const ch_ufi_fntbl[]; + +void chufi_init(void) { + uint8_t index = 1; + + do { + usb_device_type t = usb_get_device_type(index); + + if (t == USB_IS_FLOPPY) { + const uint8_t dev_index = find_storage_dev(); // dev_index == -1 (no more left) should never happen + + hbios_usbstore_devs[dev_index].drive_index = dev_index + 1; + hbios_usbstore_devs[dev_index].usb_device = index; + + print_string("\r\nUSB: FLOPPY @ $"); + print_uint16(index); + print_string(":$"); + print_uint16(dev_index); + print_string(" $"); + dio_add_entry(ch_ufi_fntbl, &hbios_usbstore_devs[dev_index]); + } + + } while (++index != MAX_NUMBER_OF_DEVICES + 1); +} diff --git a/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.c b/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.c new file mode 100644 index 00000000..65a7d904 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.c @@ -0,0 +1,85 @@ +#include "ufi_driver.h" +#include "class_ufi.h" +#include +#include + +uint32_t usb_ufi_get_cap(const uint16_t dev_index) { + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + ufi_format_capacities_response response; + memset(&response, 0, sizeof(ufi_format_capacities_response)); + + wait_for_device_ready(dev, 25); + + // not sure if we need to do this to 'clear' some state + ufi_inquiry_response inquiry; + ufi_inquiry(dev, &inquiry); + + wait_for_device_ready(dev, 15); + + const usb_error result = ufi_read_frmt_caps(dev, &response); + if (result != USB_ERR_OK) + return 0; + + return convert_from_msb_first(response.descriptors[0].number_of_blocks); +} + +usb_error usb_ufi_read(const uint16_t dev_index, uint8_t *const buffer) { + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + if (wait_for_device_ready((device_config *)dev, 20) != 0) + return -1; // Not READY! + + usb_error result; + ufi_interrupt_status sense_codes; + + memset(&sense_codes, 0, sizeof(sense_codes)); + + if (ufi_read_write_sector((device_config *)dev, false, dev->current_lba, 1, buffer, (uint8_t *)&sense_codes) != USB_ERR_OK) + return -1; // general error + + ufi_request_sense_response response; + memset(&response, 0, sizeof(response)); + + if ((result = ufi_request_sense((device_config *)dev, &response)) != USB_ERR_OK) + return -1; // error + + const uint8_t asc = response.asc; + const uint8_t ascq = response.ascq; + const uint8_t sense_key = response.sense_key & 15; + + if (sense_key != 0) + return -1; + + return USB_ERR_OK; +} + +usb_error usb_ufi_write(const uint16_t dev_index, uint8_t *const buffer) { + device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + + if (wait_for_device_ready((device_config *)dev, 20) != 0) + return -1; // Not READY! + + ufi_interrupt_status sense_codes; + + memset(&sense_codes, 0, sizeof(sense_codes)); + if ((ufi_read_write_sector((device_config *)dev, true, dev->current_lba, 1, buffer, (uint8_t *)&sense_codes)) != USB_ERR_OK) { + return -1; + } + + ufi_request_sense_response response; + memset(&response, 0, sizeof(response)); + + if ((ufi_request_sense((device_config *)dev, &response)) != USB_ERR_OK) { + return -1; + } + + const uint8_t asc = response.asc; + const uint8_t ascq = response.ascq; + const uint8_t sense_key = response.sense_key & 15; + + if (sense_key != 0) + return -1; + + return USB_ERR_OK; +} diff --git a/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.h b/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.h new file mode 100644 index 00000000..4c847bee --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/ufi-drv/ufi_driver.h @@ -0,0 +1,11 @@ +#ifndef __UFI_DRIVER__ +#define __UFI_DRIVER__ + +#include +#include + +extern uint32_t usb_ufi_get_cap(const uint16_t dev_index); +extern usb_error usb_ufi_read(const uint16_t dev_index, uint8_t *const buffer); +extern usb_error usb_ufi_write(const uint16_t dev_index, uint8_t *const buffer); + +#endif diff --git a/Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.c b/Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.c new file mode 100644 index 00000000..8c2763e5 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.c @@ -0,0 +1,69 @@ +#include "usb_cbi.h" +#include "dev_transfers.h" +#include "protocol.h" +#include +#include + +setup_packet cbi2_adsc = {0x21, 0, {0, 0}, {255, 0}, 12}; // ;4th byte is interface number + +// was no clear +usb_error usb_execute_cbi(device_config *const storage_device, + const uint8_t *const cmd, + const bool send, + const uint16_t buffer_size, + uint8_t *const buffer, + uint8_t *const sense_codes) { + usb_error result; + const uint8_t interface_number = storage_device->interface_number; + + setup_packet adsc; + adsc = cbi2_adsc; + adsc.bIndex[0] = interface_number; + + critical_begin(); + + result = usbdev_control_transfer(storage_device, &adsc, (uint8_t *const)cmd); + + if (result == USB_ERR_STALL) { + if (sense_codes != NULL) + usbdev_dat_in_trnsfer(storage_device, sense_codes, 2, ENDPOINT_INTERRUPT_IN); + + result = USB_ERR_STALL; + goto done; + } + + if (result != USB_ERR_OK) { + TRACE_USB_ERROR(result); + goto done; + } + + if (send) { + result = usbdev_blk_out_trnsfer(storage_device, buffer, buffer_size); + + if (result != USB_ERR_OK) { + TRACE_USB_ERROR(result); + goto done; + } + } else { + result = usbdev_dat_in_trnsfer(storage_device, buffer, buffer_size, ENDPOINT_BULK_IN); + + if (result != USB_ERR_OK) { + TRACE_USB_ERROR(result); + goto done; + } + } + + if (sense_codes != NULL) { + result = usbdev_dat_in_trnsfer(storage_device, sense_codes, 2, ENDPOINT_INTERRUPT_IN); + + if (result != USB_ERR_OK) { + TRACE_USB_ERROR(result); + // goto done; + } + } + +done: + critical_end(); + + return result; +} diff --git a/Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.h b/Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.h new file mode 100644 index 00000000..349a7853 --- /dev/null +++ b/Source/HBIOS/ch376-native/source-doc/ufi-drv/usb_cbi.h @@ -0,0 +1,14 @@ +#ifndef __USB_CBI_H__ +#define __USB_CBI_H__ + +#include +#include + +usb_error usb_execute_cbi(device_config *const storage_device, + const uint8_t *const cmd, + const bool send, + const uint16_t buffer_size, + uint8_t *const buffer, + uint8_t *const asc); + +#endif diff --git a/Source/HBIOS/ch376-native/ufi-drv.s b/Source/HBIOS/ch376-native/ufi-drv.s new file mode 100644 index 00000000..bcc735b4 --- /dev/null +++ b/Source/HBIOS/ch376-native/ufi-drv.s @@ -0,0 +1,11 @@ +; Generated File -- not to be modify directly +#IF (!CHNATIVEEZ80) +#include "ch376-native/ufi-drv/class_ufi.c.s" +#ENDIF +#IF (!CHNATIVEEZ80) +#include "ch376-native/ufi-drv/ufi_driver.c.s" +#ENDIF +#include "ch376-native/ufi-drv/ufi-init.c.s" +#IF (!CHNATIVEEZ80) +#include "ch376-native/ufi-drv/usb_cbi.c.s" +#ENDIF diff --git a/Source/HBIOS/ch376-native/ufi-drv/.gitignore b/Source/HBIOS/ch376-native/ufi-drv/.gitignore new file mode 100644 index 00000000..f4cb8488 --- /dev/null +++ b/Source/HBIOS/ch376-native/ufi-drv/.gitignore @@ -0,0 +1 @@ +*.asm diff --git a/Source/HBIOS/ch376-native/ufi-drv/class_ufi.c.s b/Source/HBIOS/ch376-native/ufi-drv/class_ufi.c.s new file mode 100644 index 00000000..0d214c9a --- /dev/null +++ b/Source/HBIOS/ch376-native/ufi-drv/class_ufi.c.s @@ -0,0 +1,666 @@ +; +; Generated from source-doc/ufi-drv/class_ufi.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/ufi-drv/class_ufi.c:14: uint8_t wait_for_device_ready(device_config *const storage_device, uint8_t timeout_counter) { +; --------------------------------- +; Function wait_for_device_ready +; --------------------------------- +_wait_for_device_ready: + push ix + ld ix,0 + add ix,sp + ld hl, -18 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:18: do { + ld c,(ix+6) +l_wait_for_device_ready_00105: +;source-doc/ufi-drv/class_ufi.c:19: memset(&sense, 0, sizeof(sense)); + ld hl,0 + add hl, sp + ld b,$09 +l_wait_for_device_ready_00132: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_wait_for_device_ready_00132 +;source-doc/ufi-drv/class_ufi.c:20: result = ufi_test_unit_ready(storage_device, &sense); + push bc + ld hl,2 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _ufi_test_unit_ready + pop af + pop af + ld a, l + pop bc + ld b, a +;source-doc/ufi-drv/class_ufi.c:22: if ((result == USB_ERR_OK && (sense.sense_key & 15) == 0) || timeout_counter-- == 0) + or a + jr NZ,l_wait_for_device_ready_00104 + ld a,(ix-16) + and $0f + jr Z,l_wait_for_device_ready_00107 +l_wait_for_device_ready_00104: + ld a, c + dec c + or a + jr Z,l_wait_for_device_ready_00107 +;source-doc/ufi-drv/class_ufi.c:25: delay_medium(); + push bc + call _delay_medium + pop bc +;source-doc/ufi-drv/class_ufi.c:27: } while (true); + jr l_wait_for_device_ready_00105 +l_wait_for_device_ready_00107: +;source-doc/ufi-drv/class_ufi.c:29: return result | (sense.sense_key & 15); + ld a,(ix-16) + and $0f + or b + ld l, a +;source-doc/ufi-drv/class_ufi.c:30: } + ld sp, ix + pop ix + ret +__ufi_cmd_request_sense: + DEFB +$03 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$12 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +__ufi_cmd_rd_fmt_caps: + DEFB +$23 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$0c + DEFB +$00 + DEFB +$00 + DEFB +$00 +__ufi_cmd_inquiry: + DEFB +$12 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$24 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +__ufi_cmd_format: + DEFB +$04 + DEFB +$17 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +__ufi_cmd_send_diag: + DEFB +$1d + DEFB +$04 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$00 +;source-doc/ufi-drv/class_ufi.c:32: usb_error ufi_test_unit_ready(device_config *const storage_device, ufi_request_sense_response const *response) { +; --------------------------------- +; Function ufi_test_unit_ready +; --------------------------------- +_ufi_test_unit_ready: + push ix + ld ix,0 + add ix,sp + ld hl, -24 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:35: memset(&ufi_cmd_request_test_unit_ready, 0, sizeof(ufi_test_unit_ready_command)); + ld hl,0 + add hl, sp + ld b,$06 +l_ufi_test_unit_ready_00104: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_ufi_test_unit_ready_00104 +;source-doc/ufi-drv/class_ufi.c:37: usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_test_unit_ready, false, 0, NULL, NULL); + ld hl,$0000 + push hl + push hl + push hl + xor a + push af + inc sp + ld hl,7 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi + ld hl,11 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:40: ufi_cmd_request_sense = _ufi_cmd_request_sense; + ld hl,12 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,__ufi_cmd_request_sense + ldir +;source-doc/ufi-drv/class_ufi.c:43: (uint8_t *)response, NULL); + ld c,(ix+6) + ld b,(ix+7) +;source-doc/ufi-drv/class_ufi.c:42: result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_sense, false, sizeof(ufi_request_sense_response), + ld hl,$0000 + push hl + push bc + ld l,$12 + push hl + xor a + push af + inc sp + ld hl,19 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi +;source-doc/ufi-drv/class_ufi.c:46: return result; +;source-doc/ufi-drv/class_ufi.c:47: } + ld sp,ix + pop ix + ret +;source-doc/ufi-drv/class_ufi.c:49: usb_error ufi_request_sense(device_config *const storage_device, ufi_request_sense_response const *response) { +; --------------------------------- +; Function ufi_request_sense +; --------------------------------- +_ufi_request_sense: + push ix + ld ix,0 + add ix,sp + ld hl, -12 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:51: ufi_cmd_request_sense = _ufi_cmd_request_sense; + ld hl,0 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,__ufi_cmd_request_sense + ldir +;source-doc/ufi-drv/class_ufi.c:53: usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_request_sense, false, sizeof(ufi_request_sense_response), + ld c,(ix+6) + ld b,(ix+7) + ld hl,$0000 + push hl + push bc + ld l,$12 + push hl + xor a + push af + inc sp + ld hl,7 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi +;source-doc/ufi-drv/class_ufi.c:58: return result; +;source-doc/ufi-drv/class_ufi.c:59: } + ld sp,ix + pop ix + ret +;source-doc/ufi-drv/class_ufi.c:61: usb_error ufi_read_frmt_caps(device_config *const storage_device, ufi_format_capacities_response const *response) { +; --------------------------------- +; Function ufi_read_frmt_caps +; --------------------------------- +_ufi_read_frmt_caps: + push ix + ld ix,0 + add ix,sp + ld hl, -24 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:65: ufi_cmd_read_format_capacities = _ufi_cmd_rd_fmt_caps; + ld hl,0 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,__ufi_cmd_rd_fmt_caps + ldir +;source-doc/ufi-drv/class_ufi.c:66: result = usb_execute_cbi(storage_device, (uint8_t *)&ufi_cmd_read_format_capacities, false, 12, (uint8_t *)response, NULL); + ld c,(ix+6) + ld b,(ix+7) + push bc + ld hl,$0000 + push hl + push bc + ld l,$0c + push hl + xor a + push af + inc sp + ld hl,9 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi + pop af + pop af + pop af + pop af + pop af + inc sp + ld a, l + pop bc + ld l, a +;source-doc/ufi-drv/class_ufi.c:69: CHECK(result); + or a + jr NZ,l_ufi_read_frmt_caps_00103 +;source-doc/ufi-drv/class_ufi.c:71: const uint8_t available_length = response->capacity_list_length; + ld l,(ix+6) + ld h,(ix+7) + inc hl + inc hl + inc hl + ld a, (hl) +;source-doc/ufi-drv/class_ufi.c:73: const uint8_t max_length = + cp $25 + jr C,l_ufi_read_frmt_caps_00106 + ld e,$24 + jr l_ufi_read_frmt_caps_00107 +l_ufi_read_frmt_caps_00106: + ld e, a +l_ufi_read_frmt_caps_00107: +;source-doc/ufi-drv/class_ufi.c:77: memcpy(&cmd, &ufi_cmd_read_format_capacities, sizeof(cmd)); + push de + push bc + ld hl,16 + add hl, sp + ex de, hl + ld hl,4 + add hl, sp + ld bc,$000c + ldir + pop bc + pop de +;source-doc/ufi-drv/class_ufi.c:78: cmd.allocation_length[1] = max_length; + ld (ix-4),e +;source-doc/ufi-drv/class_ufi.c:80: result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, false, max_length, (uint8_t *)response, NULL); + ld hl,$0000 + ld d,l + push hl + push bc + push de + xor a + push af + inc sp + ld hl,19 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi + pop af + pop af + pop af + pop af + pop af + inc sp +;source-doc/ufi-drv/class_ufi.c:84: done: +l_ufi_read_frmt_caps_00103: +;source-doc/ufi-drv/class_ufi.c:85: return result; +;source-doc/ufi-drv/class_ufi.c:86: } + ld sp, ix + pop ix + ret +;source-doc/ufi-drv/class_ufi.c:88: usb_error ufi_inquiry(device_config *const storage_device, ufi_inquiry_response const *response) { +; --------------------------------- +; Function ufi_inquiry +; --------------------------------- +_ufi_inquiry: + push ix + ld ix,0 + add ix,sp + ld hl, -12 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:90: ufi_cmd_inquiry = _ufi_cmd_inquiry; + ld hl,0 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,__ufi_cmd_inquiry + ldir +;source-doc/ufi-drv/class_ufi.c:92: usb_error result = + ld c,(ix+6) + ld b,(ix+7) + ld hl,$0000 + push hl + push bc + ld l,$24 + push hl + xor a + push af + inc sp + ld hl,7 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi +;source-doc/ufi-drv/class_ufi.c:97: return result; +;source-doc/ufi-drv/class_ufi.c:98: } + ld sp,ix + pop ix + ret +;source-doc/ufi-drv/class_ufi.c:100: usb_error ufi_read_write_sector(device_config *const storage_device, +; --------------------------------- +; Function ufi_read_write_sector +; --------------------------------- +_ufi_read_write_sector: + push ix + ld ix,0 + add ix,sp + ld hl, -12 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:107: memset(&cmd, 0, sizeof(cmd)); + ld hl,0 + add hl, sp + ld b,$06 +l_ufi_read_write_sector_00113: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_ufi_read_write_sector_00113 +;source-doc/ufi-drv/class_ufi.c:108: cmd.operation_code = send ? $2A : $28; + bit 0,(ix+6) + jr Z,l_ufi_read_write_sector_00104 + ld a,$2a + jr l_ufi_read_write_sector_00105 +l_ufi_read_write_sector_00104: + ld a,$28 +l_ufi_read_write_sector_00105: + ld (ix-12),a +;source-doc/ufi-drv/class_ufi.c:109: cmd.lba[2] = sector_number >> 8; + ld a,(ix+8) + ld (ix-8),a +;source-doc/ufi-drv/class_ufi.c:110: cmd.lba[3] = sector_number & $FF; + ld a,(ix+7) + ld (ix-7),a +;source-doc/ufi-drv/class_ufi.c:111: cmd.transfer_length[1] = sector_count; +;source-doc/ufi-drv/class_ufi.c:113: usb_error result = usb_execute_cbi(storage_device, (uint8_t *)&cmd, send, 512 * sector_count, (uint8_t *)buffer, sense_codes); + ld a,(ix+9) + ld (ix-4),a + add a, a + ld b, a + ld c,$00 + ld l,(ix+12) + ld h,(ix+13) + push hl + ld l,(ix+10) + ld h,(ix+11) + push hl + push bc + ld a,(ix+6) + push af + inc sp + ld hl,7 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi +;source-doc/ufi-drv/class_ufi.c:117: return result; +;source-doc/ufi-drv/class_ufi.c:118: } + ld sp,ix + pop ix + ret +;source-doc/ufi-drv/class_ufi.c:123: * HD | 93h | 1.25 MB | 77 | 2 | 8 | 1232 04D0h | 1024 0400h | +; --------------------------------- +; Function ufi_format +; --------------------------------- +_ufi_format: + push ix + ld ix,0 + add ix,sp + ld hl, -26 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:130: const ufi_format_capacity_descriptor *const format) { + ld hl,2 + add hl, sp + ld b,$06 +l_ufi_format_00104: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_ufi_format_00104 +;source-doc/ufi-drv/class_ufi.c:133: ufi_format_parameter_list parameter_list; + ld hl,14 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,__ufi_cmd_format + ldir +;source-doc/ufi-drv/class_ufi.c:136: ufi_format_command cmd; + ld a,(ix+7) + ld (ix-10),a +;source-doc/ufi-drv/class_ufi.c:137: cmd = _ufi_cmd_format; + ld (ix-8),$00 +;source-doc/ufi-drv/class_ufi.c:138: // memcpy(&cmd, &_ufi_cmd_format, sizeof(cmd)); + ld (ix-4),$0c +;source-doc/ufi-drv/class_ufi.c:140: cmd.track_number = track_number; +;source-doc/ufi-drv/class_ufi.c:141: cmd.interleave[1] = 0; + ld a,(ix+6) + and $01 + or $b0 + ld (ix-23),a +;source-doc/ufi-drv/class_ufi.c:142: cmd.parameter_list_length[1] = sizeof(parameter_list); + ld (ix-22),$00 +;source-doc/ufi-drv/class_ufi.c:143: + ld (ix-21),$08 +;source-doc/ufi-drv/class_ufi.c:144: parameter_list.defect_list_header.status = + ld hl,6 + add hl, sp + ex de, hl + ld l,(ix+8) + ld h,(ix+9) + ld bc,$0008 + ldir +;source-doc/ufi-drv/class_ufi.c:146: parameter_list.defect_list_header.defect_list_length_msb = 0; + ld hl,0 + add hl, sp + push hl + ld hl,4 + add hl, sp + push hl + ld hl,$000c + push hl + ld a,$01 + push af + inc sp + ld hl,21 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi +;source-doc/ufi-drv/class_ufi.c:153: // trace_printf("ufi_format: %d, %02X %02X (len: %d)\r\n", result, sense_codes.bASC, sense_codes.bASCQ, sizeof(parameter_list)); +;source-doc/ufi-drv/class_ufi.c:154: + ld sp,ix + pop ix + ret +;source-doc/ufi-drv/class_ufi.c:156: done: +; --------------------------------- +; Function ufi_send_diagnostics +; --------------------------------- +_ufi_send_diagnostics: + push ix + ld ix,0 + add ix,sp + ld hl, -12 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/class_ufi.c:159: + ld hl,0 + add hl, sp + ex de, hl + ld bc,$000c + ld hl,__ufi_cmd_send_diag + ldir +;source-doc/ufi-drv/class_ufi.c:161: ufi_send_diagnostic_command ufi_cmd_send_diagnostic; + ld hl,$0000 + push hl + push hl + push hl + ld a,$01 + push af + inc sp + ld hl,7 + add hl, sp + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usb_execute_cbi +;source-doc/ufi-drv/class_ufi.c:162: + ld sp,ix + pop ix + ret +;source-doc/ufi-drv/class_ufi.c:164: +; --------------------------------- +; Function convert_from_msb_first +; --------------------------------- +_convert_from_msb_first: + push ix + ld ix,0 + add ix,sp + push af + push af +;source-doc/ufi-drv/class_ufi.c:166: } + ld hl,0 + add hl, sp + ex de, hl +;source-doc/ufi-drv/class_ufi.c:167: + ld l,(ix+4) + ld h,(ix+5) + inc hl + inc hl + inc hl +;source-doc/ufi-drv/class_ufi.c:169: uint32_t result; + ld a, (hl) + dec hl + ld (de), a + inc de +;source-doc/ufi-drv/class_ufi.c:170: uint8_t *p_output = ((uint8_t *)&result); + ld a, (hl) + dec hl + ld (de), a + inc de +;source-doc/ufi-drv/class_ufi.c:171: const uint8_t *p_input = buffer + 3; + ld a, (hl) + ld (de), a + inc de +;source-doc/ufi-drv/class_ufi.c:172: + dec hl + ld a, (hl) + ld (de), a +;source-doc/ufi-drv/class_ufi.c:174: *p_output++ = *p_input--; + pop hl + push hl + ld e,(ix-2) + ld d,(ix-1) +;source-doc/ufi-drv/class_ufi.c:175: *p_output++ = *p_input--; + ld sp, ix + pop ix + ret diff --git a/Source/HBIOS/ch376-native/ufi-drv/ufi-init.c.s b/Source/HBIOS/ch376-native/ufi-drv/ufi-init.c.s new file mode 100644 index 00000000..f3297b38 --- /dev/null +++ b/Source/HBIOS/ch376-native/ufi-drv/ufi-init.c.s @@ -0,0 +1,139 @@ +; +; Generated from source-doc/ufi-drv/ufi-init.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/ufi-drv/ufi-init.c:8: void chufi_init(void) { +; --------------------------------- +; Function chufi_init +; --------------------------------- +_chufi_init: + push ix + ld ix,0 + add ix,sp + push af +;source-doc/ufi-drv/ufi-init.c:11: do { + ld (ix-1),$01 +l_chufi_init_00103: +;source-doc/ufi-drv/ufi-init.c:12: usb_device_type t = usb_get_device_type(index); + ld e,(ix-1) + ld d,$00 + push de + push de + call _usb_get_device_type + pop af + pop de +;source-doc/ufi-drv/ufi-init.c:14: if (t == USB_IS_FLOPPY) { + dec l + jr NZ,l_chufi_init_00104 +;source-doc/ufi-drv/ufi-init.c:15: const uint8_t dev_index = find_storage_dev(); // dev_index == -1 (no more left) should never happen + push de + call _find_storage_dev + ld (ix-2),l + pop de +;source-doc/ufi-drv/ufi-init.c:17: hbios_usbstore_devs[dev_index].drive_index = dev_index + 1; + ld l,(ix-2) + ld h,$00 + add hl, hl + ld bc,_hbios_usbstore_devs + add hl, bc + ld a,(ix-2) + inc a + ld (hl),a +;source-doc/ufi-drv/ufi-init.c:18: hbios_usbstore_devs[dev_index].usb_device = index; + inc hl + ld a,(ix-1) + ld (hl),a + dec hl +;source-doc/ufi-drv/ufi-init.c:20: print_string("\r\nUSB: FLOPPY @ $"); + push hl + push de + ld hl,ufi_init_str_0 + call _print_string + pop de + pop hl +;source-doc/ufi-drv/ufi-init.c:21: print_uint16(index); + push hl + ex de, hl + call _print_uint16 +;source-doc/ufi-drv/ufi-init.c:22: print_string(":$"); + ld hl,ufi_init_str_1 + call _print_string + pop hl +;source-doc/ufi-drv/ufi-init.c:23: print_uint16(dev_index); + ld e,(ix-2) + ld d,$00 + push hl + ex de, hl + call _print_uint16 +;source-doc/ufi-drv/ufi-init.c:24: print_string(" $"); + ld hl,ufi_init_str_2 + call _print_string + pop hl +;source-doc/ufi-drv/ufi-init.c:25: dio_add_entry(ch_ufi_fntbl, &hbios_usbstore_devs[dev_index]); + ex de, hl + ld hl,_ch_ufi_fntbl + call _dio_add_entry +l_chufi_init_00104: +;source-doc/ufi-drv/ufi-init.c:28: } while (++index != MAX_NUMBER_OF_DEVICES + 1); + inc (ix-1) + ld a,(ix-1) + sub $07 + jr NZ,l_chufi_init_00103 +;source-doc/ufi-drv/ufi-init.c:29: } + ld sp, ix + pop ix + ret +ufi_init_str_0: + DEFB $0d + DEFB $0a + DEFM "USB: FLOPPY @ $" + DEFB $00 +ufi_init_str_1: + DEFM ":$" + DEFB $00 +ufi_init_str_2: + DEFM " $" + DEFB $00 diff --git a/Source/HBIOS/ch376-native/ufi-drv/ufi_driver.c.s b/Source/HBIOS/ch376-native/ufi-drv/ufi_driver.c.s new file mode 100644 index 00000000..5c2459e7 --- /dev/null +++ b/Source/HBIOS/ch376-native/ufi-drv/ufi_driver.c.s @@ -0,0 +1,373 @@ +; +; Generated from source-doc/ufi-drv/ufi_driver.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/ufi-drv/ufi_driver.c:6: uint32_t usb_ufi_get_cap(const uint16_t dev_index) { +; --------------------------------- +; Function usb_ufi_get_cap +; --------------------------------- +_usb_ufi_get_cap: + push ix + ld ix,0 + add ix,sp + ld hl, -72 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/ufi_driver.c:7: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config +;source-doc/ufi-drv/ufi_driver.c:10: memset(&response, 0, sizeof(ufi_format_capacities_response)); + ld hl,0 + add hl, sp + ld b,$12 +l_usb_ufi_get_cap_00112: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_usb_ufi_get_cap_00112 +;source-doc/ufi-drv/ufi_driver.c:12: wait_for_device_ready(dev, 25); + push de + ld a,$19 + push af + inc sp + push de + call _wait_for_device_ready + pop af + inc sp + pop de +;source-doc/ufi-drv/ufi_driver.c:16: ufi_inquiry(dev, &inquiry); + push de + ld hl,38 + add hl, sp + push hl + push de + call _ufi_inquiry + pop af + pop af + pop de +;source-doc/ufi-drv/ufi_driver.c:18: wait_for_device_ready(dev, 15); + push de + ld a,$0f + push af + inc sp + push de + call _wait_for_device_ready + pop af + inc sp + pop de +;source-doc/ufi-drv/ufi_driver.c:20: const usb_error result = ufi_read_frmt_caps(dev, &response); + ld hl,0 + add hl, sp + push hl + push de + call _ufi_read_frmt_caps + pop af + pop af + ld a, l +;source-doc/ufi-drv/ufi_driver.c:21: if (result != USB_ERR_OK) + or a + jr Z,l_usb_ufi_get_cap_00102 +;source-doc/ufi-drv/ufi_driver.c:22: return 0; + ld hl,$0000 + ld e, l + ld d, l + jr l_usb_ufi_get_cap_00103 +l_usb_ufi_get_cap_00102: +;source-doc/ufi-drv/ufi_driver.c:24: return convert_from_msb_first(response.descriptors[0].number_of_blocks); + ld hl,4 + add hl, sp + push hl + call _convert_from_msb_first + pop af +l_usb_ufi_get_cap_00103: +;source-doc/ufi-drv/ufi_driver.c:25: } + ld sp, ix + pop ix + ret +;source-doc/ufi-drv/ufi_driver.c:27: usb_error usb_ufi_read(const uint16_t dev_index, uint8_t *const buffer) { +; --------------------------------- +; Function usb_ufi_read +; --------------------------------- +_usb_ufi_read: + push ix + ld ix,0 + add ix,sp + ld hl, -20 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/ufi_driver.c:28: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config +;source-doc/ufi-drv/ufi_driver.c:30: if (wait_for_device_ready((device_config *)dev, 20) != 0) + push de + ld c,e + ld b,d + push de + ld a,$14 + push af + inc sp + push bc + call _wait_for_device_ready + pop af + inc sp + ld a, l + pop de + pop bc + or a + jr Z,l_usb_ufi_read_00102 +;source-doc/ufi-drv/ufi_driver.c:31: return -1; // Not READY! + ld l,$ff + jr l_usb_ufi_read_00109 +l_usb_ufi_read_00102: +;source-doc/ufi-drv/ufi_driver.c:36: memset(&sense_codes, 0, sizeof(sense_codes)); + ld hl,0 + add hl, sp + xor a + ld (hl), a + inc hl + ld (hl), a +;source-doc/ufi-drv/ufi_driver.c:38: if (ufi_read_write_sector((device_config *)dev, false, dev->current_lba, 1, buffer, (uint8_t *)&sense_codes) != USB_ERR_OK) + ld hl,12 + add hl, de + ld e, (hl) + inc hl + ld d, (hl) + push bc + ld hl,2 + add hl, sp + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + ld a,$01 + push af + inc sp + push de + xor a + push af + inc sp + push bc + call _ufi_read_write_sector + pop af + pop af + pop af + pop af + pop af + ld a, l + pop bc + or a + jr Z,l_usb_ufi_read_00104 +;source-doc/ufi-drv/ufi_driver.c:39: return -1; // general error + ld l,$ff + jr l_usb_ufi_read_00109 +l_usb_ufi_read_00104: +;source-doc/ufi-drv/ufi_driver.c:42: memset(&response, 0, sizeof(response)); + push bc + ld hl,4 + add hl, sp + ld b,$09 +l_usb_ufi_read_00139: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_usb_ufi_read_00139 + pop bc +;source-doc/ufi-drv/ufi_driver.c:44: if ((result = ufi_request_sense((device_config *)dev, &response)) != USB_ERR_OK) + ld hl,2 + add hl, sp + push hl + push bc + call _ufi_request_sense + pop af + pop af + ld a, l + or a + jr Z,l_usb_ufi_read_00106 +;source-doc/ufi-drv/ufi_driver.c:45: return -1; // error + ld l,$ff + jr l_usb_ufi_read_00109 +l_usb_ufi_read_00106: +;source-doc/ufi-drv/ufi_driver.c:49: const uint8_t sense_key = response.sense_key & 15; + ld a,(ix-16) + and $0f + jr Z,l_usb_ufi_read_00108 +;source-doc/ufi-drv/ufi_driver.c:51: if (sense_key != 0) +;source-doc/ufi-drv/ufi_driver.c:52: return -1; + ld l,$ff + jr l_usb_ufi_read_00109 +l_usb_ufi_read_00108: +;source-doc/ufi-drv/ufi_driver.c:54: return USB_ERR_OK; + ld l,$00 +l_usb_ufi_read_00109: +;source-doc/ufi-drv/ufi_driver.c:55: } + ld sp, ix + pop ix + ret +;source-doc/ufi-drv/ufi_driver.c:57: usb_error usb_ufi_write(const uint16_t dev_index, uint8_t *const buffer) { +; --------------------------------- +; Function usb_ufi_write +; --------------------------------- +_usb_ufi_write: + push ix + ld ix,0 + add ix,sp + ld hl, -20 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/ufi_driver.c:58: device_config_storage *const dev = (device_config_storage *)get_usb_device_config(dev_index); + ld a,(ix+4) + call _get_usb_device_config +;source-doc/ufi-drv/ufi_driver.c:60: if (wait_for_device_ready((device_config *)dev, 20) != 0) + push de + ld c,e + ld b,d + push de + ld a,$14 + push af + inc sp + push bc + call _wait_for_device_ready + pop af + inc sp + ld a, l + pop de + pop bc + or a + jr Z,l_usb_ufi_write_00102 +;source-doc/ufi-drv/ufi_driver.c:61: return -1; // Not READY! + ld l,$ff + jr l_usb_ufi_write_00109 +l_usb_ufi_write_00102: +;source-doc/ufi-drv/ufi_driver.c:65: memset(&sense_codes, 0, sizeof(sense_codes)); + ld hl,0 + add hl, sp + xor a + ld (hl), a + inc hl + ld (hl), a +;source-doc/ufi-drv/ufi_driver.c:66: if ((ufi_read_write_sector((device_config *)dev, true, dev->current_lba, 1, buffer, (uint8_t *)&sense_codes)) != USB_ERR_OK) { + ld hl,12 + add hl, de + ld e, (hl) + inc hl + ld d, (hl) + push bc + ld hl,2 + add hl, sp + push hl + ld l,(ix+6) + ld h,(ix+7) + push hl + ld a,$01 + push af + inc sp + push de + ld a,$01 + push af + inc sp + push bc + call _ufi_read_write_sector + pop af + pop af + pop af + pop af + pop af + ld a, l + pop bc + or a + jr Z,l_usb_ufi_write_00104 +;source-doc/ufi-drv/ufi_driver.c:67: return -1; + ld l,$ff + jr l_usb_ufi_write_00109 +l_usb_ufi_write_00104: +;source-doc/ufi-drv/ufi_driver.c:71: memset(&response, 0, sizeof(response)); + push bc + ld hl,4 + add hl, sp + ld b,$09 +l_usb_ufi_write_00139: + xor a + ld (hl), a + inc hl + ld (hl), a + inc hl + djnz l_usb_ufi_write_00139 + pop bc +;source-doc/ufi-drv/ufi_driver.c:73: if ((ufi_request_sense((device_config *)dev, &response)) != USB_ERR_OK) { + ld hl,2 + add hl, sp + push hl + push bc + call _ufi_request_sense + pop af + pop af + ld a, l + or a + jr Z,l_usb_ufi_write_00106 +;source-doc/ufi-drv/ufi_driver.c:74: return -1; + ld l,$ff + jr l_usb_ufi_write_00109 +l_usb_ufi_write_00106: +;source-doc/ufi-drv/ufi_driver.c:79: const uint8_t sense_key = response.sense_key & 15; + ld a,(ix-16) + and $0f + jr Z,l_usb_ufi_write_00108 +;source-doc/ufi-drv/ufi_driver.c:81: if (sense_key != 0) +;source-doc/ufi-drv/ufi_driver.c:82: return -1; + ld l,$ff + jr l_usb_ufi_write_00109 +l_usb_ufi_write_00108: +;source-doc/ufi-drv/ufi_driver.c:84: return USB_ERR_OK; + ld l,$00 +l_usb_ufi_write_00109: +;source-doc/ufi-drv/ufi_driver.c:85: } + ld sp, ix + pop ix + ret diff --git a/Source/HBIOS/ch376-native/ufi-drv/usb_cbi.c.s b/Source/HBIOS/ch376-native/ufi-drv/usb_cbi.c.s new file mode 100644 index 00000000..8620ec83 --- /dev/null +++ b/Source/HBIOS/ch376-native/ufi-drv/usb_cbi.c.s @@ -0,0 +1,219 @@ +; +; Generated from source-doc/ufi-drv/usb_cbi.c.asm -- not to be modify directly +; +; +;-------------------------------------------------------- +; File Created by SDCC : free open source ISO C Compiler +; Version 4.5.0 #15248 (Linux) +;-------------------------------------------------------- +; Processed by Z88DK +;-------------------------------------------------------- + + +;-------------------------------------------------------- +; Public variables in this module +;-------------------------------------------------------- +;-------------------------------------------------------- +; Externals used +;-------------------------------------------------------- +;-------------------------------------------------------- +; special function registers +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; ram data +;-------------------------------------------------------- + +#IF 0 + +; .area _INITIALIZED removed by z88dk + +_cbi2_adsc: + DEFS 8 + +#ENDIF + +;-------------------------------------------------------- +; absolute external ram data +;-------------------------------------------------------- +;-------------------------------------------------------- +; global & static initialisations +;-------------------------------------------------------- +;-------------------------------------------------------- +; Home +;-------------------------------------------------------- +;-------------------------------------------------------- +; code +;-------------------------------------------------------- +;source-doc/ufi-drv/usb_cbi.c:10: usb_error usb_execute_cbi(device_config *const storage_device, +; --------------------------------- +; Function usb_execute_cbi +; --------------------------------- +_usb_execute_cbi: + push ix + ld ix,0 + add ix,sp + ld hl, -8 + add hl, sp + ld sp, hl +;source-doc/ufi-drv/usb_cbi.c:17: const uint8_t interface_number = storage_device->interface_number; + ld l,(ix+4) + ld h,(ix+5) + ld c,l + ld b,h + inc hl + inc hl + ld e, (hl) +;source-doc/ufi-drv/usb_cbi.c:20: adsc = cbi2_adsc; + push de + push bc + ld hl,4 + add hl, sp + ex de, hl + ld bc,$0008 + ld hl,_cbi2_adsc + ldir + pop bc + pop de +;source-doc/ufi-drv/usb_cbi.c:21: adsc.bIndex[0] = interface_number; + ld (ix-4),e +;source-doc/ufi-drv/usb_cbi.c:23: critical_begin(); + push bc + call _critical_begin + pop bc +;source-doc/ufi-drv/usb_cbi.c:25: result = usbdev_control_transfer(storage_device, &adsc, (uint8_t *const)cmd); + ld l,(ix+6) + ld h,(ix+7) + push hl + ld hl,2 + add hl, sp + push hl + push bc + call _usbdev_control_transfer + pop af + pop af + pop af +;source-doc/ufi-drv/usb_cbi.c:27: if (result == USB_ERR_STALL) { + ld a, l + sub $02 + jr NZ,l_usb_execute_cbi_00104 +;source-doc/ufi-drv/usb_cbi.c:28: if (sense_codes != NULL) + ld a,(ix+14) + or (ix+13) + jr Z,l_usb_execute_cbi_00102 +;source-doc/ufi-drv/usb_cbi.c:29: usbdev_dat_in_trnsfer(storage_device, sense_codes, 2, ENDPOINT_INTERRUPT_IN); + ld a,$02 + push af + inc sp + ld hl,$0002 + push hl + ld l,(ix+13) + ld h,(ix+14) + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usbdev_dat_in_trnsfer + ld hl,7 + add hl, sp + ld sp, hl +l_usb_execute_cbi_00102: +;source-doc/ufi-drv/usb_cbi.c:31: result = USB_ERR_STALL; + ld l,$02 +;source-doc/ufi-drv/usb_cbi.c:32: goto done; + jr l_usb_execute_cbi_00116 +l_usb_execute_cbi_00104: +;source-doc/ufi-drv/usb_cbi.c:35: if (result != USB_ERR_OK) { + ld a, l + or a + jr NZ,l_usb_execute_cbi_00116 +;source-doc/ufi-drv/usb_cbi.c:40: if (send) { + bit 0,(ix+8) + jr Z,l_usb_execute_cbi_00112 +;source-doc/ufi-drv/usb_cbi.c:41: result = usbdev_blk_out_trnsfer(storage_device, buffer, buffer_size); + ld l,(ix+9) + ld h,(ix+10) + push hl + ld l,(ix+11) + ld h,(ix+12) + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usbdev_blk_out_trnsfer + pop af + pop af + pop af +;source-doc/ufi-drv/usb_cbi.c:43: if (result != USB_ERR_OK) { + ld a, l + or a + jr Z,l_usb_execute_cbi_00113 +;source-doc/ufi-drv/usb_cbi.c:45: goto done; + jr l_usb_execute_cbi_00116 +l_usb_execute_cbi_00112: +;source-doc/ufi-drv/usb_cbi.c:48: result = usbdev_dat_in_trnsfer(storage_device, buffer, buffer_size, ENDPOINT_BULK_IN); + ld a,$01 + push af + inc sp + ld l,(ix+9) + ld h,(ix+10) + push hl + ld l,(ix+11) + ld h,(ix+12) + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usbdev_dat_in_trnsfer + pop af + pop af + pop af + inc sp +;source-doc/ufi-drv/usb_cbi.c:50: if (result != USB_ERR_OK) { + ld a, l + or a + jr NZ,l_usb_execute_cbi_00116 +;source-doc/ufi-drv/usb_cbi.c:52: goto done; +l_usb_execute_cbi_00113: +;source-doc/ufi-drv/usb_cbi.c:56: if (sense_codes != NULL) { + ld a,(ix+14) + or (ix+13) + jr Z,l_usb_execute_cbi_00116 +;source-doc/ufi-drv/usb_cbi.c:57: result = usbdev_dat_in_trnsfer(storage_device, sense_codes, 2, ENDPOINT_INTERRUPT_IN); + ld a,$02 + push af + inc sp + ld hl,$0002 + push hl + ld l,(ix+13) + ld h,(ix+14) + push hl + ld l,(ix+4) + ld h,(ix+5) + push hl + call _usbdev_dat_in_trnsfer + pop af + pop af + pop af + inc sp +;source-doc/ufi-drv/usb_cbi.c:65: done: +l_usb_execute_cbi_00116: +;source-doc/ufi-drv/usb_cbi.c:66: critical_end(); + push hl + call _critical_end + pop hl +;source-doc/ufi-drv/usb_cbi.c:68: return result; +;source-doc/ufi-drv/usb_cbi.c:69: } + ld sp, ix + pop ix + ret +_cbi2_adsc: + DEFB +$21 + DEFB +$00 + DEFB +$00 + DEFB +$00 + DEFB +$ff + DEFB +$00 + DEFW +$000c diff --git a/Source/HBIOS/ch376.asm b/Source/HBIOS/ch376.asm new file mode 100644 index 00000000..d9abbe6f --- /dev/null +++ b/Source/HBIOS/ch376.asm @@ -0,0 +1,65 @@ +; +;================================================================================================== +; CH376 NATIVE USB DRIVER +;================================================================================================== +; + +#DEFINE DEFM .DB +#DEFINE DEFB .DB +#DEFINE DEFW .DW + +_CH376_DAT_PORT_ADDR .EQU _CH376_DATA_PORT +_CH376_CMD_PORT_ADDR .EQU _CH376_COMMAND_PORT +_USB_MOD_LEDS_ADDR .EQU _USB_MODULE_LEDS + +_print_string .EQU PRTSTR + +_print_hex: + ld a, l + JP PRTHEXBYTE + +_dio_add_entry: + LD B, H + LD C, L + JP DIO_ADDENT ; ADD ENTRY TO GLOBAL DISK DEV TABLE + +#IF (CHNATIVEEZ80) + +#include "./ch376-native/ez80-firmware.asm" + +_ch376_driver_version: + .DB ",F); $", 0 + +#ELSE + +_ch376_driver_version: + .DB ",W); $", 0 + +_delay: + push af + call DELAY + pop af + ret + +_delay_20ms: + LD DE, 1250 + JP VDELAY +; +; DELAY approx 60ms +_delay_short: + LD DE, 3750 + JP VDELAY +; +; DELAY approx 1/2 second +_delay_medium .EQU LDELAY + +#include "./ch376-native/cruntime.asm" +#include "./ch376-native/base-drv.asm" +#ENDIF + +#include "./ch376-native/print.asm" +#include "./ch376-native/base-drv.s" + +CHNATIVE_INIT .EQU _chnative_init +CHNATIVE_INITF .EQU _chnative_init_force + diff --git a/Source/HBIOS/ch376kyb.asm b/Source/HBIOS/ch376kyb.asm new file mode 100644 index 00000000..bf552ea7 --- /dev/null +++ b/Source/HBIOS/ch376kyb.asm @@ -0,0 +1,151 @@ +; +;================================================================================================== +; CH376 NATIVE USB KEYBOARD DRIVER +;================================================================================================== +; +; This driver is designed to work within the TMS video driver for a CRT solution. + + +#IF (!CHNATIVEENABLE) + .ECHO "*** TMSMODE: TMSMODE_MSXUKY REQUIRES CHNATIVEENABLE***\n" + !!!!! *** TMSMODE: TMSMODE_MSXUKY REQUIRES CHNATIVEENABLE*** +_usb_kyb_status: +_usb_kyb_flush: +#ENDIF + + +#DEFINE DEFM .DB +#DEFINE DEFB .DB +#DEFINE DEFW .DW + +#IF (!CHNATIVEEZ80) +#IF (SYSTIM == TM_NONE) + .ECHO "*** ERROR: MKY REQUIRES SYSTEM TIMER -- NONE CONFIGURED!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +#ENDIF + +#include "./ch376-native/keyboard.s" + +#IF (CHNATIVEEZ80) +CHUKB_INIT .EQU _keyboard_init + +#ELSE +; COUNT FOR INTERRUPT HANDLER TO TRIGGER KEYBOARD SCANNER (EG: SCAN KEYBOARD ONLY EVERY 2ND INTERRUPT (2/60)) +SCAN_INT_PERIOD: .EQU 2 + + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + .DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +UKY_INTSTK: ; 128 bytes for keyboard interrupt stack - need ~52 bytes??? + +CHUKB_INIT: + CALL _keyboard_init + OR A + RET Z + + ; INSTALL INTERRUPT HANDLER + LD HL, (VEC_TICK+1) + LD (VEC_CHUKB_TICK+1), HL + + LD HL, CHUKB_TICK + LD (VEC_TICK+1), HL + + RET + +CHUKB_TICK: + LD A, SCAN_INT_PERIOD ; SCAN THE KEYBOARD EVERY 'SCAN_INT_PERIOD' INTERRUPTS. +UKY_SCNCNT .EQU $ - 1 + DEC A + LD (UKY_SCNCNT), A + JP NZ, HB_TICK + + LD A, SCAN_INT_PERIOD + LD (UKY_SCNCNT), A + + ; we gonna need a bigger stack + + LD (UKY_INT_SP),SP ; SAVE ORIGINAL STACK FRAME + LD SP,UKY_INTSTK ; USE DEDICATED INT STACK FRAME IN HI MEM + + CALL _usb_kyb_tick + + LD SP, $FFFF ; RESTORE ORIGINAL STACK FRAME +UKY_INT_SP .EQU $ - 2 +; + + +VEC_CHUKB_TICK: + JP HB_TICK + +#ENDIF + +; ### Function 0x4C -- Keyboard Status (VDAKST) +; +; Inputs: +; None +; +; Outputs: +; A: Status / Codes Pending +; +; Return a count of the number of key Codes Pending (A) in the keyboard buffer. +; If it is not possible to determine the actual number in the buffer, it is +; acceptable to return 1 to indicate there are key codes available to read and +; 0 if there are none available. +; The value returned in register A is used as both a Status (A) code and the +; return value. Negative values (bit 7 set) indicate a standard HBIOS result +; (error) code. Otherwise, the return value represents the number of key codes +; pending. +; +UKY_STAT: .EQU _usb_kyb_status + +; ### Function 0x4D -- Video Keyboard Flush (VDAKFL) +; +; Inputs: +; None +; +; Outputs: +; A: standard HBIOS result code +; +; Purged and all contents discarded. The Status (A) is a standard HBIOS result code. +; +UKY_FLUSH .EQU _usb_kyb_flush + +; +; ### Function 0x4E -- Video Keyboard Read (VDAKRD) +; +; Inputs: +; None +; +; Outputs: +; A: Status +; E: Keycode +; +; Read the next key data from the keyboard. If a buffer is used, return the next key code in the buffer. +; If no key data is available, this function will wait indefinitely for a key press. The Status (A) is a +; standard HBIOS result code. +; +; The Keycode (E) is generally returned as appropriate ASCII values, if possible. Special keys, like +; function keys and arrows, are returned as reserved codes. +; +UKY_READ: + CALL _usb_kyb_read + LD A, H + OR A + JR NZ, UKY_READ + LD E, L + XOR A + RET diff --git a/Source/HBIOS/ch376scsi.asm b/Source/HBIOS/ch376scsi.asm new file mode 100644 index 00000000..cd5aa873 --- /dev/null +++ b/Source/HBIOS/ch376scsi.asm @@ -0,0 +1,318 @@ +; +;================================================================================================== +; CH376 NATIVE MASS STORAGE DRIVER +;================================================================================================== +; + +#include "./ch376-native/scsi-drv.s" + + ; find and mount all Mass Storage USB devices +CHSCSI_INIT .EQU _chscsi_init + +; DRIVER FUNCTION TABLE +; +_ch_scsi_fntbl +CH_SCSI_FNTBL: + .DW CH_SCSI_STATUS + .DW CH_SCSI_RESET + .DW CH_SCSI_SEEK + .DW CH_SCSI_READ + .DW CH_SCSI_WRITE + .DW CH_SCSI_VERIFY + .DW CH_SCSI_FORMAT + .DW CH_SCSI_DEVICE + .DW CH_SCSI_MEDIA + .DW CH_SCSI_DEFMED + .DW CH_SCSI_CAP + .DW CH_SCSI_GEOM +#IF (($ - CH_SCSI_FNTBL) != (DIO_FNCNT * 2)) + .ECHO "*** INVALID CH_SCSI_FNTBL FUNCTION TABLE ***\n" +#ENDIF + +CH_SCSI_STATUS: + XOR A + RET + +CH_SCSI_RESET: + XOR A + RET + +; ### Function 0x12 -- Disk Seek (DIOSEEK) +; +; Inputs: +; IY: device config pointer +; DEHL: Sector Address +; +; Outputs: +; A: Status +; +; This function will set the desired sector to be used for the next I/O +; operation. The returned Status (A) is a standard HBIOS result code. +; +; The double-word Sector Address (DEHL) can represent either a Logical +; Block Address (LBA) or a Cylinder/Head/Sector (CHS). Bit 7 of D is +; set (1) for LBA mode and cleared (0) for CHS mode. +; +; For LBA mode operation, the high bit is set and the rest of the +; double-word is then treated as the logical sector address. +; +; For CHS mode operation, the Sector Address (DEHL) registers are +; interpreted as: D=Head, E=Sector, and HL=Track. All values (including +; sector) are 0 relative. +; +CH_SCSI_SEEK: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + BIT 7,D ; CHECK FOR LBA FLAG + CALL Z,HB_CHS2LBA ; CLEAR MEANS CHS, CONVERT TO LBA + RES 7,D ; CLEAR FLAG REGARDLESS (DOES NO HARM IF ALREADY LBA) + + PUSH DE + PUSH HL + PUSH IY + CALL _usb_scsi_seek + POP IY + POP HL + POP DE + + XOR A + RET +; +; ### Function 0x13 -- Disk Read (DIOREAD) +; +; Inputs +; IY: device config pointer +; D: Buffer Bank ID +; E: Sector Count +; HL: Buffer Address +; +; Outputs +; A: Status +; E: Sectors Read +; +; Read Sector Count (E) sectors into the buffer located in Buffer Bank ID (D) +; at Buffer Address (HL) starting at the Current Sector. The returned +; Status (A) is a standard HBIOS result code. +; +CH_SCSI_READ: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR + + ; call scsi_read(IY, HL); + ; HL = HL + 512 + PUSH HL + PUSH IY + CALL _usb_scsi_read + LD A, L + POP IY + POP HL + LD BC, 512 + ADD HL, BC + OR A + RET +; +; ### Function 0x14 -- Disk Write (DIOWRITE) +; +; Inputs +; IY: device config pointer +; D: Buffer Bank ID +; E: Sector Count +; HL: Buffer Address +; +; Outputs +; A: Status +; E: Sectors Written +; +; Write Sector Count (E) sectors from the buffer located in Buffer Bank ID (D) +; at Buffer Address (HL) starting at the Current Sector. The returned +; Status (A) is a standard HBIOS result code. +; +CH_SCSI_WRITE: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR + + ; call scsi_write(IY, HL); + ; HL = HL + 512 + PUSH HL + PUSH IY + CALL _usb_scsi_write + LD A, L + POP IY + POP HL + LD BC, 512 + ADD HL, BC + OR A + RET + +CH_SCSI_VERIFY: +CH_SCSI_FORMAT: + LD A, $FF + OR A + RET +; +; ### Function 0x17 -- Disk Device (DIODEVICE) +; +; Inputs +; IY: device config pointer +; +; Outputs +; A: Status +; C: Device Attributes +; D: Device Type (DIODEV_USB) +; E: Device Number (1) +; H: Device Unit Mode (0) +; L: Device I/O Base Address +; +; Reports device information. The Status (A) is a standard +; HBIOS result code. +; +; The Device Attribute (C): +; +; | **Bits** | **Definition** | +; |---------:|--------------------------------------------------| +; | 7 | Floppy | +; | 6 | Removable | +; | 5 | High Capacity (>8 MB) | +; +; Low Capacity Devices?? +; +; | **Bits** | **Definition** | +; |---------:|--------------------------------------------------| +; | 4-3 | Form Factor: 0=8", 1=5.25", 2=3.5", 3=Other | +; | 2 | Sides: 0=SS, 1=DS | +; | 1-0 | Density: 0=SD, 1=DD, 2=HD, 3=ED | +; +; High Capacity Devices +; +; | **Bits** | **Definition** | +; |---------:|--------------------------------------------------| +; | 4 | LBA Capable | +; | 3-0 | Media Type: 0=Hard Disk, 1=CF, 2=SD, 3=USB, | +; | | 4=ROM, 5=RAM, 6=RAMF, 7=FLASH, 8=CD-ROM, | +; | | 9=Cartridge, 10=usb-scsi, 11=usb-ufi | +; +CH_SCSI_DEVICE: + LD C, %00111010 + LD D, DIODEV_USB + LD E, (IY+0) ; drive_index + DEC E + LD HL, 0 + XOR A + RET +; +; ### Function 0x18 -- Disk Media (DIOMEDIA) +; +; Inputs +; IY: device config pointer +; E: Flags +; +; Outputs +; A: Status +; E: Media ID +; +; Report the Media ID (E) for the for media. If bit 0 of Flags (E) is set, +; then media discovery or verification will be performed. The Status +; (A) is a standard HBIOS result code. If there is no media in device, +; function will return an error status. +; +CH_SCSI_MEDIA: + LD E, MID_HD ;todo verify device still active? + XOR A + RET + +CH_SCSI_DEFMED: + LD A, $FF + OR A + RET +; +; ### Function 0x1A -- Disk Capacity (DIOCAPACITY) +; +; Inputs +; IY: device config pointer +; +; Outputs +; A: Status +; DEHL: Sector Count +; BC: Block Size +; +; +; Report the current media capacity information. +; +; +CH_SCSI_CAP: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + PUSH IX + LD IX, -8 ; reserve 8 bytes for + ADD IX, SP ; scsi_read_capacity_result + LD SP, IX + + PUSH IX + PUSH IY + CALL _usb_scsi_read_capacity + POP IY + POP IX + + LD D, (IX) ; response.number_of_blocks[0] + LD E, (IX+1) ; response.number_of_blocks[1] + LD H, (IX+2) ; response.number_of_blocks[2] + LD L, (IX+3) ; response.number_of_blocks[3] + LD B, (IX+6) ; response.block_size[2] + LD C, (IX+7) ; response.block_size[3] + + LD IX, 8 + ADD IX, SP + LD SP, IX + POP IX + + XOR A ; todo determine a drive status + RET +; +; ### Function 0x1B -- Disk Geometry (DIOGEOMETRY) +; +; Inputs +; IY: device config pointer +; +; Outputs +; A: Status +; D: Heads +; E: Sectors +; HL: Cylinder Count +; BC: Block Size +; +; Report the simulated geometry for the media. The Status (A) is a +; standard HBIOS result code. If the media is unknown, an error will be returned. +; +; ** Does not appear to be used?? +; +CH_SCSI_GEOM: + ; FOR LBA, WE SIMULATE CHS ACCESS USING 16 HEADS AND 16 SECTORS + ; RETURN HS:CC -> DE:HL, SET HIGH BIT OF D TO INDICATE LBA CAPABLE + CALL CH_SCSI_CAP ; GET TOTAL BLOCKS IN DE:HL, BLOCK SIZE TO BC + LD L,H ; DIVIDE BY 256 FOR # TRACKS + LD H,E ; ... HIGH BYTE DISCARDED, RESULT IN HL + LD D,16 | $80 ; HEADS / CYL = 16, SET LBA CAPABILITY BIT + LD E,16 ; SECTORS / TRACK = 16 + RET ; DONE, A STILL HAS CHUSB_CAP STATUS diff --git a/Source/HBIOS/ch376ufi.asm b/Source/HBIOS/ch376ufi.asm new file mode 100644 index 00000000..5c005930 --- /dev/null +++ b/Source/HBIOS/ch376ufi.asm @@ -0,0 +1,323 @@ +; +;================================================================================================== +; CH376 NATIVE MASS STORAGE DRIVER +;================================================================================================== +; + +#include "./ch376-native/ufi-drv.s" +_ufi_seek .EQU _usb_scsi_seek + + ; find and mount all floppy USB drives +CHUFI_INIT .EQU _chufi_init + +; DRIVER FUNCTION TABLE +; +_ch_ufi_fntbl +CH_UFI_FNTBL: + .DW CH_UFI_STATUS + .DW CH_UFI_RESET + .DW CH_UFI_SEEK + .DW CH_UFI_READ + .DW CH_UFI_WRITE + .DW CH_UFI_VERIFY + .DW CH_UFI_FORMAT + .DW CH_UFI_DEVICE + .DW CH_UFI_MEDIA + .DW CH_UFI_DEFMED + .DW CH_UFI_CAP + .DW CH_UFI_GEOM +#IF (($ - CH_UFI_FNTBL) != (DIO_FNCNT * 2)) + .ECHO "*** INVALID CH_UFI_FNTBL FUNCTION TABLE ***\n" +#ENDIF + +CH_UFI_STATUS: + XOR A + RET + +CH_UFI_RESET: + XOR A + RET +; ### Function 0x12 -- Disk Seek (DIOSEEK) +; +; Inputs: +; IY: device config pointer +; DEHL: Sector Address +; +; Outputs: +; A: Status +; +; This function will set the desired sector to be used for the next I/O +; operation. The returned Status (A) is a standard HBIOS result code. +;if +; The double-word Sector Address (DEHL) can represent either a Logical +; Block Address (LBA) or a Cylinder/Head/Sector (CHS). Bit 7 of D is +; set (1) for LBA mode and cleared (0) for CHS mode. +; +; For LBA mode operation, the high bit is set and the rest of the +; double-word is then treated as the logical sector address. +; +; For CHS mode operation, the Sector Address (DEHL) registers are +; interpreted as: D=Head, E=Sector, and HL=Track. All values (including +; sector) are 0 relative. +; +CH_UFI_SEEK: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + BIT 7,D ; CHECK FOR LBA FLAG + CALL Z,CH_UFI_CHS2LBA ; CLEAR MEANS CHS, CONVERT TO LBA + RES 7,D ; CLEAR FLAG REGARDLESS (DOES NO HARM IF ALREADY LBA) + + PUSH DE + PUSH HL + PUSH IY + CALL _ufi_seek + POP IY + POP HL + POP DE + + XOR A + RET +; +; Helper function to convert CHS address in DE:HL to LBA. +; Currently assumes 1.44MB floppy media +; LBA = (TRACK * #HDS * #SPT) + (HEAD * #SPT) + SECTOR +; For 1.44MB FLOPPY, #HDS = 2, #SPT = 18 +; LBA = (TRACK * 36) + (HEAD * 18) + SECTOR +; Algorithm uses B=#HDS*SPT, C=#SPT. For now, hard coded B=36, C=18 +; for 1.44MB media. In future, BC could be passed in to accommodate +; different media geometry. +; +CH_UFI_CHS2LBA: + LD B,2 * 18 ; #HDS * #SPT (SECTORS PER CYLINDER) + LD C,18 ; #SPT + + ; TRACK * #HDS * #SPT + PUSH DE ; SAVE DE + LD E,B ; SECTORS PER CYLINDER + LD H,L ; LSB OF TRACK TO H, H IS NEVER USED BY FLOPPY CHS + CALL MULT8 ; HL = H * E; TRACK LBA + POP DE ; RECOVER DE + PUSH HL ; SAVE TRACK LBA + + ; HEAD * #SPT + PUSH DE ; SAVE DE + LD E,C ; SECTORS PER TRACK + LD H,D ; HEADS + CALL MULT8 ; HL = H * E; HEAD LBA + POP DE ; RECOVER DE + + ; COMPUTE LBA (HL) = SECTOR (E) + HEAD LBA (HL) + TRACK LBA (TOS) + LD A,E ; SECTOR + CALL ADDHLA ; SECTOR * HEAD LBA + POP DE ; RECOVER TRACK LBA + ADD HL,DE ; ADD IN TRACK LBA + + ; FINISH UP + LD DE,0 ; DE IS ALWAYS ZERO + RET +; +; ### Function 0x13 -- Disk Read (DIOREAD) +; +; Inputs +; IY: device config pointer +; D: Buffer Bank ID +; E: Sector Count +; HL: Buffer Address +; +; Outputs +; A: Status +; E: Sectors Read +; +; Read Sector Count (E) sectors into the buffer located in Buffer Bank ID (D) +; at Buffer Address (HL) starting at the Current Sector. The returned +; Status (A) is a standard HBIOS result code. +; +CH_UFI_READ: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + CALL HB_DSKREAD ; HOOK HBIOS DISK READ SUPERVISOR + + PUSH HL + PUSH IY + CALL _usb_ufi_read + LD L, 0 + LD A, L + POP IY + POP HL + LD BC, 512 + ADD HL, BC + OR A + RET +; +; ### Function 0x14 -- Disk Write (DIOWRITE) +; +; Inputs +; IY: device config pointer +; D: Buffer Bank ID +; E: Sector Count +; HL: Buffer Address +; +; Outputs +; A: Status +; E: Sectors Written +; +; Write Sector Count (E) sectors from the buffer located in Buffer Bank ID (D) +; at Buffer Address (HL) starting at the Current Sector. The returned +; Status (A) is a standard HBIOS result code. +; +CH_UFI_WRITE: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + CALL HB_DSKWRITE ; HOOK HBIOS DISK WRITE SUPERVISOR + + ; call scsi_write(IY, HL); + ; HL = HL + 512 + PUSH HL + PUSH IY + CALL _usb_ufi_write + LD A, L + POP IY + POP HL + LD BC, 512 + ADD HL, BC + OR A + RET + +CH_UFI_VERIFY: +CH_UFI_FORMAT: + LD HL, 0 + LD DE, 0 + LD BC, 0 + LD A, $FF + OR A + RET + +; ### Function 0x17 -- Disk Device (DIODEVICE) +; +; Inputs +; IY: device config pointer +; +; Outputs +; A: Status +; C: Device Attributes +; D: Device Type (DIODEV_USB) +; E: Device Number (1) +; H: Device Unit Mode (0) +; L: Device I/O Base Address +; +; Reports device information. The Status (A) is a standard +; HBIOS result code. +; +; The Device Attribute (C): +; +; | **Bits** | **Definition** | +; |---------:|--------------------------------------------------| +; | 7 | Floppy | +; | 6 | Removable | +; | 5 | High Capacity (>8 MB) | +; +; Low Capacity Devices?? +; +; | **Bits** | **Definition** | +; |---------:|--------------------------------------------------| +; | 4-3 | Form Factor: 0=8", 1=5.25", 2=3.5", 3=Other | +; | 2 | Sides: 0=SS, 1=DS | +; | 1-0 | Density: 0=SD, 1=DD, 2=HD, 3=ED | +; +; High Capacity Devices +; +; | **Bits** | **Definition** | +; |---------:|--------------------------------------------------| +; | 4 | LBA Capable | +; | 3-0 | Media Type: 0=Hard Disk, 1=CF, 2=SD, 3=USB, | +; | | 4=ROM, 5=RAM, 6=RAMF, 7=FLASH, 8=CD-ROM, | +; | | 9=Cartridge, 10=usb-scsi, 11=usb-ufi | +; +CH_UFI_DEVICE: + LD C, %11010110 + LD D, DIODEV_USB + LD E, (IY+0) ; drive_index + DEC E + LD HL, 0 + XOR A + RET +; +; ### Function 0x18 -- Disk Media (DIOMEDIA) +; +; Inputs +; IY: device config pointer +; E: Flags +; +; Outputs +; A: Status +; E: Media ID +; +; Report the Media ID (E) for the for media. If bit 0 of Flags (E) is set, +; then media discovery or verification will be performed. The Status +; (A) is a standard HBIOS result code. If there is no media in device, +; function will return an error status. +; +CH_UFI_MEDIA: + LD E, MID_FD144 ;todo verify device still active? + XOR A + RET + +CH_UFI_DEFMED: + LD HL, 0 + LD DE, 0 + LD BC, 0 + LD A, $FF + OR A + RET + +; +; ### Function 0x1A -- Disk Capacity (DIOCAPACITY) +; +; Inputs +; IY: device config pointer +; +; Outputs +; A: Status +; DEHL: Sector Count +; BC: Block Size +; +; +; Report the current media capacity information. +; +CH_UFI_CAP: + EXX + LD D, 0 + LD E, (IY+1) ; usb_device + PUSH DE + POP IY + EXX + + PUSH IY + CALL _usb_ufi_get_cap + POP IY + LD BC, 512 + XOR A + RET + +CH_UFI_GEOM: + LD HL, 0 + LD DE, 0 + LD BC, 0 + LD A, $FF + OR A + RET diff --git a/Source/HBIOS/cvdu.asm b/Source/HBIOS/cvdu.asm index 99b1c664..b432515f 100644 --- a/Source/HBIOS/cvdu.asm +++ b/Source/HBIOS/cvdu.asm @@ -48,13 +48,15 @@ CVDU_ROWS .EQU 25 CVDU_COLS .EQU 80 ; #IF (CVDUMON == CVDUMON_CGA) - #DEFINE USEFONTCGA - #DEFINE CVDU_FONT FONTCGA + #DEFINE USEFONT8X8 + #DEFINE CVDU_FONT FONT8X8 +CVDU_FONTID .EQU FONTID_8X8 #ENDIF ; #IF (CVDUMON == CVDUMON_EGA) #DEFINE USEFONT8X16 #DEFINE CVDU_FONT FONT8X16 +CVDU_FONTID .EQU FONTID_8X16 #ENDIF ; TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER @@ -105,6 +107,7 @@ CVDU_INIT1: CALL PRTDEC PRTS("KB$") CALL CVDU_LOADFONT ; LOAD FONT DATA FROM ROM TO CVDU STRORAGE + ; *** DIAGNOSE FONT LOAD ERROR HERE!!! *** CALL CVDU_VDAINI CALL KBD_INIT ; INITIALIZE KEYBOARD DRIVER @@ -486,46 +489,43 @@ CVDU_CRTINIT2: ; ADJUST FOR 16K RAM SIZE ; LOAD FONT DATA ;---------------------------------------------------------------------- ; +; THE GDP USES 16 BYTES PER FONT EVEN WHEN THE FONT HAS ONLY 8 +; BYTES. SO, FOR FONT8X8, WE NEED TO ALTERNATELY WRITE 8 BYTES OF +; REAL FONT DATA, THEN WRITE 8 BYTES OF GARBAGE. +; CVDU_LOADFONT: LD HL,$2000 ; START OF FONT BUFFER LD C,18 ; UPDATE ADDRESS REGISTER PAIR CALL CVDU_WRX ; DO IT - -#IF USELZSA2 - LD (CVDU_STACK),SP ; SAVE STACK - LD HL,(CVDU_STACK) ; AND SHIFT IT - LD DE,$2000 ; DOWN 4KB TO - OR A ; CREATE A - SBC HL,DE ; DECOMPRESSION BUFFER - LD SP,HL ; HL POINTS TO BUFFER - EX DE,HL ; START OF STACK BUFFER - PUSH DE ; SAVE IT - LD HL,CVDU_FONT ; START OF FONT DATA - CALL DLZSA2 ; DECOMPRESS TO DE - POP HL ; RECALL STACK BUFFER POSITION -#ELSE - LD HL,CVDU_FONT ; START OF FONT DATA -#ENDIF - +; + LD A,CVDU_FONTID ; DESIRED FONT + CALL FNT_SELECT ; SELECT IT + RET NZ ; ERROR RETURN +; LD DE,$2000 ; LENGTH OF FONT DATA LD C,31 ; DATA REGISTER +; CVDU_LOADFONT1: - LD A,(HL) ; LOAD NEXT BYTE OF FONT DATA - CALL CVDU_WR ; WRITE IT - INC HL ; INCREMENT FONT DATA POINTER +; DEC DE ; DECREMENT LOOP COUNTER +#IF (CVDUMON == CVDUMON_CGA) + ; SKIP ALTERNATING 8 BYTE PAIRS (SEE COMMENT ABOVE) + ; WE ONLY GET NEXT REAL FONT BYTE IF BIT 3 OF COUNTER IS SET. + BIT 3,E ; BIT 3 CHANGES WITH EVERY 8 BYTES + CALL NZ,FNT_NEXT ; LOAD NEXT FONT BYTE ONLY IF BIT IS ON +#ELSE + CALL FNT_NEXT ; LOAD NEXT FONT BYTE +#ENDIF +; + CALL CVDU_WR ; WRITE IT LD A,D ; CHECK DE... OR E ; FOR COUNTER EXHAUSTED - JR NZ,CVDU_LOADFONT1 ; LOOP TILL DONE - -#IF USELZSA2 - LD HL,(CVDU_STACK) ; ERASE DECOMPRESS BUFFER - LD SP,HL ; BY RESTORING THE STACK - RET ; DONE -CVDU_STACK .DW 0 -#ELSE + JR Z,CVDU_LOADFONT3 ; BAIL OUT IF DONE + JR CVDU_LOADFONT1 ; LOOP TILL DONE +; +CVDU_LOADFONT3: + XOR A ; SIGNAL SUCCESS RET -#ENDIF ; ;---------------------------------------------------------------------- ; SET CURSOR POSITION TO ROW IN D AND COLUMN IN E diff --git a/Source/HBIOS/ds7rtc.asm b/Source/HBIOS/ds7rtc.asm index 4014b26e..aadc740b 100644 --- a/Source/HBIOS/ds7rtc.asm +++ b/Source/HBIOS/ds7rtc.asm @@ -418,12 +418,12 @@ DS7_CLP:LD C,(HL) RET ; DS7_CLKTBL: - .DB 04H, 00111111B, '/' - .DB 05H, 00011111B, '/' - .DB 06H, 11111111B, ' ' - .DB 02H, 00011111B, ':' - .DB 01H, 01111111B, ':' - .DB 00H, 01111111B, 00H + .DB 04H, 00111111B, '/' ; DD: 31 + .DB 05H, 00011111B, '/' ; MM: 12 + .DB 06H, 11111111B, ' ' ; YY: 99 + .DB 02H, 01111111B, ':' ; SS: 59 + .DB 01H, 01111111B, ':' ; MM: 59 + .DB 00H, 00111111B, 00H ; HH: 24 ; DS7_BCD:PUSH HL LD HL,DS7_BUF ; READ VALUE FROM diff --git a/Source/HBIOS/dsrtc.asm b/Source/HBIOS/dsrtc.asm index ecce36ee..81015be0 100644 --- a/Source/HBIOS/dsrtc.asm +++ b/Source/HBIOS/dsrtc.asm @@ -482,6 +482,7 @@ DSRTC_DETECT: DSRTC_DETECT1: PUSH AF ; SAVE STATUS LD A,(DSRTC_TEMP) ; GET SAVED VALUE + LD E,A ; TO E LD C,30 ; NVRAM INDEX 30 CALL DSRTC_SETBYT ; SAVE IT POP AF ; RECOVER STATUS diff --git a/Source/HBIOS/ez80cpudrv.asm b/Source/HBIOS/ez80cpudrv.asm index 494f717b..813869c4 100644 --- a/Source/HBIOS/ez80cpudrv.asm +++ b/Source/HBIOS/ez80cpudrv.asm @@ -40,13 +40,20 @@ EZ80_PREINIT: LD A, 5 LD (HB_CPUTYPE),A - ; DETECT IF USING ALT-FIRMWARE - LD A, C - AND $80 - LD (EZ80_ALT_FIRM), A LD (EZ80_PLT_VERSION), HL LD (EZ80_PLT_VERSION+2), DE + ; need version 0.4.x.x at miniumum + LD HL, 4-1 + XOR A + SBC HL, DE + + JR c, EZ80_VEROK + CPL + +EZ80_VEROK: + LD (EZ80_VER_WARNING), A + EXX LD A, C LD (EZ80_BUILD_DATE), A ; DAY @@ -82,12 +89,12 @@ EZ80_PREINIT: LD L, EZ80_MEM_CYCLES | $80 EZ80_UTIL_MEMTM_SET() LD A, L - LD (EZ80_PLT_MEMWS), A + LD (EZ80_PLT_MEMBC), A LD L, EZ80_IO_CYCLES | $80 EZ80_UTIL_IOTM_SET() LD A, L - LD (EZ80_PLT_IOWS), A + LD (EZ80_PLT_IOBC), A RET #ENDIF @@ -96,30 +103,19 @@ EZ80_PREINIT: LD HL, EZ80_MEM_MIN_NS LD E, 0 EZ80_CPY_EHL_TO_UHL - LD E, EZ80_MEM_MIN_WS + LD E, EZ80_MEM_MIN_BC | $80 EZ80_UTIL_MEMTMFQ_SET LD A, L - LD (EZ80_PLT_MEMWS), A + LD (EZ80_PLT_MEMBC), A LD HL, EZ80_IO_MIN_NS LD E, 0 EZ80_CPY_EHL_TO_UHL - LD E, EZ80_IO_MIN_WS + LD E, EZ80_IO_MIN_BC EZ80_UTIL_IOTMFQ_SET LD A, L - LD (EZ80_PLT_IOWS), A -#ENDIF -#IF (EZ80_WSMD_TYP == EZ80WSMD_WAIT) - LD L, EZ80_MEM_WS - EZ80_UTIL_MEMTM_SET() - LD A, L - LD (EZ80_PLT_MEMWS), A - - LD L, EZ80_IO_WS - EZ80_UTIL_IOTM_SET() - LD A, L - LD (EZ80_PLT_IOWS), A + LD (EZ80_PLT_IOBC), A #ENDIF LD C, TICKFREQ @@ -131,32 +127,14 @@ EZ80_PREINIT: ; eZ80 CPU DRIVER REPORT TIMINGS ; -------------------------------- EZ80_RPT_TIMINGS: - LD A, (EZ80_PLT_MEMWS) - BIT 7, A - JR NZ, EZ80_RPT_MCYC - - CALL PRTDECB - CALL PRTSTRD - .TEXT " MEM W/S, $" - JR EZ80_RPT_IOTIMING - -EZ80_RPT_MCYC: + LD A, (EZ80_PLT_MEMBC) AND $7F CALL PRTDECB CALL PRTSTRD .TEXT " MEM B/C, $" EZ80_RPT_IOTIMING: - LD A, (EZ80_PLT_IOWS) - BIT 7, A - JR NZ, EZ80_RPT_ICYC - - CALL PRTDECB - CALL PRTSTRD - .TEXT " I/O W/S, $" - JR EZ80_RPT_FSH_TIMINGS - -EZ80_RPT_ICYC: + LD A, (EZ80_PLT_IOBC) AND $7F CALL PRTDECB CALL PRTSTRD @@ -272,11 +250,12 @@ EZ80_RPT_FIRMWARE: CALL PC_LEADING_ZERO CALL PRTDECB - LD A, (EZ80_ALT_FIRM) - OR A - RET Z - CALL PRTSTRD - .TEXT " (ALT)$" + LD A, (EZ80_VER_WARNING) + OR A + RET Z + CALL PRTSTRD + .TEXT " (WARN-VER-OOD)$" + RET PC_LEADING_ZERO: @@ -292,17 +271,17 @@ PC_DASH: LD A, '-' JP PC_PRTCHR -EZ80_PLT_MEMWS: - .DB EZ80_MEM_WS -EZ80_PLT_IOWS: - .DB EZ80_IO_WS +EZ80_PLT_MEMBC: + .DB EZ80_MEM_CYCLES +EZ80_PLT_IOBC: + .DB EZ80_IO_CYCLES EZ80_PLT_FLSHWS: .DB EZ80_FLSH_WS EZ80_PLT_VERSION: .DB 0, 0, 0, 0 -EZ80_ALT_FIRM: +EZ80_VER_WARNING: .DB 0 EZ80_BUILD_DATE: @@ -331,3 +310,23 @@ _EZ80_CPY_UHL_TO_EHL: .DB $49, $E1 ; POP.L HL POP IX RET + +; set the upper byte (u of DE) to MB. +_EZ80_EXTN_DE_TO_MB_DE: + .DB $49, $D5 ; PUSH.L DE + .DB $5B, $FD, $21, $00, $00, $00 ; LD.LIL IY, 0 + .DB $49, $FD, $39 ; ADD.L IY, SP + .DB $ED, $6E ; LD A, MB + .DB $5B, $FD, $77, $02 ; LD.LIL (IY+2), A + .DB $49, $D1 ; POP.L DE + RET + +; set the upper byte (u of IY) to MB. +_EZ80_EXTN_IY_TO_MB_IY: + .DB $49, $FD, $E5 ; PUSH.L IY + .DB $5B, $FD, $21, $00, $00, $00 ; LD.LIL IY, 0 + .DB $49, $FD, $39 ; ADD.L IY, SP + .DB $ED, $6E ; LD A, MB + .DB $5B, $FD, $77, $02 ; LD.LIL (IY+2), A + .DB $49, $FD, $E1 ; POP.L IY + RET diff --git a/Source/HBIOS/ez80instr.inc b/Source/HBIOS/ez80instr.inc index 5da3db4d..de7e168a 100644 --- a/Source/HBIOS/ez80instr.inc +++ b/Source/HBIOS/ez80instr.inc @@ -47,6 +47,25 @@ #DEFINE EZ80_TMR_IS_TICK_ISR LD A, 2 \ LD B, 10 \ EZ80_FN #DEFINE EZ80_TMR_DELAY LD A, 2 \ LD B, 11 \ EZ80_FN + #DEFINE EZ80_EX_USB_INIT LD A, 6 \ LD B, 255 \ EZ80_FN + #DEFINE EZ80_EX_USB_STORAGE_SEEK LD A, 6 \ LD B, 254 \ EZ80_FN + #DEFINE EZ80_EX_USB_GET_DEV_TYPE LD A, 6 \ LD B, 253 \ EZ80_FN + + #DEFINE EZ80_EX_USB_SCSI_READ LD A, 6 \ LD B, 0 \ EZ80_FN + #DEFINE EZ80_EX_USB_SCSI_WRITE LD A, 6 \ LD B, 1 \ EZ80_FN + #DEFINE EZ80_EX_USB_SCSI_READ_CAP LD A, 6 \ LD B, 2 \ EZ80_FN + #DEFINE EZ80_EX_USB_SCSI_INIT LD A, 6 \ LD B, 15 \ EZ80_FN + + #DEFINE EZ80_EX_USB_UFI_READ LD A, 6 \ LD B, 16 \ EZ80_FN + #DEFINE EZ80_EX_USB_UFI_WRITE LD A, 6 \ LD B, 17 \ EZ80_FN + #DEFINE EZ80_EX_USB_UFI_GET_CAP LD A, 6 \ LD B, 18 \ EZ80_FN +; #DEFINE EZ80_EX_USB_UFI_INIT LD A, 6 \ LD B, 31 \ EZ80_FN + + #DEFINE EZ80_EX_USB_KYB_STATUS LD A, 6 \ LD B, 32 \ EZ80_FN + #DEFINE EZ80_EX_USB_KYB_READ LD A, 6 \ LD B, 33 \ EZ80_FN + #DEFINE EZ80_EX_USB_KYB_FLUSH LD A, 6 \ LD B, 34 \ EZ80_FN + #DEFINE EZ80_EX_USB_KYB_INIT LD A, 6 \ LD B, 47 \ EZ80_FN + #DEFINE EZ80_THROTTLE_START(p,store) \ #DEFCONT \ PUSH AF #DEFCONT \ PUSH BC @@ -112,6 +131,13 @@ #defcont \ .DB $49 #defcont \ SBC HL, BC + ; LD.L DE,(IY+d) $49, $FD, $17, d + #DEFINE LD_DE_IY_P_.L(dd) \ + #DEFCONT \ .DB $49 + #DEFCONT \ .DB $FD + #DEFCONT \ .DB $17 + #DEFCONT \ .DB dd + IO_SEGMENT .EQU $FF ; THE UPPER 8-BIT ADDRESS FOR I/O #DEFINE OUT_NN_A(addr) \ @@ -126,6 +152,8 @@ IO_SEGMENT .EQU $FF ; THE UPPER 8-BIT ADDRESS FOR I/O #define EZ80_CPY_EHL_TO_UHL CALL _EZ80_CPY_EHL_TO_UHL #define EZ80_CPY_UHL_TO_EHL CALL _EZ80_CPY_UHL_TO_EHL +#define EZ80_EXTN_DE_TO_MB_DE CALL _EZ80_EXTN_DE_TO_MB_DE +#DEFINE EZ80_EXTN_IY_TO_MB_IY CALL _EZ80_EXTN_IY_TO_MB_IY #ELSE #DEFINE EZ80_IO diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm index 07ff95d8..d8b4bb86 100644 --- a/Source/HBIOS/hbios.asm +++ b/Source/HBIOS/hbios.asm @@ -522,8 +522,9 @@ HB_HCB_END .EQU $ ; THE FOLLOWING CODE IS RELOCATED TO THE TOP OF MEMORY TO HANDLE INVOCATION DISPATCHING ; HB_PROXY_BEG .EQU $ +HBX_IMG .EQU $ ; LOC OF HBX IMAGE IN HBIOS IMAGE BANK ; - .FILL (HBX_IMG - $) ; FILL TO START OF PROXY IMAGE START +;;; .FILL (HBX_IMG - $) ; FILL TO START OF PROXY IMAGE START .ORG HBX_LOC ; ADJUST FOR RELOCATION ; ; MEMORY LAYOUT: @@ -1371,7 +1372,7 @@ HB_ENTRYTBL .EQU $ ; JP HB_START ; HBIOS INITIALIZATION JP HB_DISPATCH ; VECTOR TO DISPATCHER - JP PRTSUM + ; JP PRTSUM ; !!! DO NOT ADD ADDTIONAL VECTORS HERE WITHOUT ; CHECKING W/ WAYNE !!! ; @@ -1472,6 +1473,13 @@ HB_RESTART: #IF (CPUFAM != CPU_EZ80) IM 1 ; INTERRUPT MODE 1 #ENDIF +; + ; IF WE ARE RESTARTING IN RAM, WE NEED TO RESET THE INTERRUPTS + ; ENABLED FLAG. IF THIS IS A NORMAL ROM START, THIS DOES + ; NOTHING AND THE FLAG IS RESET BY DEFAULT. + XOR A + LD (INTSENAB),A +; ; #IFDEF APPBOOT ; @@ -1919,9 +1927,9 @@ ROMRESUME: ; ; LAUNCH S100 MONITOR FROM ROM BANK 3 LD A,BID_IMG2 ; S100 MONITOR BANK - LD IX,0 ; EXECUTION RESUMES HERE + LD IX,HWMON_IMGLOC ; EXECUTION RESUMES HERE CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN - HALT ; WE SHOULD NOT COME BACK HERE! + JR $ ; HALT WE SHOULD NOT COME BACK HERE! ; S100MON_SKIP: ; RESTORE DEFAULT RELOAD REGISTER VALUE (PROBABLY NOT NEEDED) @@ -2076,7 +2084,7 @@ MBC_SINGLE: LD A,BID_BIOS ; BIOS BANK ID LD IX,HB_START1 ; EXECUTION RESUMES HERE CALL HBX_BNKCALL ; CONTINUE IN RAM BANK, DO NOT RETURN - HALT ; WE SHOULD NOT COME BACK HERE! + JR $ ; HALT WE SHOULD NOT COME BACK HERE! #ENDIF ; ; EXECUTION RESUMES HERE AFTER SWITCH TO RAM BANK @@ -2141,32 +2149,32 @@ CB_IDS: LD (HL),A ; POPULATE CB_BIDCOM ; DISABLED AT THIS POINT. ; #IF (CPUFAM != CPU_EZ80) -#IF ((INTMODE == 2) | ((INTMODE == 1) & (CPUFAM == CPU_Z180))) + #IF ((INTMODE == 2) | ((INTMODE == 1) & (CPUFAM == CPU_Z180))) ; SETUP Z80 IVT AND INT MODE 2 LD A,HBX_IVT >> 8 ; SETUP HI BYTE OF IVT ADDRESS LD I,A ; ... AND PLACE IT IN I REGISTER - #IF (CPUFAM == CPU_Z180) + #IF (CPUFAM == CPU_Z180) ; SETUP Z180 IVT XOR A ; SETUP LO BYTE OF IVT ADDRESS OUT0 (Z180_IL),A ; ... AND PLACE IN Z180 IL REGISTER - #ENDIF + #ENDIF - #IF (INTMODE == 2) + #IF (INTMODE == 2) IM 2 ; SWITCH TO INT MODE 2 + #ENDIF #ENDIF -#ENDIF ; -#IF (MEMMGR == MM_Z280) + #IF (MEMMGR == MM_Z280) ; NOW POINT TO RAM COPY OF Z280 INT/TRAP TABLE ; HL IS TOP 16 BITS OF PHYSICAL ADDRESS OF IVT ; IVT *MUST* BE ON A 4K BOUNDARY LD C,Z280_VPR LD HL,0 + (((PBANK(BID_BIOS) << 15) + Z280_IVT) >> 8) LDCTL (C),HL -#ENDIF + #ENDIF ; -#IF (INTMODE == 3) + #IF (INTMODE == 3) ; ; SETUP Z280 INT A FOR VECTORED INTERRUPTS LD HL,%0010000000000000 @@ -2176,7 +2184,7 @@ CB_IDS: LD (HL),A ; POPULATE CB_BIDCOM ; TRANSITION TO INTERRUPT MODE 3 IM 3 ; -#ENDIF + #ENDIF #ENDIF ; ;-------------------------------------------------------------------------------------------------- @@ -2949,27 +2957,6 @@ NXTMIO: LD A,(HL) ; #ENDIF ; -;-------------------------------------------------------------------------------------------------- -; ENABLE INTERRUPTS -;-------------------------------------------------------------------------------------------------- -; -#IFDEF TESTING -; -INTTEST: - ; TEST TO SEE IF SOMEBODY ENABLED INTS EARLY! - LD A,I - JP PO,INTTEST_Z ; IF PO, INTS DISABLED AS EXPECTED - PRTX(STR_INTWARN) ; WARNING - JR INTTEST_Z ; CONTINUE -; -STR_INTWARN .TEXT "\r\n\r\nWARNING: INTERRUPTS ENABLED TOO EARLY!!!$" -; -INTTEST_Z: -; -#ENDIF -; - HB_EI ; INTERRUPTS SHOULD BE OK NOW -; ; PERFORM A RESET OPERATION ON ALL CHARACTER DEVICES THAT HAVE BEEN ; INSTALLED. THIS SHOULD CORRECT ANY PROBLEMS IF A PROBE DESTROYED ; THE PROGRAMMING OF ANOTHER DEVICE. @@ -3093,6 +3080,32 @@ HB_SPDTST: #ENDIF ; ;-------------------------------------------------------------------------------------------------- +; ENABLE INTERRUPTS +;-------------------------------------------------------------------------------------------------- +; +#IFDEF TESTING +; +INTTEST: + ; TEST TO SEE IF SOMEBODY ENABLED INTS EARLY! + LD A,I + JP PO,INTTEST_Z ; IF PO, INTS DISABLED AS EXPECTED + PRTX(STR_INTWARN) ; WARNING + JR INTTEST_Z ; CONTINUE +; +STR_INTWARN .TEXT "\r\n\r\nWARNING: INTERRUPTS ENABLED TOO EARLY!!!$" +; +INTTEST_Z: +; +#ENDIF +; + HB_EI ; INTERRUPTS SHOULD BE OK NOW +; +#IF (INTMODE != 0) + OR $FF ; TRUE + LD (INTSENAB),A ; SET INTERRUPTS ENABLED FLAG +#ENDIF +; +;-------------------------------------------------------------------------------------------------- ; DISPLAY PLATFORM INFORMATION ;-------------------------------------------------------------------------------------------------- ; @@ -3708,12 +3721,7 @@ INITSYS3: LD DE,STR_BANNER ; POINT TO BANNER CALL NZ,WRITESTR ; OUTPUT IF CONSOLE MOVED ; -;-------------------------------------------------------------------------------------------------- -; PRINT DEVICE SUMMARY -;-------------------------------------------------------------------------------------------------- -; INITSYS3A: - CALL PRTSUM ; PRINT UNIT/DEVICE SUMMARY TABLE ; ;-------------------------------------------------------------------------------------------------- ; DIAGNOSTIC ROUTINES @@ -3837,6 +3845,13 @@ DBG_NOTE: ; TRANSITION TO USER LAND ;-------------------------------------------------------------------------------------------------- ; +; WE CAN GET HERE 2 WAYS. ON A COLD START, WE JUST FALL THROUGH FROM +; ABOVE. ON A WARM START, INITSYS4 IS INVOKED FROM SYS_RESWARM. +; REGISTER E IS SET TO INDICATE WHICH OF THESE IF OCCURRING SO THAT +; ROMLDR CAN BEHAVE AS APPROPRIATE. +; + LD E,START_COLD ; SIGNAL A COLD START +; INITSYS4: ; ; IF Z280, WE NEED TO SWITCH TO USER MODE NOW. @@ -3857,12 +3872,14 @@ INITSYS4: LD C,Z280_MSR ; MASTER STATUS REGISTER LD HL,$4000 | $0B ; USER MODE W/ NORMAL INT MASK LDCTL (C),HL ; DO IT +#ELSE + LD SP,HBX_LOC ; STACK JUST BELOW HBIOS PROXY #ENDIF ; DIAG(0) ; CLEAR BOOT DIAG LED(S) FPLEDS(DIAG_00) ; CLEAR FP LEDS ; -; CHAIN TO LOADER +; CHAIN TO ROM LOADER (ROMLDR) ; #IFDEF ROMBOOT LD A,BID_IMG0 ; CHAIN TO OS IMAGES BANK @@ -3871,7 +3888,7 @@ INITSYS4: #ENDIF LD IX,0 ; ENTER AT ADDRESS 0 CALL HBX_BNKCALL ; GO THERE - HALT ; WE SHOULD NEVER COME BACK! + JR $ ; HALT WE SHOULD NEVER COME BACK! ; ;-------------------------------------------------------------------------------------------------- ; TABLE OF RECOVERY MODE INITIALIZATION ENTRY POINTS @@ -3954,6 +3971,9 @@ HB_PCINITTBL: #IF (PIO_4P | PIO_ZP) .DW PIO_PREINIT #ENDIF +#IF (XOSENABLE) + .DW XOS_PREINIT +#ENDIF ; HB_PCINITTBLLEN .EQU (($ - HB_PCINITTBL) / 2) ; @@ -3963,6 +3983,15 @@ HB_PCINITTBLLEN .EQU (($ - HB_PCINITTBL) / 2) ; HB_INITTBL: ; +#IF (CHNATIVEENABLE) + ; NEED TO ENUMERATE USB DEVICES EARLY, SO THAT ACTUAL DRIVERS + ; WILL BE ABLE TO FIND THEM. +#IF (CHNATIVEFORCE) + .DW CHNATIVE_INITF +#ELSE + .DW CHNATIVE_INIT +#ENDIF +#ENDIF #IF (KIOENABLE) .DW KIO_INIT #ENDIF @@ -4058,6 +4087,9 @@ HB_INITTBL: #IF (EZ80RTCENABLE) .DW EZ80RTC_INIT #ENDIF +#IF (PCRTCENABLE) + .DW PCRTC_INIT +#ENDIF #IF (CPUFAM == CPU_EZ80) ; INITALISE ONE OF THE SUPPORTED SYSTEM TIMER TICKS DRIVERS .DW EZ80_TMR_INIT @@ -4089,6 +4121,9 @@ HB_INITTBL: #IF (SCONENABLE) .DW SCON_INIT #ENDIF +#IF (XOSENABLE) + .DW XOS_INIT +#ENDIF #IF (LPTENABLE) .DW LPT_INIT #ENDIF @@ -4143,6 +4178,12 @@ HB_INITTBL: #IF (ESPENABLE) .DW ESP_INIT #ENDIF +#IF (CHSCSIENABLE) + .DW CHSCSI_INIT +#ENDIF +#IF (CHUFIENABLE) + .DW CHUFI_INIT +#ENDIF ; HB_INITTBLLEN .EQU (($ - HB_INITTBL) / 2) ; @@ -5369,21 +5410,8 @@ SYS_RESINT: SYS_RESWARM: ; CALL SYS_RESINT ; HBIOS INTERNAL RESET -; -#IF (MEMMGR == MM_Z280) - JP INITSYS4 -#ELSE - ; PERFORM BANK CALL TO OS IMAGES BANK IN ROM - LD SP,HBX_LOC ; STACK JUST BELOW HBIOS PROXY - #IFDEF APPBOOT - LD A,BID_AUX ; IF APPBOOT, CHAIN TO AUX BANK - #ELSE - LD A,BID_IMG0 ; ELSE CHAIN TO OS IMAGES BANK - #ENDIF - LD IX,0 ; ENTER AT ADDRESS 0 - CALL HBX_BNKCALL ; GO THERE - HALT ; WE SHOULD NEVER COME BACK! -#ENDIF + LD E,START_WARM ; SIGNAL A WARM START + JP INITSYS4 ; DO OUR NORMAL USER LAND STARTUP ; ; RESTART SYSTEM AS THOUGH POWER HAD JUST BEEN TURNED ON ; @@ -5432,7 +5460,7 @@ SYS_RESUSER: ; IN0 A,(Z180_ITC) ; GET ITC REGISTER XOR $80 ; PRECLEAR TRAP BIT - RET M ; IF TRAP BIT NOT SET, DONE + JP M,SYS_RESUSER3 ; IF TRAP BIT NOT SET, DONE ; ; HANDLE INVALID OPCODE DEC HL ; BACK UP TO OPCODE START @@ -5466,6 +5494,7 @@ SYS_RESUSER2: ; #ENDIF ; +SYS_RESUSER3: ; RESET ACTIVE VIDEO DISPLAY ATTACHED TO EMULATOR CALL TERM_RESET ; @@ -6210,7 +6239,7 @@ SYS_SETCPUSPD: ; LD A,L ; CLK SPD TO ACCUM CP $FF ; NO CHANGE? - JR Z,SYS_SETCPUSPD3 ; DONE IF SO + JR Z,SYS_SETCPUSPD_OK ; DONE IF SO LD C,%00000000 ; HALF SPEED CP 0 JR Z,SYS_SETCPUSPD1 @@ -6222,12 +6251,12 @@ SYS_SETCPUSPD1: LD A,(HB_RTCVAL) AND ~%00001000 ; CLEAR SPEED BIT OR C ; IMPLEMENT NEW SPEED BIT -#IF (PLATFORM == PLT_SBC) + #IF (PLATFORM == PLT_SBC) ; SBC SPEED BIT IS INVERTED, ADJUST IT LD A,C XOR %00001000 LD C,A -#ENDIF + #ENDIF LD (HB_RTCVAL),A ; SAVE IN SHADOW REGISTER OUT (RTCIO),A ; UPDATE HARDWARE REGISTER ; @@ -6255,15 +6284,11 @@ SYS_SETCPUSPD2: ADC A,C ; C -> A; ADD CF FOR ROUNDING LD (CB_CPUMHZ),A ; SAVE IT ; -#IF (CPUFAM != CPU_EZ80) + #IF (CPUFAM != CPU_EZ80) ; REINIT DELAY ROUTINE LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY -#ENDIF -; -SYS_SETCPUSPD3: - XOR A - RET + #ENDIF #ENDIF ; #IF (PLATFORM == PLT_HEATH) @@ -6302,14 +6327,11 @@ SYS_SETCPUSPD2: ADC A,C ; C -> A; ADD CF FOR ROUNDING LD (CB_CPUMHZ),A ; SAVE IT ; -#IF (CPUFAM != CPU_EZ80) + #IF (CPUFAM != CPU_EZ80) ; REINIT DELAY ROUTINE LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY -#ENDIF -; - XOR A ; SIGNAL SUCCESS - RET + #ENDIF #ENDIF ; #IF (CPUFAM == CPU_Z180) @@ -6441,11 +6463,11 @@ SYS_SETCPUSPD4: LD A,L ; WORKING VALUE TO A OUT0 (Z180_DCNTL),A ; IMPLEMENT NEW VALUE ; -#IF (CPUFAM != CPU_EZ80) + #IF (CPUFAM != CPU_EZ80) ; REINIT DELAY ROUTINE LD A,(CB_CPUMHZ) ; CPU SPEED TO ACCUM AND INIT CALL DELAY_INIT ; .. SPEED COMPENSATED DELAY -#ENDIF + #ENDIF ; #IF ((INTMODE == 2) & (Z180_TIMER)) ; THE Z180 TIMER IS BASED ON CPU SPEED. SO HERE @@ -6473,10 +6495,16 @@ SYS_SETCPUSPD4: LD IY,ASCI1_CFG CALL ASCI_INITDEV #ENDIF +#ENDIF +; +SYS_SETCPUSPD_OK: +; + LD B,BF_DSKYEVENT + LD C,DSKY_EVT_CPUSPD + CALL DSKY_DISPATCH ; XOR A RET -#ENDIF ; SYS_SETCPUSPD_ERR: OR $FF ; NOT SUPPORTED @@ -6914,7 +6942,7 @@ SYSHALT: LD DE,STR_HALT CALL WRITESTR DI - HALT + JR $ ; HALT ; ;-------------------------------------------------------------------------------------------------- ; INTERRUPT MANAGEMENT SUPPORT @@ -7360,7 +7388,7 @@ Z280_DIAG: ; ;RETIL DI - HALT + JR $ ; HALT ; Z280_BADINTSTR .TEXT "BAD INT $" Z280_SSTEPSTR .TEXT "SINGLE STEP $" @@ -7430,7 +7458,7 @@ Z280_PRIVINST4: ; ; GO NO FURTHER DI - HALT + JR $ ; HALT ; Z280_PRIVINSTX: ; RESTORE REGISTERS @@ -8266,217 +8294,210 @@ HB_CPUSPD2: RET ; AND DONE #ENDIF ; CPUFAM != CPU_EZ80 ; -HB_UTIL_END .EQU $ -; ;================================================================================================== -; DISPLAY SUMMARY OF ATTACHED UNITS/DEVICES +; FONT MANAGEMENT ROUTINES ;================================================================================================== ; -HB_PRTSUM_BEG .EQU $ +; SELECT A FONT BASED ON THE FONT ID PASSED IN REGISTER A. THIS WILL +; PREPARE TO STREAM FONT DATA VIA THE FNT_NEXT ROUTINE. USES AF, BC, +; DE, AND HL. RETURNS ZERO (ZF SET) FOR SUCCESS OR NON-ZERO (ZF CLEAR) +; IF FONT NOT FOUND. ; -PRTSUM: - CALL NEWLINE2 ; SKIP A LINE - LD DE,PS_STRHDR ; POINT TO HEADER - CALL WRITESTR ; PRINT IT +#IF ROMFONTS +FNT_BNKID .EQU FONTS_BNK +FNT_MAP .EQU FONTS_LOC +#ELSE +FNT_BNKID .EQU BID_BIOS +#ENDIF +; +FNT_SELECT: + ;;;CALL PC_SPACE ; ** DEBUG *** + ;;;CALL PRTHEXBYTE ; ** DEBUG *** + LD E,A ; DESIRED FONT ID TO E + LD A,FNT_BNKID ; FONT BANK ID TO A + LD (FNT_BID),A ; SAVE IN WORKING VARIABLE + LD D,FNT_BNKID ; D = BANK FOR FONT DATA + LD HL,FNT_MAP ; POINT TO START OF MAP +; + ; FONT MAP TABLE BEGINS WITH A 2 BYTE SIGNATURE. ATTEMPTING + ; TO DECOMPRESS INVALID DATA WOULD BE VERY BAD. + CALL FNT_BYTE ; FIRST SIGNATURE BYTE + ;;;CALL PC_SPACE ; ** DEBUG *** + ;;;CALL COUT ; ** DEBUG *** + INC HL ; BUMP PTR + CP 'F' ; SHOULD BE 'F' + JR NZ,FNT_SELECT_ERR ; IF MISMATCH, BAIL OUT W/ ERR + CALL FNT_BYTE ; SECOND SIGNATURE BYTE + ;;;CALL COUT ; ** DEBUG *** + INC HL ; BUMP PTR + CP 'M' ; SHOULD BE 'M' + JR NZ,FNT_SELECT_ERR ; IF MISMATCH, BAIL OUT W/ ERR +; +FNT_SELECT0: + CALL FNT_BYTE ; LOAD THE FONT ID FROM MAP + ;;;CALL PC_SPACE ; ** DEBUG *** + ;;;CALL PRTHEXBYTE ; ** DEBUG *** + AND $7F ; MASK OUT COMP INDICATOR + OR A ; CHECK FOR END OF TABLE + JR Z,FNT_SELECT_ERR ; IF SO, BAIL OUT W/ ERR + CP E ; CHECK FOR DESIRED FONT ID + JR Z,FNT_SELECT1 ; IF SO, LOCK IT IN + INC HL ; BUMP PAST FONT ID + INC HL ; BUMP TO + INC HL ; ... NEXT TABLE ENTRY + JR FNT_SELECT0 ; AND LOOP +; +FNT_SELECT1: + CALL FNT_BYTE ; GET FONT ID BYTE + PUSH AF ; SAVE IT + LD C,A ; SAVE IT IN E + INC HL ; BUMP PAST FONT ID + CALL FNT_BYTE ; LO BYTE OF ADDRESS + LD E,A ; PUT IN E + INC HL ; BUMP + CALL FNT_BYTE ; HI BYTE OF ADDRESS + LD D,A ; PUT IN D + EX DE,HL ; FULL ADDRESS TO HL +; +;;;#IF ROMFONTS +;;; CALL PC_SPACE ; ** DEBUG *** +;;; LD A,'R' ; ** DEBUG *** +;;; CALL COUT ; ** DEBUG *** +;;;#ELSE +;;; CALL PC_SPACE ; ** DEBUG *** +;;; LD A,'H' ; ** DEBUG *** +;;; CALL COUT ; ** DEBUG *** +;;;#ENDIF ; - LD C,BF_SYSGET_CIOCNT ; CHARACTER DEVICES - LD HL,PS_SERIAL - CALL PRT_ALLD + POP AF ; RECOVER FONT ID + AND $80 ; COMPRESSED FONT DATA? + JR Z,FNT_SELECT2 ; IF NOT, SKIP DECOMP ; - LD C,BF_SYSGET_DIOCNT ; DISK DRIVES - LD HL,PS_DISK - CALL PRT_ALLD +#IF ((CVDUENABLE | GDCENABLE | TMSENABLE | VGAENABLE | VRCENABLE) & USELZSA2) ; - LD C,BF_SYSGET_VDACNT ; VIDEO DEVICES - LD HL,PS_VIDEO - CALL PRT_ALLD +; DECOMPRESS THE FONT DATA. WE USURP $E000-$EFFF AS A BUFFER FOR THE +; DECOMPRESSED DATA. IF THE FONT DATA IS IN ROM, WE FIRST COPY THE +; COMPRESSED DATA TO $D000-DFFF. THE BUFFER SIZES ARE LARGE ENOUGH TO +; CONTAIN THE LARGEST FONT IN ITS DECOMPRESSED STATE. THE BUFFER +; LOCATIONS ARE SAFE DURING BOOT, BUT *NOT* FOR A RUNNING SYSTEM. SO, +; ANY FONT THAT MUST BE RELOADED AFTER BOOT WILL NEED TO BE SAVED IN +; DECOMPRESSED STATE! SPECIFICALLY THE 6X8 TMS FONT. ; - LD C,BF_SYSGET_SNDCNT ; SOUND DEVICES - LD HL,PS_SOUND - CALL PRT_ALLD - RET + ;;;LD A,'C' ; ** DEBUG *** + ;;;CALL COUT ; ** DEBUG *** ; -PRT_ALLD: - LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET - RST 08 ; E := UNIT COUNT - LD B,E ; MOVE TO B FOR LOOP COUNT - LD A,E ; MOVE TO ACCUM - OR A ; SET FLAGS - RET Z ; IF NONE, JUST RETURN - LD C,0 ; C WILL BE UNIT INDEX -PRT_ALLD1: - PUSH BC ; SAVE LOOP CONTROL - PUSH DE - PUSH HL - CALL JPHL ; CALL THE ROUTINE PASSED IN HL - POP HL - POP DE - POP BC ; RESTORE LOOP CONTROL - INC C ; BUMP UNIT INDEX - DJNZ PRT_ALLD1 ; LOOP THRU ALL DEVICES - RET + #IF ROMFONTS + ; COPY THE COMPRESSED DATA FROM ROM TO RAM BUFFER + LD A,(FNT_BID) ; GET ROM FONT BANK ID + LD (HB_SRCBNK),A ; SETUP SOURCE BANK + LD A,BID_BIOS ; DEST BANK IS BIOS BANK + LD (HB_DSTBNK),A ; SETUP DESTINATION BANK + LD DE,$D000 ; PUT DEST IN DE + LD BC,$1000 ; BLINDLY COPY 4K + CALL HBX_BNKCPY ; COPY COMP FONT DATA TO RAM +; + ; DO THE DECOMPRESSION + LD HL,$D000 ; COMP BUF ADR TO HL + LD DE,$E000 ; DECOMP BUF ADR TO DE + CALL DLZSA2 ; DECOMPRESS + LD A,BID_BIOS ; BANK OF DECOMP BUF + LD (FNT_BID),A ; UPDATE FNT_BID + LD HL,$E000 ; DECOMP BUF ADR TO HL + #ELSE + LD DE,$E000 ; DECOMP BUF ADR TO DE + CALL DLZSA2 ; DECOMPRESS + LD HL,$E000 ; DECOMP BUF ADR TO HL + #ENDIF ; -; PRINT ONE LINE DISK UNIT/DEVICE INFO, DISK UNIT INDEX IN C -; -PS_DISK: - PUSH BC ; SAVE UNIT INDEX FOR LATER -; - ; UNIT COLUMN - PRTS("Disk $") - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT - CP 10 ; CHECK FOR MULTIPLE DIGITS - CALL C,PC_SPACE ; EXTRA SPACE IF NEEDED - PRTS(" $") ; PAD TO NEXT COLUMN -; - ; DEVICE COLUMN - LD B,BF_DIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - RST 08 ; DE:=DEVTYP/NUM, C:=DISK ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES - LD HL,PS_DDMD ; POINT TO DISK DEVICE TYPE NAME TABLE - CALL PS_PRTDEV ; PRINT DISK DEVICE NMEMONIC PADDED TO FIELD WIDTH - POP DE ; RECOVER ATTRIBUTES TO DE - PUSH DE ; SAVE ATTRIBUTES AGAIN - CALL PS_PRTDT ; PRINT DISK TYPE - POP DE ; RESTORE ATTRIBUTES - POP BC ; RESTORE UNIT NUM - CALL PS_PRTDC ; PRINT DISK CAPACITY +#ELSE + JR FNT_SELECT_ERR ; OOPS, CAN'T DECOMPRESS +#ENDIF ; - CALL NEWLINE +FNT_SELECT2: + LD (FNT_PTR),HL ; SAVE STARTING POINTER + ;;;LD A,(FNT_BID) ; ** DEBUG *** + ;;;CALL PC_SPACE ; ** DEBUG *** + ;;;CALL PRTHEXBYTE ; ** DEBUG *** + ;;;LD HL,(FNT_PTR) ; ** DEBUG *** + ;;;CALL PC_SPACE ; ** DEBUG *** + ;;;CALL PRTHEXWORDHL ; ** DEBUG *** + XOR A ; SIGNAL SUCCESS RET -; -; PRINT DISK TYPE (DISK ATTRIBUTE IN E) -; -PS_PRTDT: - LD A,E ; ATTRIBUTES TO A - BIT 7,A ; FLOPPY BIT SET? - LD HL,PS_DTFLOP ; ASSUME FLOPPY - JP NZ,PS_PRT18 ; IF FLOPPY, JUMP AHEAD - LD C,E - LD DE,PS_DTHARD - LD A,00001111B - CALL PRTIDXMSK - CALL PS_PAD18 ; PAD TO 18 SPACES + +FNT_SELECT_ERR: + OR $FF ; SIGNAL FAILURE RET ; -; PRINT DISK CAPACITY (UNIT IN C, ATTRIBUTE IN E) -; -PS_PRTDC: -; - LD A,E ; ATTRIBUTE TO ACCUM - BIT 7,A ; TEST FOR FLOPPY - JR NZ,PS_PRTDC2 ; HANDLE FLOPPY - AND $0F ; ISOLATE TYPE BITS - CP 4 ; ROM DISK? - JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB - CP 5 ; RAM DISK? - JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB - CP 7 ; FLASH DISK? - JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB -; - ; PRINT HARD DISK STORAGE SIZE IN MB - LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY - RST 08 ; DE:HL := BLOCKS - JP NZ,PS_PRTNUL ; MEDIA PROBLEM - RES 7,D ; CLEAR LBA BIT - LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB - CALL SRL32 ; RIGHT SHIFT - CALL PRTDEC32 ; PRINT DWORD IN DECIMAL - PRTS("MB$") ; PRINT SUFFIX - CALL PC_COMMA - PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA - RET ; DONE -; -PS_PRTDC1: - ; PRINT ROM/RAM DISK CAPACITY IN KB - LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY - RST 08 ; DE:HL := BLOCKS - JP NZ,PS_PRTNUL ; MEDIA PROBLEM - RES 7,D ; CLEAR LBA BIT - LD B,1 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB - CALL SRL32 ; RIGHT SHIFT - CALL PRTDEC32 ; PRINT DWORD IN DECIMAL - PRTS("KB$") ; PRINT SUFFIX - CALL PC_COMMA - PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA - RET ; DONE -; -PS_PRTDC2: - LD C,E ; ATTRIBUTE TO C FOR SAFE KEEPING -; - LD A,%00011000 ; DISPLAY FORM FACTOR - LD DE,PS_FLP_FSTR ; WHICH IS DEFINED IN - CALL PRTIDXMSK ; BITS 5 AND 6. +; RETURN THE NEXT BYTE OF FONT DATA IN REGISTER A. EACH CALL RETURNS +; THE NEXT BYTE OF DATA. THERE IS NO INDICATION OF THE END OF THE +; FONT DATA. THE CALLER CONTROLS NUMBER OF BYTES REQUESTED. +; ONLY REGISTER A IS MODIFIED. ; - LD A,%00000100 ; DISPLAY SIDES - LD DE,PS_FLP_SSTR ; WHICH IS DEFINED - CALL PRTIDXMSK ; IN BIT 4 -; - LD A,%00000011 ; DISPLAY DENSITY - LD DE,PS_FLP_DSTR ; WHICH IS DEFINED IN - CALL PRTIDXMSK ; BITS 2 AND 3. +FNT_NEXT: + PUSH HL + LD HL,(FNT_PTR) + CALL FNT_BYTE + INC HL + LD (FNT_PTR),HL + POP HL + RET ; - CALL PC_COMMA - PRTS("CHS$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA +; HELPER FUNCTION TO RETRIEVE A BYTE OF ROM FONT DATA FROM THE +; ROM FONT BANK. RETURNS BYTE FROM (FNT_BID:HL). RETURNS BYTE IN A. +; ALL OTHER REGSITERS UNCHANGED. ; +FNT_BYTE: +#IF (MEMMGR == MM_Z280) + ; THERE IS A DEFICIENCY IN HBX_PEEK FOR Z280 W/ MM_Z280. + ; IT WILL NOT WORK WHEN CALLED FROM Z280 SYSTEM MODE. + ; THIS SHOULD BE REVISITED. + ; + ; NOTE: WHEN WE GO TO RESTORE THE USER SPACE BANK, WE DON'T + ; REALLY HAVE A GOOD SOURCE OF WHAT BANK ID TO RESTORE IT TO. + ; IN THEORY, WE ARE BEING INVOKED EITHER DURING SYSTEM BOOT OR + ; VIA HB_INVOKE. DURING SYSTEM BOOT, THE USER BANK IS NOT + ; RELEVANT. FOR HB_INVOKE, THE PREVIOUS USER BANK WILL BE + ; RECORDED IN HB_INVBNK. SO, WE BLINDLY USE HB_INVBNK. THIS + ; WILL BE CORRECT WHEN INVOKED VIA HB_INVOKE AND SHOULD DO NO + ; HARM WHEN INVOKED DURING SYSTEM BOOT. THIS REALLY NEEDS TO + ; BE REVIEWED. + ; + LD A,(FNT_BID) ; GET THE FONT BANK ID + PUSH BC ; SAVE BC + PUSH HL ; SAVE HL + LD B,$00 ; POINT TO USER PDRS + CALL Z280_BNKSEL ; SELECT Z280 USER BANK + POP HL ; RECOVER HL + PUSH HL ; AND RESAVE IT + LDUP A,(HL) ; GET THE BYTE FROM USER SPACE + PUSH AF ; SAVE THE BYTE + LD A,(HB_INVBNK) ; GET PRIOR BANK (SEE NOTE ABOVE) + LD B,$00 ; POINT TO USER PDRS + CALL Z280_BNKSEL ; SELECT IT + POP AF ; RECOVER VALUE + POP HL ; RECOVER HL + POP BC ; RECOVER BC RET ; DONE -; -; PRINT ONE LINE SERIAL UNIT/DEVICE INFO, SERIAL UNIT INDEX IN C -; -PS_SERIAL: - PUSH BC ; SAVE UNIT INDEX FOR LATER -; - ; UNIT COLUMN - PRTS("Char $") - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT - PRTS(" $") ; PAD TO NEXT COLUMN -; - ; DEVICE COLUMN - LD B,BF_CIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - RST 08 ; DE:=DEVTYP/NUM, C:=DEVICE ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES - LD HL,PS_SDUART ; POINT TO SERIAL DEVICE TYPE NAME TABLE - CALL PS_PRTDEV ; PRINT SERIAL DEVICE NMEMONIC PADDED TO FIELD WIDTH - POP BC ; RECOVER ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES AGAIN - CALL PS_PRTST ; PRINT SERIAL TYPE - POP BC ; RESTORE ATTRIBUTES - POP DE ; RESTORE UNIT NUM TO E - CALL PS_PRTSC ; PRINT SERIAL CONFIG -; - CALL NEWLINE +#ELSE + PUSH DE + LD A,(FNT_BID) + LD D,A + CALL SYS_PEEK + LD A,E + POP DE RET +#ENDIF ; -; PRINT CHARACTER TYPE (SERIAL ATTRIBUTE IN C) +FNT_BID .DB 0 ; BANK CONTAINING FONT DATA +FNT_PTR .DW 0 ; POINTER TO NEXT BYTE OF DATA ; -PS_PRTST: - LD HL,PS_STPPT - BIT 6,C - JP NZ,PS_PRT18 ; PARALLEL TYPE? - LD HL,PS_STRS232 ; ASSUME RS-232 - BIT 7,C ; 0=RS-232, 1=TERMINAL - JP Z,PS_PRT18 ; HANDLE TERMINAL TYPE - LD HL,PS_STTERM ; TYPE IS TERMINAL - JP PS_PRT18 +HB_UTIL_END .EQU $ ; -; PRINT SERIAL CONFIG (UNIT IN E, ATTRIBUTE IN C) +;================================================================================================== +; DISPLAY SUMMARY OF ATTACHED UNITS/DEVICES +;================================================================================================== ; -PS_PRTSC: - BIT 6,C ; PARALLEL TYPE? - JR NZ,PSPRTPC0 - - BIT 7,C ; 0=RS-232, 1=TERMINAL - JP NZ,PS_PRTSC1 ; PRINT TERMINAL CONFIG -; - ; PRINT RS-232 CONFIG - LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG - LD C,E ; SET SERIAL UNIT NUM - RST 08 ; DE:HL := BAUD RATE - LD A,D ; TEST FOR $FF - AND E - INC A ; SET Z IF DE == $FF - JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED +HB_PRTSUM_BEG .EQU $ ; PS_PRTSC0: ; PRINT BAUD RATE @@ -8526,209 +8547,6 @@ PS_PRTSC0: ; RET ; -PSPRTPC0: - LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG - LD C,E ; SET PARALLEL UNIT NUM - RST 08 ; DE:HL := I/O SETTING - LD A,D ; TEST FOR $FF - AND E - INC A ; SET Z IF DE == $FF - JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED -; -PS_PRTPC0: - LD C,E ; DISPLAY PIO TYPE - LD A,11000000B ; WHICH IS DEFINE BY - LD DE,PIO_MODE_STR ; BITS 6 AND 7 - JP PRTIDXMSK -; RET ; TRICK RETURN -; -PS_PRTSC1: - ; PRINT TERMINAL CONFIG - LD A,C ; GET ATTRIBUTE VALUE - CP $BF ; NO ATTACHED VDA - JR Z,PS_PRTSC2 - PRTS("Video $") ; FORMATTING - AND $0F ; ISOLATE VIDEO UNIT NUM - CALL PRTDECB ; PRINT IT - CALL PC_COMMA -#IF (VDAEMU == EMUTYP_TTY) - PRTS("TTY$") -#ENDIF -#IF (VDAEMU == EMUTYP_ANSI) - PRTS("ANSI$") -#ENDIF - RET -; -PS_PRTSC2: - PRTS("Term Module$") - CALL PC_COMMA - PRTS("ANSI$") - RET -; -; PRINT ONE LINE VIDEO UNIT/DEVICE INFO, VIDEO UNIT INDEX IN C -; -PS_VIDEO: - PUSH BC ; SAVE UNIT INDEX FOR LATER -; - ; UNIT COLUMN - PRTS("Video $") - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT - PRTS(" $") ; PAD TO NEXT COLUMN -; - ; DEVICE COLUMN - LD B,BF_VDADEV ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES - PUSH BC ; SAVE ATTRIBUTES - LD HL,PS_VDVDU ; POINT TO VIDEO DEVICE TYPE NAME TABLE - CALL PS_PRTDEV ; PRINT VIDEO DEVICE NMEMONIC PADDED TO FIELD WIDTH - POP DE ; RECOVER ATTRIBUTES - PUSH DE ; SAVE ATTRIBUTES AGAIN - CALL PS_PRTVT ; PRINT VIDEO TYPE - POP DE ; RESTORE ATTRIBUTES - POP BC ; RESTORE UNIT NUM - CALL PS_PRTVC ; PRINT VIDEO CONFIG -; - CALL NEWLINE - RET -; -; PRINT VIDEO TYPE (VIDEO ATTRIBUTE IN E) -; -PS_PRTVT: - LD HL,PS_VTCRT ; ASSUME CRT - JP PS_PRT18 ; PRINT -; -; PRINT VIDEO CONFIG (UNIT IN C, ATTRIBUTE IN E) -; -PS_PRTVC: - PRTS("Text$") - CALL PC_COMMA - LD B,BF_VDAQRY ; FUNC: QUERY FOR VDA CONFIG - RST 08 ; D:=ROWS, E:=COLS - LD A,E - CALL PRTDECB - LD A,'x' - CALL COUT - LD A,D - CALL PRTDECB - RET -; -; PRINT SOUND CONFIG -; -PS_SOUND: - PUSH BC - - ; UNIT COLUMN - PRTS("Sound $") - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT - CP 10 ; CHECK FOR MULTIPLE DIGITS - CALL C,PC_SPACE ; EXTRA SPACE IF NEEDED - PRTS(" $") ; PAD TO NEXT COLUMN - - ; DEVICE COLUMN - - PUSH BC - LD E,C - XOR A - LD DE,PS_SDSND ; POINT TO DEVICE TYPE NAME TABLE - CALL PRTIDXDEA ; PRINT DEVICE NMEMONIC PADDED TO FIELD WIDTH - LD A,C ; MOVE UNIT NUM TO A - CALL PRTDECB ; PRINT IT - CALL PC_COLON - LD A,(PRTIDXCNT) - SUB 12-1 ; SUBTRACT FIELD WIDTH (LESS THE COLON) - NEG ; MAKE IT A POSITIVE NUMBER - CALL PS_PAD ; PAD AS NEEDED - POP BC - - ; DEVICE TYPE -; - LD B,BF_SNDQUERY ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - LD E,BF_SNDQ_DEV - RST 08 - PUSH BC - LD A,B - LD DE,PS_SDSN76489 - CALL PRTIDXDEA - CALL PS_PAD18 - POP BC -; - ; DEVICE CHARACTERISTICS -; - LD B,BF_SNDQUERY ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C - LD E,BF_SNDQ_CHCNT - RST 08 - LD A,B - CALL PRTDECB - LD A,'+' - CALL COUT - LD A,C - CALL PRTDECB - PRTS(" CHANNELS$") - CALL NEWLINE -; - POP BC - RET -; -; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE -; -PS_PRTDEV: - EX DE,HL - LD A,H ; TYPE ID - CALL PRTIDXDEA ; PRINT TYPE LABEL - LD A,L ; UNIT NUMBER - CALL PRTDECB ; PRINT NUM, ASSUME 1 CHAR - CALL PC_COLON ; PRINT COLON - LD A,(PRTIDXCNT) - SUB 12-2+1 ; 12 CHAR FIELD - 1 POS FOR UNIT NUM AND 1 POS FOR COLON - NEG - CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) - RET -; -; PRINT DEVICE MNEMONIC, DEVTYP/NUM SPECIFIED IN DE -; -PS_PRTNUL: - LD HL,PS_STRNUL - ; FALL THRU TO PS_PRT -; -; PRINT STRING AT (HL), $ TERM, RETURN CHARS PRINTED IN C -; -PS_PRT: LD C,0 ; INIT CHAR COUNT -PS_PRT1: - LD A,(HL) ; GET CHAR - INC HL ; BUMP INDEX - CP '$' ; TERM? - RET Z ; IF SO, DONE - CALL COUT ; PRINT IT - INC C ; BUMP COUNTER - JR PS_PRT1 ; AND LOOP -; -; PAD 18 CHARACTER FIELD -; -PS_PAD18: - LD A,(PRTIDXCNT) - LD C,A - JR PS_PRT18A -; -; PRINT STRING AT HL IN 18 CHARACTER FIELD -; -PS_PRT18: - CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED -PS_PRT18A: - LD A,18 ; 18 CHAR FIELD - SUB C -; CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) -; -; PAD N SPACES SPECIFIED IN A -; -PS_PAD: LD B,A - LD A,' ' -PS_PAD1: - CALL COUT - DJNZ PS_PAD1 - RET -; HB_CPU_STR: .TEXT " Z80$" .TEXT " Z80180$" .TEXT " Z8S180-K$" @@ -8736,123 +8554,8 @@ HB_CPU_STR: .TEXT " Z80$" .TEXT " Z80280$" .TEXT " eZ80$" ; -PS_STRNUL .TEXT "--$" ; DISPLAY STRING FOR NUL VALUE -; -; DISK DEVICE STRINGS -; -PS_DDMD .TEXT "MD$" -PS_DDFD .TEXT "FD$" -PS_DDRF .TEXT "RF$" -PS_DDIDE .TEXT "IDE$" -PS_DDATAPI .TEXT "ATAPI$" -PS_DDPPIDE .TEXT "PPIDE$" -PS_DDSD .TEXT "SD$" -PS_DDPRPSD .TEXT "PRPSD$" -PS_DDPPPSD .TEXT "PPPSD$" -PS_DDHDSK .TEXT "HDSK$" -PS_DDPPA .TEXT "PPA$" -PS_DDIMM .TEXT "IMM$" -PS_DDSYQ .TEXT "SYQ$" -PS_DDCHUSB .TEXT "CHUSB$" -PS_DDCHSD .TEXT "CHSD$" -; -; DISK TYPE STRINGS -; -PS_DTFLOP .TEXT "Floppy Disk$" -PS_DTHARD .TEXT "Hard Disk$" -PS_DTCF .TEXT "CompactFlash$" -PS_DTSD .TEXT "SD Card$" -PS_DTUSB .TEXT "USB Drive$" -PS_DTROM .TEXT "ROM Disk$" -PS_DTRAM .TEXT "RAM Disk$" -PS_DTFSH .TEXT "Flash ROM$" -PS_DTRF .TEXT "RAM Floppy$" -PS_DTCD .TEXT "CD-ROM$" -PS_DTCRT .TEXT "Cartridge$" -PS_DTOTHER .TEXT "???$" -; -; FLOPPY ATTRIBUTE STRINGS -; -PS_FLP_FSTR: .TEXT "8\",$" ; PS_FLP8 - .TEXT "5.25\",$" ; PS_FLP5 - .TEXT "3.5\",$" ; PS_FLP3 - .TEXT "???\",$" ; PS_FLPN -; -PS_FLP_SSTR: .TEXT "SS/$" ; PS_FLPSS - .TEXT "DS/$" ; PS_FLPDS -; -PS_FLP_DSTR: .TEXT "SD$" ; PS_FLPSD - .TEXT "DD$" ; PS_FLPDD - .TEXT "HD$" ; PS_FLPHD - .TEXT "ED$" ; PS_FLPED -; -; CHARACTER DEVICE STRINGS -; -PS_SDUART .TEXT "UART$" -PS_SDASCI .TEXT "ASCI$" -PS_SDTERM .TEXT "TERM$" -PS_SDPRPCON .TEXT "PRPCON$" -PS_SDPPPCON .TEXT "PPPCON$" -PS_SDSIO .TEXT "SIO$" -PS_SDACIA .TEXT "ACIA$" -PS_SDPIO .TEXT "PIO$" -PS_SDUF .TEXT "UF$" -PS_SDDUART .TEXT "DUART$" -PS_SDZ2U .TEXT "Z2U$" -PS_SDLPT .TEXT "LPT$" -PS_SDESPCON .TEXT "ESPCON$" -PS_SDESPSER .TEXT "ESPSER$" -PS_SDSCON .TEXT "SCON$" -PS_SDEF .TEXT "EF$" -PS_SDSSER .TEXT "SSER$" -PS_SDEZ80 .TEXT "EZ80$" -; -; CHARACTER SUB TYPE STRINGS -; -PS_STRS232 .TEXT "RS-232$" -PS_STTERM .TEXT "Terminal$" -PS_STPPT .TEXT "Parallel$" -; PS_STPARMAP .DB "NONENMNS" ; -; PARALLEL TYPE STRINGS -; -PIO_MODE_STR: .TEXT "Output$" - .TEXT "Input$" - .TEXT "Bidirectional$" - .TEXT "BitCtrl$" -; -; VIDEO DEVICE STRINGS -; -PS_VDVDU .TEXT "VDU$" -PS_VDCVDU .TEXT "CVDU$" -PS_VDGDC .TEXT "GDC$" -PS_VDTMS .TEXT "TMS$" -PS_VDVGA .TEXT "VGA$" -PS_VDVRC .TEXT "VRC$" -PS_VDEF .TEXT "EF$" -PS_VDFV .TEXT "FV$" -; -; VIDEO TYPE STRINGS -; -PS_VTCRT .TEXT "CRT$" -; -; SOUND DEVICE STRINGS -; -PS_SDSND .TEXT "SND$" -; -; SOUND TYPE STRINGS -; -PS_SDSN76489 .TEXT "SN76489$" -PS_SDAY38910 .TEXT "AY-3-8910$" -PS_SDBITMODE .TEXT "I/O PORT$" -PS_SDYM2612 .TEXT "YM2612$" -; -; 0 1 2 3 4 5 6 7 -; 01234567890123456789012345678901234567890123456789012345678901234567890123456789 -PS_STRHDR .TEXT "Unit Device Type Capacity/Mode\r\n" - .TEXT "---------- ---------- ---------------- --------------------\r\n$" -; HB_PRTSUM_END .EQU $ ; ;================================================================================================== @@ -8971,6 +8674,15 @@ SIZ_DS5RTC .EQU $ - ORG_DS5RTC MEMECHO " bytes.\n" #ENDIF ; +#IF (PCRTCENABLE) +ORG_PCRTC .EQU $ + #INCLUDE "pcrtc.asm" +SIZ_PCRTC .EQU $ - ORG_PCRTC + MEMECHO "PCRTC occupies " + MEMECHO SIZ_PCRTC + MEMECHO " bytes.\n" +#ENDIF +; #IF (INTRTCENABLE) ORG_INTRTC .EQU $ #INCLUDE "intrtc.asm" @@ -8980,6 +8692,15 @@ SIZ_INTRTC .EQU $ - ORG_INTRTC MEMECHO " bytes.\n" #ENDIF ; +#IF (DS7RTCENABLE) +ORG_DS7RTC .EQU $ + #INCLUDE "ds7rtc.asm" +SIZ_DS7RTC .EQU $ - ORG_DS7RTC + .ECHO "DS7RTC occupies " + .ECHO SIZ_DS7RTC + .ECHO " bytes.\n" +#ENDIF +; #IF (RP5RTCENABLE) ORG_RP5RTC .EQU $ #INCLUDE "rp5rtc.asm" @@ -9160,6 +8881,15 @@ SIZ_FV .EQU $ - ORG_FV MEMECHO " bytes.\n" #ENDIF ; +#IF (XOSENABLE) +ORG_XOS .EQU $ + #INCLUDE "xosera.asm" +SIZ_XOS .EQU $ - ORG_XOS + MEMECHO "XOS occupies " + MEMECHO SIZ_XOS + MEMECHO " bytes.\n" +#ENDIF +; #IF (DMAENABLE) ORG_DMA .EQU $ #INCLUDE "dma.asm" @@ -9398,6 +9128,41 @@ SIZ_YM2612 .EQU $ - ORG_YM2612 MEMECHO " bytes.\n" #ENDIF ; +#IF (CHNATIVEENABLE) +ORG_CHNATIVE .EQU $ + #INCLUDE "ch376.asm" +SIZ_CHNATIVE .EQU $ - ORG_CHNATIVE + MEMECHO "CH376 Native occupies " + MEMECHO SIZ_CHNATIVE + MEMECHO " bytes.\n" +#ENDIF +; +#IF (CHSCSIENABLE) +ORG_CHSCSI .EQU $ + #INCLUDE "ch376scsi.asm" +SIZ_CHSCSI .EQU $ - ORG_CHSCSI + MEMECHO " CH376 SCSI Mass Storage occupies " + MEMECHO SIZ_CHSCSI + MEMECHO " bytes.\n" +#ENDIF +; +#IF (CHUFIENABLE) +ORG_CHUFI .EQU $ + #INCLUDE "ch376ufi.asm" +SIZ_CHUFI .EQU $ - ORG_CHUFI + MEMECHO " CH376 UFI Floppy Storage occupies " + MEMECHO SIZ_CHUFI + MEMECHO " bytes.\n" +#ENDIF +; +#IF (USBKYBENABLE) +ORG_UKY .EQU $ + #INCLUDE "ch376kyb.asm" +SIZ_UKY .EQU $ - ORG_UKY + MEMECHO " CH376 USB Keyboard occupies " + MEMECHO SIZ_UKY + MEMECHO " bytes.\n" +#ENDIF ; #IF (CPUFAM == CPU_EZ80) MEMECHO "EZ80 DRIVERS\n" @@ -9458,57 +9223,88 @@ ORG_FONTS .EQU $ ; MEMECHO "FONTS" ; -#IFDEF USEFONT8X8 -FONT8X8: +#IF !ROMFONTS ; -; FOR NOW, WE NEVER COMPRESS THE 8X8 FONT. SEE TMS DRIVER. +; HIGH BIT OF THE FONTID BYTE INDICATES THAT THE FONT DATA IS COMPRESSED ; - #IF USELZSA2 & FALSE - #INCLUDE "font8x8c.asm" + #IF USELZSA2 +FNT_CMPMASK .EQU $80 #ELSE - #INCLUDE "font8x8u.asm" +FNT_CMPMASK .EQU $00 + #ENDIF +; +; FONT LOCATION MAP +; +FNT_MAP: + .DB 'F','M' ; TABLE SIGNATURE + #IFDEF USEFONT6X8 + ; FOR NOW, WE NEVER COMPRESS THE 6X8 FONT. SEE TMS DRIVER. +;;; .DB FONTID_6X8 | FNT_CMPMASK + .DB FONTID_6X8 + .DW FONT6X8 + #ENDIF +; + #IFDEF USEFONT8X8 + .DB FONTID_8X8 | FNT_CMPMASK + .DW FONT8X8 + #ENDIF +; + #IFDEF USEFONT8X11 + .DB FONTID_8X11 | FNT_CMPMASK + .DW FONT8X11 + #ENDIF +; + #IFDEF USEFONT8X16 + .DB FONTID_8X16 | FNT_CMPMASK + .DW FONT8X16 + #ENDIF +; + .DB 0 ; END OF TABLE +; + #IFDEF USEFONT6X8 +FONT6X8: +; +; FOR NOW, WE NEVER COMPRESS THE 6X8 FONT. SEE TMS DRIVER. +; + #IF USELZSA2 & FALSE + #INCLUDE "font6x8c.asm" + #ELSE + #INCLUDE "font6x8u.asm" + #ENDIF + MEMECHO " 6X8" #ENDIF +; + #IFDEF USEFONT8X8 +FONT8X8: +; + #IF USELZSA2 + #INCLUDE "font8x8c.asm" + #ELSE + #INCLUDE "font8x8u.asm" + #ENDIF MEMECHO " 8X8" -#ENDIF + #ENDIF ; -#IFDEF USEFONT8X11 + #IFDEF USEFONT8X11 FONT8X11: - #IF USELZSA2 - #INCLUDE "font8x11c.asm" - #ELSE - #INCLUDE "font8x11u.asm" - #ENDIF + #IF USELZSA2 + #INCLUDE "font8x11c.asm" + #ELSE + #INCLUDE "font8x11u.asm" + #ENDIF MEMECHO " 8X11" -#ENDIF + #ENDIF ; -#IFDEF USEFONT8X16 + #IFDEF USEFONT8X16 FONT8X16: - #IF USELZSA2 - #INCLUDE "font8x16c.asm" - #ELSE - #INCLUDE "font8x16u.asm" - #ENDIF + #IF USELZSA2 + #INCLUDE "font8x16c.asm" + #ELSE + #INCLUDE "font8x16u.asm" + #ENDIF MEMECHO " 8X16" -#ENDIF -; -#IFDEF USEFONTCGA -FONTCGA: - #IF USELZSA2 - #INCLUDE "fontcgac.asm" - #ELSE - #INCLUDE "fontcgau.asm" #ENDIF - MEMECHO " CGA" -#ENDIF ; -#IFDEF USEFONTVGARC -FONTVGARC: - #IF USELZSA2 - #INCLUDE "fontvgarcc.asm" - #ELSE - #INCLUDE "fontvgarcu.asm" - #ENDIF - MEMECHO " VGARC" #ENDIF ; SIZ_FONTS .EQU $ - ORG_FONTS @@ -9539,6 +9335,8 @@ HB_BATCOND .DB 0 ; BATTERY CONDITION (0=LOW, 1=OK) ; RTCDEFVAL .DB RTCDEF ; STORAGE FOR RTC DEFAULT VALUE ; +INTSENAB .DB 0 ; INTERRUPTS ENABLED +; #IF (BT_REC_TYPE != BT_REC_NONE) HB_BOOT_REC .DB 0 ; BOOT MODE (0=NORMAL, 1=RECOVERY MODE) #ENDIF diff --git a/Source/HBIOS/hbios.inc b/Source/HBIOS/hbios.inc index c542a497..50fc8be7 100644 --- a/Source/HBIOS/hbios.inc +++ b/Source/HBIOS/hbios.inc @@ -71,7 +71,7 @@ BF_SND .EQU $50 BF_SNDRESET .EQU BF_SND + 0 ; RESET SOUND SYSTEM BF_SNDVOL .EQU BF_SND + 1 ; REQUEST SOUND VOL - L CONTAINS VOLUME (255 MAX, 0 SILENT) - SCALED AS REQUIRED BY DRIVER (EG: MAPS TO JUST 4 BIT RESOLUTION FOR SN76489) BF_SNDPRD .EQU BF_SND + 2 ; REQUEST SOUND PERIOD - HL CONTAINS DRIVER SPECIFIC VALUE -BF_SNDNOTE .EQU BF_SND + 3 ; REQUEST NOTE - L CONTAINS NOTE - EACH VALUE IS QUARTER NOTE +BF_SNDNOTE .EQU BF_SND + 3 ; REQUEST NOTE - L CONTAINS NOTE - EACH VALUE IS AN EIGHTH TONE BF_SNDPLAY .EQU BF_SND + 4 ; INITIATE THE REQUESTED SOUND COMMAND BF_SNDQUERY .EQU BF_SND + 5 ; E IS SUBFUNCTION BF_SNDDURATION .EQU BF_SND + 6 ; REQUEST DURATION HL MILLISECONDS @@ -420,6 +420,7 @@ DIODEV_IMM .EQU $0B DIODEV_SYQ .EQU $0C DIODEV_CHUSB .EQU $0D DIODEV_CHSD .EQU $0E +DIODEV_USB .EQU $0F ; ; RTC DEVICE IDS ; @@ -431,6 +432,7 @@ RTCDEV_DS7 .EQU $04 ; DS1307 (I2C) RTCDEV_RP5 .EQU $05 ; RP5C01 RTCDEV_DS5 .EQU $06 ; DS1305 (SPI) RTCDEV_EZ80 .EQU $07 ; EZ80 ON-CHIP RTC +RTCDEV_PC .EQU $08 ; PC style parallel RTC ; ; DSKY DEVICE IDS ; @@ -450,6 +452,7 @@ VDADEV_VGA .EQU $04 ; ECB VGA3 - HITACHI HD6445 VDADEV_VRC .EQU $05 ; VGARC VDADEV_EF .EQU $06 ; EF9345 VDADEV_FV .EQU $07 ; S100 FPGA VGA +VDADEV_XOSERA .EQU $08 ; XOSERA RCBUS ; ; SOUND DEVICE IDS ; diff --git a/Source/HBIOS/hwmon.asm b/Source/HBIOS/hwmon.asm new file mode 100644 index 00000000..9c7121ac --- /dev/null +++ b/Source/HBIOS/hwmon.asm @@ -0,0 +1,30 @@ +; +;============================================================================= +; HWMON.ASM - BARE METAL HARDWARE MONITOR +;============================================================================= +; +; THIS IS JUST A STUB FOR NOW. +; +#INCLUDE "std.asm" +; +; MONITOR WILL BE LOADED AT HWMON_LOC +; + .ORG HWMON_LOC +; +; IT IS CRITICAL THAT THE FINAL BINARY BE EXACTLY HWMON_SIZ BYTES. +; THIS GENERATES FILLER AS NEEDED. IT WILL ALSO FORCE AN ASSEMBLY +; ERROR IF THE SIZE EXCEEDS THE SPACE ALLOCATED. +; +SLACK .EQU (HWMON_END - $) +; +#IF (SLACK < 0) + .ECHO "*** HWMON IS TOO BIG!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +; + .FILL SLACK,$00 + .ECHO "Hardware Monitor space remaining: " + .ECHO SLACK + .ECHO " bytes.\n" +; + .END diff --git a/Source/HBIOS/imgpad2.asm b/Source/HBIOS/imgpad2.asm deleted file mode 100644 index 43099f3d..00000000 --- a/Source/HBIOS/imgpad2.asm +++ /dev/null @@ -1,10 +0,0 @@ -#INCLUDE "std.asm" -; -SLACK .EQU $8000 - .FILL SLACK,00H -; - .ECHO "Padspace space created: " - .ECHO SLACK - .ECHO " bytes.\n" - - .END \ No newline at end of file diff --git a/Source/HBIOS/invntdev.asm b/Source/HBIOS/invntdev.asm new file mode 100644 index 00000000..164015b8 --- /dev/null +++ b/Source/HBIOS/invntdev.asm @@ -0,0 +1,712 @@ +;============================================================================== +; DEVIVE INVENTORY - Inventory Device +; Version June-2025 +;============================================================================== +; +; This was extracted from HBIOS and converted into a ROM Application +; +; This is a program CALLED from RomLoader, and is specific to RomWBW +;------------------------------------------------------------------------------ +; +; Change Log: +; 2025-06-30 [MAP] Initial Release copied from HBIOS.ASM +;______________________________________________________________________________ +; +; Include Files +; +#include "std.asm" ; standard RomWBW constants +; +;***************************************************************************** +; +; APPLICATION WILL WILL BE LOADED AT DEV_LOC. THEREFORE, THE CODE +; MUST "ORG" AT THIS ADDRESS. TO CHANGE THE LOAD LOCATION OF THIS +; CODE, YOU CAN UPDATE DEV_LOC IN LAYOUT.INC +; + .ORG DEV_LOC +; +;***************************************************************************** +; INIT CODE +;***************************************************************************** +; +; +;***************************************************************************** +; Main Code starts here +;***************************************************************************** +; +PRTSUM: + CALL NEWLINE2 ; SKIP A LINE + LD DE,PS_STRHDR ; POINT TO HEADER + CALL WRITESTR ; PRINT IT +; + LD C,BF_SYSGET_CIOCNT ; CHARACTER DEVICES + LD HL,PS_SERIAL + CALL PRT_ALLD +; + LD C,BF_SYSGET_DIOCNT ; DISK DRIVES + LD HL,PS_DISK + CALL PRT_ALLD +; + LD C,BF_SYSGET_VDACNT ; VIDEO DEVICES + LD HL,PS_VIDEO + CALL PRT_ALLD +; + LD C,BF_SYSGET_SNDCNT ; SOUND DEVICES + LD HL,PS_SOUND + CALL PRT_ALLD + RET +; +;***************************************************************************** +; Supporting Code Stars Here +;***************************************************************************** +; +PRT_ALLD: + LD B,BF_SYSGET ; FUNC: SYSTEM INFO GET + RST 08 ; E := UNIT COUNT + LD B,E ; MOVE TO B FOR LOOP COUNT + LD A,E ; MOVE TO ACCUM + OR A ; SET FLAGS + RET Z ; IF NONE, JUST RETURN + LD C,0 ; C WILL BE UNIT INDEX +PRT_ALLD1: + PUSH BC ; SAVE LOOP CONTROL + PUSH DE + PUSH HL + CALL JPHL ; CALL THE ROUTINE PASSED IN HL + POP HL + POP DE + POP BC ; RESTORE LOOP CONTROL + INC C ; BUMP UNIT INDEX + DJNZ PRT_ALLD1 ; LOOP THRU ALL DEVICES + RET +; +; PRINT ONE LINE DISK UNIT/DEVICE INFO, DISK UNIT INDEX IN C +; +PS_DISK: + PUSH BC ; SAVE UNIT INDEX FOR LATER +; + ; UNIT COLUMN + PRTS("Disk $") + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT + CP 10 ; CHECK FOR MULTIPLE DIGITS + CALL C,PC_SPACE ; EXTRA SPACE IF NEEDED + PRTS(" $") ; PAD TO NEXT COLUMN +; + ; DEVICE COLUMN + LD B,BF_DIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + RST 08 ; DE:=DEVTYP/NUM, C:=DISK ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES + LD HL,PS_DDMD ; POINT TO DISK DEVICE TYPE NAME TABLE + CALL PS_PRTDEV ; PRINT DISK DEVICE NMEMONIC PADDED TO FIELD WIDTH + POP DE ; RECOVER ATTRIBUTES TO DE + PUSH DE ; SAVE ATTRIBUTES AGAIN + CALL PS_PRTDT ; PRINT DISK TYPE + POP DE ; RESTORE ATTRIBUTES + POP BC ; RESTORE UNIT NUM + CALL PS_PRTDC ; PRINT DISK CAPACITY +; + CALL NEWLINE + RET +; +; PRINT DISK TYPE (DISK ATTRIBUTE IN E) +; +PS_PRTDT: + LD A,E ; ATTRIBUTES TO A + BIT 7,A ; FLOPPY BIT SET? + LD HL,PS_DTFLOP ; ASSUME FLOPPY + JP NZ,PS_PRT18 ; IF FLOPPY, JUMP AHEAD + LD C,E + LD DE,PS_DTHARD + LD A,00001111B + CALL PRTIDXMSK + CALL PS_PAD18 ; PAD TO 18 SPACES + RET +; +; PRINT DISK CAPACITY (UNIT IN C, ATTRIBUTE IN E) +; +PS_PRTDC: +; + LD A,E ; ATTRIBUTE TO ACCUM + BIT 7,A ; TEST FOR FLOPPY + JR NZ,PS_PRTDC2 ; HANDLE FLOPPY + AND $0F ; ISOLATE TYPE BITS + CP 4 ; ROM DISK? + JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB + CP 5 ; RAM DISK? + JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB + CP 7 ; FLASH DISK? + JR Z,PS_PRTDC1 ; PRINT CAPACITY IN KB +; + ; PRINT HARD DISK STORAGE SIZE IN MB + LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY + RST 08 ; DE:HL := BLOCKS + JP NZ,PS_PRTNUL ; MEDIA PROBLEM + RES 7,D ; CLEAR LBA BIT + LD B,11 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB + CALL SRL32 ; RIGHT SHIFT + CALL PRTDEC32 ; PRINT DWORD IN DECIMAL + PRTS("MB$") ; PRINT SUFFIX + CALL PC_COMMA + PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA + RET ; DONE +; +PS_PRTDC1: + ; PRINT ROM/RAM DISK CAPACITY IN KB + LD B,BF_DIOCAP ; HBIOS FUNC: GET CAPACTIY + RST 08 ; DE:HL := BLOCKS + JP NZ,PS_PRTNUL ; MEDIA PROBLEM + RES 7,D ; CLEAR LBA BIT + LD B,1 ; 11 BIT SHIFT TO CONVERT BLOCKS --> MB + CALL SRL32 ; RIGHT SHIFT + CALL PRTDEC32 ; PRINT DWORD IN DECIMAL + PRTS("KB$") ; PRINT SUFFIX + CALL PC_COMMA + PRTS("LBA$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA + RET ; DONE +; +PS_PRTDC2: + LD C,E ; ATTRIBUTE TO C FOR SAFE KEEPING +; + LD A,%00011000 ; DISPLAY FORM FACTOR + LD DE,PS_FLP_FSTR ; WHICH IS DEFINED IN + CALL PRTIDXMSK ; BITS 5 AND 6. +; + LD A,%00000100 ; DISPLAY SIDES + LD DE,PS_FLP_SSTR ; WHICH IS DEFINED + CALL PRTIDXMSK ; IN BIT 4 +; + LD A,%00000011 ; DISPLAY DENSITY + LD DE,PS_FLP_DSTR ; WHICH IS DEFINED IN + CALL PRTIDXMSK ; BITS 2 AND 3. +; + CALL PC_COMMA + PRTS("CHS$") ; FOR NOW, WE ASSUME HARD DISK DOES LBA +; + RET ; DONE +; +; PRINT ONE LINE SERIAL UNIT/DEVICE INFO, SERIAL UNIT INDEX IN C +; +PS_SERIAL: + PUSH BC ; SAVE UNIT INDEX FOR LATER +; + ; UNIT COLUMN + PRTS("Char $") + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT + PRTS(" $") ; PAD TO NEXT COLUMN +; + ; DEVICE COLUMN + LD B,BF_CIODEVICE ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + RST 08 ; DE:=DEVTYP/NUM, C:=DEVICE ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES + LD HL,PS_SDUART ; POINT TO SERIAL DEVICE TYPE NAME TABLE + CALL PS_PRTDEV ; PRINT SERIAL DEVICE NMEMONIC PADDED TO FIELD WIDTH + POP BC ; RECOVER ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES AGAIN + CALL PS_PRTST ; PRINT SERIAL TYPE + POP BC ; RESTORE ATTRIBUTES + POP DE ; RESTORE UNIT NUM TO E + CALL PS_PRTSC ; PRINT SERIAL CONFIG +; + CALL NEWLINE + RET +; +; PRINT CHARACTER TYPE (SERIAL ATTRIBUTE IN C) +; +PS_PRTST: + LD HL,PS_STPPT + BIT 6,C + JP NZ,PS_PRT18 ; PARALLEL TYPE? + LD HL,PS_STRS232 ; ASSUME RS-232 + BIT 7,C ; 0=RS-232, 1=TERMINAL + JP Z,PS_PRT18 ; HANDLE TERMINAL TYPE + LD HL,PS_STTERM ; TYPE IS TERMINAL + JP PS_PRT18 +; +; PRINT SERIAL CONFIG (UNIT IN E, ATTRIBUTE IN C) +; +PS_PRTSC: + BIT 6,C ; PARALLEL TYPE? + JR NZ,PSPRTPC0 + + BIT 7,C ; 0=RS-232, 1=TERMINAL + JP NZ,PS_PRTSC1 ; PRINT TERMINAL CONFIG +; + ; PRINT RS-232 CONFIG + LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG + LD C,E ; SET SERIAL UNIT NUM + RST 08 ; DE:HL := BAUD RATE + LD A,D ; TEST FOR $FF + AND E + INC A ; SET Z IF DE == $FF + JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED +; +PS_PRTSC0: + ; PRINT BAUD RATE + PUSH DE ; PRESERVE DE + LD A,D + AND $1F ; ISOLATE ENCODED BAUD RATE + LD L,A ; PUT IN L + LD H,0 ; H IS ALWAYS ZERO + LD DE,75 ; BAUD RATE DECODE CONSTANT + CALL DECODE ; DE:HL := BAUD RATE + LD BC,HB_BCDTMP ; POINT TO TEMP BCD BUF + CALL BIN2BCD ; CONVERT TO BCD + CALL PRTBCD ; AND PRINT IN DECIMAL + POP DE ; RESTORE DE +; + ; PRINT DATA BITS + PUSH DE ; PRESERVE DE + CALL PC_COMMA ; FORMATTING + LD A,E ; GET CONFIG BYTE + AND $03 ; ISOLATE DATA BITS VALUE + ADD A,'5' ; CONVERT TO CHARACTER + CALL COUT ; AND PRINT + POP DE ; RESTORE DE +; + ; PRINT PARITY + PUSH DE ; PRESERVE DE + CALL PC_COMMA ; FORMATTING + LD A,E ; GET CONFIG BYTE + RRCA ; SHIFT RELEVANT BITS + RRCA ; ... + RRCA ; ... + AND $07 ; AND ISOLATE DATA BITS VALUE + LD HL,PS_STPARMAP ; CHARACTER LOOKUP TABLE + CALL ADDHLA ; APPLY OFFSET + LD A,(HL) ; GET CHARACTER + CALL COUT ; AND PRINT + POP DE ; RESTORE DE +; + ; PRINT STOP BITS + CALL PC_COMMA ; FORMATTING + LD A,E ; GET CONFIG BYTE + RRCA ; SHIFT RELEVANT BITS + RRCA ; ... + AND $01 ; AND ISOLATE DATA BITS VALUE + ADD A,'1' ; MAKE IT A CHARACTER + CALL COUT ; AND PRINT +; + RET +; +PSPRTPC0: + LD B,BF_CIOQUERY ; HBIOS FUNC: GET CIO CONFIG + LD C,E ; SET PARALLEL UNIT NUM + RST 08 ; DE:HL := I/O SETTING + LD A,D ; TEST FOR $FF + AND E + INC A ; SET Z IF DE == $FF + JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED +; +PS_PRTPC0: + LD C,E ; DISPLAY PIO TYPE + LD A,11000000B ; WHICH IS DEFINE BY + LD DE,PIO_MODE_STR ; BITS 6 AND 7 + JP PRTIDXMSK +; RET ; TRICK RETURN +; +PS_PRTSC1: + ; PRINT TERMINAL CONFIG + LD A,C ; GET ATTRIBUTE VALUE + CP $BF ; NO ATTACHED VDA + JR Z,PS_PRTSC2 + PRTS("Video $") ; FORMATTING + AND $0F ; ISOLATE VIDEO UNIT NUM + CALL PRTDECB ; PRINT IT + CALL PC_COMMA +#IF (VDAEMU == EMUTYP_TTY) + PRTS("TTY$") +#ENDIF +#IF (VDAEMU == EMUTYP_ANSI) + PRTS("ANSI$") +#ENDIF + RET +; +PS_PRTSC2: + PRTS("Term Module$") + CALL PC_COMMA + PRTS("ANSI$") + RET +; +; PRINT ONE LINE VIDEO UNIT/DEVICE INFO, VIDEO UNIT INDEX IN C +; +PS_VIDEO: + PUSH BC ; SAVE UNIT INDEX FOR LATER +; + ; UNIT COLUMN + PRTS("Video $") + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT, ASSUME SINGLE DIGIT + PRTS(" $") ; PAD TO NEXT COLUMN +; + ; DEVICE COLUMN + LD B,BF_VDADEV ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + RST 08 ; DE:=DEVTYP/NUM, H:=DISK ATTRIBUTES + PUSH BC ; SAVE ATTRIBUTES + LD HL,PS_VDVDU ; POINT TO VIDEO DEVICE TYPE NAME TABLE + CALL PS_PRTDEV ; PRINT VIDEO DEVICE NMEMONIC PADDED TO FIELD WIDTH + POP DE ; RECOVER ATTRIBUTES + PUSH DE ; SAVE ATTRIBUTES AGAIN + CALL PS_PRTVT ; PRINT VIDEO TYPE + POP DE ; RESTORE ATTRIBUTES + POP BC ; RESTORE UNIT NUM + CALL PS_PRTVC ; PRINT VIDEO CONFIG +; + CALL NEWLINE + RET +; +; PRINT VIDEO TYPE (VIDEO ATTRIBUTE IN E) +; +PS_PRTVT: + LD HL,PS_VTCRT ; ASSUME CRT + JP PS_PRT18 ; PRINT +; +; PRINT VIDEO CONFIG (UNIT IN C, ATTRIBUTE IN E) +; +PS_PRTVC: + PRTS("Text$") + CALL PC_COMMA + LD B,BF_VDAQRY ; FUNC: QUERY FOR VDA CONFIG + RST 08 ; D:=ROWS, E:=COLS + LD A,E + CALL PRTDECB + LD A,'x' + CALL COUT + LD A,D + CALL PRTDECB + RET +; +; PRINT SOUND CONFIG +; +PS_SOUND: + PUSH BC + + ; UNIT COLUMN + PRTS("Sound $") + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT + CP 10 ; CHECK FOR MULTIPLE DIGITS + CALL C,PC_SPACE ; EXTRA SPACE IF NEEDED + PRTS(" $") ; PAD TO NEXT COLUMN + + ; DEVICE COLUMN + + PUSH BC + LD E,C + XOR A + LD DE,PS_SDSND ; POINT TO DEVICE TYPE NAME TABLE + CALL PRTIDXDEA ; PRINT DEVICE NMEMONIC PADDED TO FIELD WIDTH + LD A,C ; MOVE UNIT NUM TO A + CALL PRTDECB ; PRINT IT + CALL PC_COLON + LD A,(PRTIDXCNT) + SUB 12-1 ; SUBTRACT FIELD WIDTH (LESS THE COLON) + NEG ; MAKE IT A POSITIVE NUMBER + CALL PS_PAD ; PAD AS NEEDED + POP BC + + ; DEVICE TYPE +; + LD B,BF_SNDQUERY ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + LD E,BF_SNDQ_DEV + RST 08 + PUSH BC + LD A,B + LD DE,PS_SDSN76489 + CALL PRTIDXDEA + CALL PS_PAD18 + POP BC +; + ; DEVICE CHARACTERISTICS +; + LD B,BF_SNDQUERY ; FUNC=GET DEVICE INFO, UNIT NUM STILL IN C + LD E,BF_SNDQ_CHCNT + RST 08 + LD A,B + CALL PRTDECB + LD A,'+' + CALL COUT + LD A,C + CALL PRTDECB + PRTS(" CHANNELS$") + CALL NEWLINE +; + POP BC + RET +; +; PRINT DEVICE NMEMONIC, DEVTYP/NUM SPECIFIED IN DE +; +PS_PRTDEV: + EX DE,HL + LD A,H ; TYPE ID + CALL PRTIDXDEA ; PRINT TYPE LABEL + LD A,L ; UNIT NUMBER + CALL PRTDECB ; PRINT NUM, ASSUME 1 CHAR + CALL PC_COLON ; PRINT COLON + LD A,(PRTIDXCNT) + SUB 12-2+1 ; 12 CHAR FIELD - 1 POS FOR UNIT NUM AND 1 POS FOR COLON + NEG + CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) + RET +; +; PRINT DEVICE MNEMONIC, DEVTYP/NUM SPECIFIED IN DE +; +PS_PRTNUL: + LD HL,PS_STRNUL + ; FALL THRU TO PS_PRT +; +; PRINT STRING AT (HL), $ TERM, RETURN CHARS PRINTED IN C +; +PS_PRT: LD C,0 ; INIT CHAR COUNT +PS_PRT1: + LD A,(HL) ; GET CHAR + INC HL ; BUMP INDEX + CP '$' ; TERM? + RET Z ; IF SO, DONE + CALL COUT ; PRINT IT + INC C ; BUMP COUNTER + JR PS_PRT1 ; AND LOOP +; +; PAD 18 CHARACTER FIELD +; +PS_PAD18: + LD A,(PRTIDXCNT) + LD C,A + JR PS_PRT18A +; +; PRINT STRING AT HL IN 18 CHARACTER FIELD +; +PS_PRT18: + CALL PS_PRT ; PRINT $ TERM STRING AT (HL), C:=CHARS PRINTED +PS_PRT18A: + LD A,18 ; 18 CHAR FIELD + SUB C +; CALL PS_PAD ; PAD N SPACES (SPECIFIED IN A) +; +; PAD N SPACES SPECIFIED IN A +; +PS_PAD: LD B,A + LD A,' ' +PS_PAD1: + CALL COUT + DJNZ PS_PAD1 + RET +; +;***************************************************************************** +; Support Routines +;***************************************************************************** +; +; TODO Ideally we wouldnt import all these here, as they take up quite a +; bit of space. Util.asm needs to be broken up, or copy required code here +; +#include "util.asm" +#include "decode.asm" +#include "bcd.asm" +; +;======================================================================= +; Console character I/O helper routines (registers preserved) +;======================================================================= +; +#if (BIOS == BIOS_WBW) +; +; Output character from A +; +COUT: + ; Save all incoming registers + push af + push bc + push de + push hl +; + ; Output character to console via HBIOS + ld e,a ; output char to E + ld c,CIO_CONSOLE ; output to current HBIOS console + ld b,BF_CIOOUT ; HBIOS func: output char + rst 08 ; HBIOS outputs character +; + ; Restore all registers + pop hl + pop de + pop bc + pop af + ret +; +#endif +; +#if (BIOS == BIOS_UNA) +; +; Output character from A +; +COUT: + ; Save all incoming registers + push af + push bc + push de + push hl +; + ; Output character to console via UBIOS + ld e,a + ld bc,$12 + rst 08 +; + ; Restore all registers + pop hl + pop de + pop bc + pop af + ret +; +#endif +; +;=============================================================================== +; Static Strings and Data +;=============================================================================== +; +PS_STRNUL .TEXT "--$" ; DISPLAY STRING FOR NUL VALUE +; +; DISK DEVICE STRINGS +; +PS_DDMD .TEXT "MD$" +PS_DDFD .TEXT "FD$" +PS_DDRF .TEXT "RF$" +PS_DDIDE .TEXT "IDE$" +PS_DDATAPI .TEXT "ATAPI$" +PS_DDPPIDE .TEXT "PPIDE$" +PS_DDSD .TEXT "SD$" +PS_DDPRPSD .TEXT "PRPSD$" +PS_DDPPPSD .TEXT "PPPSD$" +PS_DDHDSK .TEXT "HDSK$" +PS_DDPPA .TEXT "PPA$" +PS_DDIMM .TEXT "IMM$" +PS_DDSYQ .TEXT "SYQ$" +PS_DDCHUSB .TEXT "CHUSB$" +PS_DDCHSD .TEXT "CHSD$" +PS_DDCHNATUSB .TEXT "USB$" +; +; DISK TYPE STRINGS +; +PS_DTFLOP .TEXT "Floppy Disk$" +PS_DTHARD .TEXT "Hard Disk$" +PS_DTCF .TEXT "CompactFlash$" +PS_DTSD .TEXT "SD Card$" +PS_DTUSB .TEXT "USB Drive$" +PS_DTROM .TEXT "ROM Disk$" +PS_DTRAM .TEXT "RAM Disk$" +PS_DTFSH .TEXT "Flash ROM$" +PS_DTRF .TEXT "RAM Floppy$" +PS_DTCD .TEXT "CD-ROM$" +PS_DTCRT .TEXT "Cartridge$" +PS_DTOUSBSCI .TEXT "SCSI$" +PS_DTOUSBUFI .TEXT "UFI$" +PS_DTOTHER .TEXT "???$" + +; +; FLOPPY ATTRIBUTE STRINGS +; +PS_FLP_FSTR: .TEXT "8\",$" ; PS_FLP8 + .TEXT "5.25\",$" ; PS_FLP5 + .TEXT "3.5\",$" ; PS_FLP3 + .TEXT "???\",$" ; PS_FLPN +; +PS_FLP_SSTR: .TEXT "SS/$" ; PS_FLPSS + .TEXT "DS/$" ; PS_FLPDS +; +PS_FLP_DSTR: .TEXT "SD$" ; PS_FLPSD + .TEXT "DD$" ; PS_FLPDD + .TEXT "HD$" ; PS_FLPHD + .TEXT "ED$" ; PS_FLPED +; +; CHARACTER DEVICE STRINGS +; +PS_SDUART .TEXT "UART$" +PS_SDASCI .TEXT "ASCI$" +PS_SDTERM .TEXT "TERM$" +PS_SDPRPCON .TEXT "PRPCON$" +PS_SDPPPCON .TEXT "PPPCON$" +PS_SDSIO .TEXT "SIO$" +PS_SDACIA .TEXT "ACIA$" +PS_SDPIO .TEXT "PIO$" +PS_SDUF .TEXT "UF$" +PS_SDDUART .TEXT "DUART$" +PS_SDZ2U .TEXT "Z2U$" +PS_SDLPT .TEXT "LPT$" +PS_SDESPCON .TEXT "ESPCON$" +PS_SDESPSER .TEXT "ESPSER$" +PS_SDSCON .TEXT "SCON$" +PS_SDSSER .TEXT "SSER$" +PS_SDEZ80 .TEXT "EZ80$" +; +; CHARACTER SUB TYPE STRINGS +; +PS_STRS232 .TEXT "RS-232$" +PS_STTERM .TEXT "Terminal$" +PS_STPPT .TEXT "Parallel$" +; +PS_STPARMAP .DB "NONENMNS" +; +; PARALLEL TYPE STRINGS +; +PIO_MODE_STR: .TEXT "Output$" + .TEXT "Input$" + .TEXT "Bidirectional$" + .TEXT "BitCtrl$" +; +; VIDEO DEVICE STRINGS +; +PS_VDVDU .TEXT "VDU$" +PS_VDCVDU .TEXT "CVDU$" +PS_VDGDC .TEXT "GDC$" +PS_VDTMS .TEXT "TMS$" +PS_VDVGA .TEXT "VGA$" +PS_VDVRC .TEXT "VRC$" +PS_VDEF .TEXT "EF$" +PS_VDFV .TEXT "FV$" +PS_VDXOSERA .TEXT "XOSERA$" +; +; VIDEO TYPE STRINGS +; +PS_VTCRT .TEXT "CRT$" +; +; SOUND DEVICE STRINGS +; +PS_SDSND .TEXT "SND$" +; +; SOUND TYPE STRINGS +; +PS_SDSN76489 .TEXT "SN76489$" +PS_SDAY38910 .TEXT "AY-3-8910$" +PS_SDBITMODE .TEXT "I/O PORT$" +PS_SDYM2612 .TEXT "YM2612$" +; +; 0 1 2 3 4 5 6 7 +; 01234567890123456789012345678901234567890123456789012345678901234567890123456789 +PS_STRHDR .TEXT "Unit Device Type Capacity/Mode\r\n" + .TEXT "---------- ---------- ---------------- --------------------\r\n$" +; +;=============================================================================== +; Working data +;=============================================================================== +; +HB_BCDTMP .FILL 5,0 ; BCD NUMBER STORAGE (TEMP) +; +;=============================================================================== +; +; IT IS CRITICAL THAT THE FINAL BINARY BE EXACTLY DEV_SIZ BYTES. +; THIS GENERATES FILLER AS NEEDED. IT WILL ALSO FORCE AN ASSEMBLY +; ERROR IF THE SIZE EXCEEDS THE SPACE ALLOCATED. +; +SLACK .EQU (DEV_END - $) +; +#IF (SLACK < 0) + .ECHO "*** INVENTORY SLICE IS TOO BIG!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +; + .FILL SLACK,$00 + .ECHO "INVNTDEV Device Inventory space remaining: " + .ECHO SLACK + .ECHO " bytes.\n" +; +;=============================================================================== +; +.END diff --git a/Source/HBIOS/invntslc.asm b/Source/HBIOS/invntslc.asm new file mode 100644 index 00000000..5aa3cdc8 --- /dev/null +++ b/Source/HBIOS/invntslc.asm @@ -0,0 +1,409 @@ +;============================================================================== +; SLICE INVENTORY - Inventory Slice +; Version June-2025 +;============================================================================== +; +; Author: Mark Pruden +; +; This is a SUBSET of SLABEL.ASM -> Please See this program also when +; making changes, as most of the code found here exists there also +; +; This is a program CALLED from RomLoader, and is specific to RomWBW +; +; See SLABEL.ASM for ALL other Notes about This program. +;------------------------------------------------------------------------------ +; +; Change Log: +; 2025-06-30 [MAP] Initial v1.0 release for distribution +; 2025-07-12 [MR] Minor tweak to partially tidy up output formatting +;______________________________________________________________________________ +; +; Include Files +; +#include "./hbios.inc" +#include "./layout.inc" +;______________________________________________________________________________ +; +; General operational equates (should not requre adjustment) +; +sigbyte1 .equ $A5 ; 1st sig byte boot info sector (bb_sig) +sigbyte2 .equ $5A ; 2nd sig byte boot info sector (bb_sig) +; +labelterm .equ '$' ; terminating charater for disk label +; +;***************************************************************************** +; +; APPLICATION WILL WILL BE LOADED AT USR_LOC. THEREFORE, THE CODE +; MUST "ORG" AT THIS ADDRESS. TO CHANGE THE LOAD LOCATION OF THIS +; CODE, YOU CAN UPDATE SLC_LOC IN LAYOUT.INC +; + .ORG SLC_LOC +; +;***************************************************************************** +; Main Code (shared) starts here +;***************************************************************************** +; +; Print list of all slices +; +prtslc: + ld de,PRTSLC_HDR ; Header for list of Slices + call prtstr ; Print It + ; + ld bc,BC_SYSGET_DIOCNT ; FUNC: SYSTEM INFO GET DISK DRIVES + rst 08 ; E := UNIT COUNT + ; + ld b,e ; MOVE Disk CNT TO B FOR LOOP COUNT + ld c,0 ; C WILL BE UNIT INDEX +prtslc1: + ld a,b ; loop counter + or a ; set flags + ret z ; IF no more drives, finished + ; + ld a,c ; unit index + ld (currunit),a ; store the unit number + ; + push bc ; save loop vars + call prtslc2 ; for each disk Unit, print its details + pop bc ; restore loop variables + ; + inc c ; bump the unit number + djnz prtslc1 ; main disk loop + ; +prtslcfin: + ret ; loop has finished, RETURN +; +;***************************************************************************** +; Supporting Code Stars Here +;***************************************************************************** +; +; Print list of All Slices for a given Unit +; +prtslc2: + ; get the media infor + ld b,BF_DIOMEDIA ; get media information + ld e,1 ; with media discovery + rst 08 ; do media discovery + ret nz ; an error + ; + ld a,MID_HD ; hard disk + cp e ; is it hard disk + ret nz ; if not noting to do + ; + ; setup the loop + ld b,64 ; arbitrary (?) number of slices to check. + ; NOTE: could be higher, but each slice check has disk IO + ld c,0 ; starting at slice 0 +; +prtslc2a: + ld a,c ; slice number + ld (currslice),a ; save slice number + ; + push bc ; save loop counter + call prtslc3 ; print detals of the slice + pop bc ; restore loop counter + ret nz ; if error don't continue + ; + inc c ; next slice number + djnz prtslc2a ; loop if more slices + ; + ret ; return from Slice Loop +; +;------------------------------------------------------------------------------- +; Print details of a Slice for a given Unit/Slice +; +prtslc3: + ; get the details of the device / slice + ld a,(currunit) + ld d,a ; unit + ld a,(currslice) + ld e,a ; slice + ld b,BF_EXTSLICE ; EXT function to check compute slice offset + rst 08 ; noting this call checks partition table. + ret NZ ; an error, for lots of reasons, e.g. Slice not valid + ; + call thirdsector ; point to the third sector of partition + ; + call diskread ; do the sector read + ret nz ; read error. exit the slice loop + ; + ; Check signature + ld bc,(bb_sig) ; get signature read + ld a,sigbyte1 ; expected value of first byte + cp b ; compare + jr nz,prtslc5 ; ignore missing signature and loop + ld a,sigbyte2 ; expected value of second byte + cp c ; compare + jr nz,prtslc5 ; ignore missing signature and loop + ; + ; Print slice label string at HL, '$' terminated, 16 chars max + ld a,(currunit) + call prtdecb ; print unit number as decimal + call pdot ; print a DOT + ld a,(currslice) + call prtdecb +; +;------------------------------------------------------------------------------- +; Added by MartinR, July 2025, to help neaten the output formatting. +; Note - this is not a complete fix and will still result in misaligned output +; where the unit number exceeds 9 (ie - uses 2 digits). + cp 10 ; is it less than 10? + ld a,' ' + jr nc,jr01 ; If not, then we don't need an extra space printed + call cout ; print the extra space necessary +jr01: call cout ; print a space + call cout ; print a space +;------------------------------------------------------------------------------- +; + ld hl,bb_label ; point to label + call pvol ; print it + call crlf + ; +prtslc5: + xor a + ret +; +;------------------------------------------------------------------------------- +; Print volume label string at HL, '$' terminated, 16 chars max +; +pvol: + ld b,16 ; init max char downcounter +pvol1: + ld a,(hl) ; get next character + cp labelterm ; set flags based on terminator $ + inc hl ; bump pointer regardless + ret z ; done if null + call cout ; display character + djnz pvol1 ; loop till done + ret ; hit max of 16 chars +; +;------------------------------------------------------------------------------- +; advance the DE HL LBA sector by 2, ie third sector +; +thirdsector: + ld bc,2 ; sector offset + add hl,bc ; add to LBA value low word + jr nc,sectornum ; check for carry + inc de ; if so, bump high word +sectornum: + ld (lba),hl ; update lba, low word + ld (lba+2),de ; update lba, high word + ret +; +;=============================================================================== +; +; Read disk sector(s) +; DE:HL is LBA, B is sector count, C is disk unit +; +diskread: +; + ; Seek to requested sector in DE:HL + ld a,(currunit) + ld c,a ; from the specified unit + set 7,d ; set LBA access flag + ld b,BF_DIOSEEK ; HBIOS func: seek + rst 08 ; do it + ret nz ; handle error +; + ; Read sector(s) into buffer + ld a,(currunit) + ld c,a ; from the specified unit + ld e,1 ; read 1 sector + ld hl,(dma) ; read into info sec buffer + ld a,(BID_USR) ; get user bank to accum + ld d,a ; and move to D + ld b,BF_DIOREAD ; HBIOS func: disk read + rst 08 ; do it + ret ; and done +; +;***************************************************************************** +; SUPPORT ROUTINES +;***************************************************************************** +; +; Print a dot on console +; +pdot: + push af + ld a,'.' + call cout + pop af + ret +; +;------------------------------------------------------------------------------- +; Print character in A without destroying any registers +; NOTE THIS CODE IS SPECIFIC AS IT USES HBIOS DIRECTLY +; +prtchr: +cout: + push af ; save registers + push bc + push de + push hl + LD B,BF_CIOOUT + LD C,CIO_CONSOLE + LD E,A + RST 08 + pop hl ; restore registers + pop de + pop bc + pop af + ret +; +;------------------------------------------------------------------------------- +; Start a newline on console (cr/lf) +; +crlf2: + call crlf ; two of them +crlf: + push af ; preserve AF + ld a,13 ; + call prtchr ; print it + ld a,10 ; + call prtchr ; print it + pop af ; restore AF + ret +; +;------------------------------------------------------------------------------- +; Print a zero terminated string at (de) without destroying any registers +; +prtstr: + push af + push de +; +prtstr1: + ld a,(de) ; get next char + or a + jr z,prtstr2 + call prtchr + inc de + jr prtstr1 +; +prtstr2: + pop de ; restore registers + pop af + ret +; +;------------------------------------------------------------------------------- +; Print value of a in decimal with leading zero suppression +; +prtdecb: + push hl + push af + ld l,a + ld h,0 + call prtdec + pop af + pop hl + ret +; +;------------------------------------------------------------------------------- +; Print value of HL in decimal with leading zero suppression +; +prtdec: + push bc + push de + push hl + ld e,'0' + ld bc,-10000 + call prtdec1 + ld bc,-1000 + call prtdec1 + ld bc,-100 + call prtdec1 + ld c,-10 + call prtdec1 + ld e,0 + ld c,-1 + call prtdec1 + pop hl + pop de + pop bc + ret +prtdec1: + ld a,'0' - 1 +prtdec2: + inc a + add hl,bc + jr c,prtdec2 + sbc hl,bc + cp e + jr z,prtdec3 + ld e,0 + call cout +prtdec3: + ret +; +;=============================================================================== +; +PRTSLC_HDR .TEXT "\r\n\r\n" + .TEXT "Un.Sl Label \r\n" + .TEXT "----- ----------------\r\n" + .DB 0 +; +;=============================================================================== +; Working data +;=============================================================================== +; +currunit .db 0 ; parameters for disk unit, current unit +currslice .db 0 ; parameters for disk slice, current slice +lba .dw 0, 0 ; lba address (4 bytes), of slice +; +BID_USR .db 0 ; Bank ID for user bank +dma .dw bl_infosec ; address for disk buffer +; +;=============================================================================== +; +; IT IS CRITICAL THAT THE FINAL BINARY BE EXACTLY SLC_SIZ BYTES. +; THIS GENERATES FILLER AS NEEDED. IT WILL ALSO FORCE AN ASSEMBLY +; ERROR IF THE SIZE EXCEEDS THE SPACE ALLOCATED. +; +SLACK .EQU (SLC_END - $) +; +#IF (SLACK < 0) + .ECHO "*** INVENTORY SLICE IS TOO BIG!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +; + .FILL SLACK,$00 + .ECHO "INVNTSLC Slice Inventory space remaining: " + .ECHO SLACK + .ECHO " bytes.\n" +; +;=============================================================================== +; Disk Buffer +;=============================================================================== +; + ; define origin of disk buffer = 9000 + ; Note this shares SAME Buffer Address as ROMLDR + .org $9000 +; +; Below is copied from ROM LDR +; Boot info sector is read into area below. +; The third sector of a disk device is reserved for boot info. +; +bl_infosec .equ $ + .ds (512 - 128) +bb_metabuf .equ $ +bb_sig .ds 2 ; signature (0xA55A if set) +bb_platform .ds 1 ; formatting platform +bb_device .ds 1 ; formatting device +bb_formatter .ds 8 ; formatting program +bb_drive .ds 1 ; physical disk drive # +bb_lu .ds 1 ; logical unit (lu) + .ds 1 ; msb of lu, now deprecated + .ds (bb_metabuf + 128) - $ - 32 +bb_protect .ds 1 ; write protect boolean +bb_updates .ds 2 ; update counter +bb_rmj .ds 1 ; rmj major version number +bb_rmn .ds 1 ; rmn minor version number +bb_rup .ds 1 ; rup update number +bb_rtp .ds 1 ; rtp patch level +bb_label .ds 16 ; 16 character drive label +bb_term .ds 1 ; label terminator ('$') +bb_biloc .ds 2 ; loc to patch boot drive info +bb_cpmloc .ds 2 ; final ram dest for cpm/cbios +bb_cpmend .ds 2 ; end address for load +bb_cpment .ds 2 ; CP/M entry point (cbios boot) +; +;=============================================================================== + +.END diff --git a/Source/HBIOS/layout.inc b/Source/HBIOS/layout.inc index e2fd12ae..c2c7af62 100644 --- a/Source/HBIOS/layout.inc +++ b/Source/HBIOS/layout.inc @@ -1,146 +1,243 @@ ; -; The was extracted out of STD.ASM, so can be included -; in BIOS apps that are NOT in HBIOS directory! +;================================================================================================== +; ROMWBW CPU MEMORY AND ROM BANK LAYOUT DEFINITIONS +;================================================================================================== ; -; ============= -; MEMORY LAYOUT -; ============= +; THIS FILE DEFINES THE MEMORY LAYOUT OF THE CPU ADDRESS SPACE AND +; THE LAYOUT OF CODE IMAGES IN ROM. THIS FILE IS INTENDED TO BE +; INCLUDED IN SOURCE FILES AS NEEDED TO ADAPT TO THE ROMWBW BUILD +; CONFIGURATION. ; -SYS_SIZ .EQU $3000 ; COMBINED SIZE OF SYSTEM AREA (OS + HBIOS PROXY) -HBBUF_SIZ .EQU 1024 ; INVARIANT HBIOS PHYSICAL DISK BUFFER, 1K -HBX_SIZ .EQU $200 ; HBIOS PROXY SIZE (SUBJECT TO CHANGE) -CPM_SIZ .EQU SYS_SIZ - HBX_SIZ ; NET SIZE OF ALL OS COMPONENTS (EXCLUDING HBIOS PROXY) -CCP_SIZ .EQU $800 ; INVARIANT SIZE OF CCP -BDOS_SIZ .EQU $E00 ; INVARIANT SIZE OF BDOS -CBIOS_SIZ .EQU CPM_SIZ - CCP_SIZ - BDOS_SIZ ; CBIOS IS THE REMAINDER +; THE FIRST 4 BANKS OF ROMWBW ROMS CONTAIN ROMWBW SOFTWARE COMPONENTS. +; THE REMAINING BANKS ARE USED AS ROM DISK CONTENTS. +; +; ROM BANK SUMMARY +; ---------------- +; +; ROM BANK BANK ID DESCRIPTION +; -------- -------- ---------------------------------------- +; 0 (ROM0) BID_BOOT HBIOS KERNEL (HBIOS.ASM) +; 1 (ROM1) BID_IMG0 MONITOR, BOOT LOADER, ROM OS IMAGES +; 2 (ROM2) BID_IMG1 ROM APPLICATIONS +; 3 (ROM3) BID_IMG2 ROM UTILITIES +; +;-------------------------------------------------------------------------------------------------- +; CPU ADDRESS SPACE MEMORY LAYOUT +;-------------------------------------------------------------------------------------------------- ; MEMTOP .EQU $10000 ; INVARIANT TOP OF Z80 ADDRESSABLE MEMORY BNKTOP .EQU $8000 ; BANK MEMORY BARRIER ; -HBX_IMG .EQU $200 ; LOC OF HBX IMAGE IN HBIOS IMAGE BANK +HBX_SIZ .EQU $200 ; HBIOS PROXY SIZE (SUBJECT TO CHANGE) +HBX_LOC .EQU MEMTOP - HBX_SIZ ; RUNNING LOCATION OF HBIOS PROXY ; -HBBUF_END .EQU BNKTOP ; END OF PHYSICAL DISK BUFFER IN HBIOS -HBBUF_LOC .EQU HBBUF_END - HBBUF_SIZ ; START OF PHYSICAL DISK BUFFER -HBX_END .EQU MEMTOP ; END OF HBIOS PROXY -HBX_LOC .EQU HBX_END - HBX_SIZ ; START OF HBIOS PROXY -CPM_END .EQU HBX_LOC ; END OF CPM COMPONENTS (INCLUDING CBIOS) -CPM_LOC .EQU CPM_END - CPM_SIZ ; START OF CPM COMPONENTS -CBIOS_END .EQU HBX_LOC ; END OF CBIOS -CBIOS_LOC .EQU CBIOS_END - CBIOS_SIZ ; START OF CBIOS +CPM_LOC .EQU $D000 ; START OF CPM COMPONENTS +CPM_SIZ .EQU HBX_LOC - CPM_LOC ; NET SIZE OF ALL OS COMPONENTS (EXCLUDING HBIOS PROXY) ; -CPM_ENT .EQU CBIOS_LOC ; CPM ENTRY POINT (IN CBIOS) +CCP_SIZ .EQU $0800 ; INVARIANT SIZE OF CCP +BDOS_SIZ .EQU $0E00 ; INVARIANT SIZE OF BDOS +CBIOS_SIZ .EQU CPM_SIZ - CCP_SIZ - BDOS_SIZ ; REMAINDER IS CBIOS SIZE ; -CPM_IMGSIZ .EQU $3000 +CBIOS_LOC .EQU HBX_LOC - CBIOS_SIZ ; START OF CBIOS +BDOS_LOC .EQU CBIOS_LOC - BDOS_SIZ ; START OF BDOS +CCP_LOC .EQU BDOS_LOC - CCP_SIZ ; START OF CCP ; -; ============================= -; ROM BANK 0 (hbios_rom.bin) -; ============================= -; -; See hbios.asm for content of Bank 0 +CPM_ENT .EQU CBIOS_LOC ; CPM ENTRY POINT (IN CBIOS) ; -; ============================= -; ROM BANK 1 LAYOUT (osimg.bin) -; ============================= +; THE SIZE OF THE CPM IMAGE STORED ON A ROM BANK IS GREATER THAN THE +; SIZE TO BE LOADED. THE FORMER INCLUDES HBIOS SPACE AND THE LATTER +; DOES NOT. USE CPM_IMGSIZ WHEN REFERRING TO IMAGE SIZE STORED ON ROM. +CPM_IMGSIZ .EQU $3000 ; CPM IMAGE SIZE ON ROM ; -LDR_LOC .EQU $0000 ; ROM LOADER -LDR_SIZ .EQU $1000 -LDR_END .EQU LDR_LOC +LDR_SIZ -LDR_IMGLOC .EQU $0000 +;-------------------------------------------------------------------------------------------------- +; ROM BANK 0 (BID_BOOT) LAYOUT (ROM0.BIN) +;-------------------------------------------------------------------------------------------------- ; -MON_LOC .EQU $EE00 ; LOCATION OF MONITOR FOR RUNNING SYSTEM -MON_SIZ .EQU $1000 ; SIZE OF MONITOR BINARY IMAGE -MON_END .EQU MON_LOC + MON_SIZ ; END OF MONITOR -MON_IMGLOC .EQU LDR_IMGLOC + LDR_SIZ +; SEE HBIOS.ASM FOR CONTENT OF BANK 0 ; -ZSYS_IMGLOC .EQU MON_IMGLOC + MON_SIZ ; ZSDOS / Z-System +;-------------------------------------------------------------------------------------------------- +; ROM BANK 1 (BID_IMG0) LAYOUT (ROM1.BIN) +;-------------------------------------------------------------------------------------------------- ; -CPM_IMGLOC .EQU ZSYS_IMGLOC + CPM_IMGSIZ ; CP/M 2.2 +BNK_NXTLOC .EQU $0000 ; RESET TO START OF BANK +BNK_CUR .EQU 1 ; THIS IS ROM BANK 1 (BID_IMG0) ; -BNK1_IMGEND .EQU CPM_IMGLOC + CPM_IMGSIZ ; END OF BANK -BNK1_REMAIN .EQU BNKTOP - BNK1_IMGEND ; REMAINING +LDR_BNK .EQU BNK_CUR +LDR_LOC .EQU $0000 ; RUNNING LOCATION OF BOOT LOADER +LDR_SIZ .EQU $1000 ; SIZE OF BOOT LOADER BINARY IMAGE +LDR_END .EQU LDR_LOC + LDR_SIZ ; ENDING ADDRESS OF RUNNING BOOT LOADER +LDR_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET LDR_IMGLOC + LDR_SIZ ; IMG LOC OF NEXT COMPONENT ; -; ============================== -; ROM BANK 2 LAYOUT (osimg1.bin) -; ============================== +MON_BNK .EQU BNK_CUR +MON_LOC .EQU $EE00 ; RUNNING LOCATION OF MONITOR +MON_SIZ .EQU $1000 ; SIZE OF MONITOR BINARY IMAGE +MON_END .EQU MON_LOC + MON_SIZ ; ENDING ADDRESS OF RUNNING MONITOR +MON_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET MON_IMGLOC + MON_SIZ ; IMG LOC OF NEXT COMPONENT +; +MON_DSKY .EQU MON_LOC + (0 * 3) ; MONITOR ENTRY (DSKY) +MON_SERIAL .EQU MON_LOC + (1 * 3) ; MONITOR ENTRY (SERIAL PORT) +; +ZSYS_BNK .EQU BNK_CUR +ZSYS_LOC .EQU CPM_LOC ; RUNNING LOCATION OF ZSYSTEM +ZSYS_SIZ .EQU CPM_SIZ ; SIZE OF ZSYSTEM BINARY IMAGE +ZSYS_END .EQU ZSYS_LOC + ZSYS_SIZ ; ENDING ADDRESS OF RUNNING ZSYSTEM +ZSYS_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +ZSYS_IMGSIZ .EQU CPM_IMGSIZ ; SIZE OF LOAD IMAGE IN BANK +BNK_NXTLOC .SET ZSYS_IMGLOC + ZSYS_IMGSIZ ; IMG LOC OF NEXT COMPONENT +; +CPM22_BNK .EQU BNK_CUR +CPM22_LOC .EQU CPM_LOC ; RUNNING LOCATION OF CPM 2.2 +CPM22_SIZ .EQU CPM_SIZ ; SIZE OF CPM 2.2 BINARY IMAGE +CPM22_END .EQU CPM22_LOC + CPM22_SIZ ; ENDING ADDRESS OF RUNNING CPM 2.2 +CPM22_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +CPM22_IMGSIZ .EQU CPM_IMGSIZ ; SIZE OF LOAD IMAGE IN BANK +BNK_NXTLOC .SET CPM22_IMGLOC + CPM22_IMGSIZ ; IMG LOC OF NEXT COMPONENT +; +BNK1_LEN .EQU BNK_NXTLOC ; SIZE OF BANK CONTENTS +BNK1_SLACK .EQU BNKTOP - BNK_NXTLOC ; REMAINING BANK SPACE +; +;-------------------------------------------------------------------------------------------------- +; ROM BANK 2 (BID_IMG1) LAYOUT (ROM2.BIN) +;-------------------------------------------------------------------------------------------------- +; +BNK_NXTLOC .SET $0000 ; RESET TO START OF BANK +BNK_CUR .SET 2 ; THIS IS ROM BANK 2 (BID_IMG1) ; ; NOTE FOLLOWING ARE COPY/PASTED INTO camel80.azm !!!!!!!! +FTH_BNK .EQU BNK_CUR FTH_LOC .EQU $0200 ; CAMEL FORTH FTH_SIZ .EQU $1700 FTH_END .EQU FTH_LOC + FTH_SIZ -FTH_IMGLOC .EQU $0000 - +FTH_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET FTH_IMGLOC + FTH_SIZ ; IMG LOC OF NEXT COMPONENT +; +BAS_BNK .EQU BNK_CUR BAS_LOC .EQU $0200 ; NASCOM BASIC BAS_SIZ .EQU $2000 BAS_END .EQU BAS_LOC + BAS_SIZ -BAS_IMGLOC .EQU FTH_IMGLOC + FTH_SIZ +BAS_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET BAS_IMGLOC + BAS_SIZ ; IMG LOC OF NEXT COMPONENT ; ; NOTE FOLLOWING ARE COPY/PASTED INTO tastybasic.asm !!!!!!!! +TBC_BNK .EQU BNK_CUR TBC_LOC .EQU $0A00 ; TASTYBASIC TBC_SIZ .EQU $0A00 TBC_END .EQU TBC_LOC + TBC_SIZ -TBC_IMGLOC .EQU BAS_IMGLOC + BAS_SIZ +TBC_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET TBC_IMGLOC + TBC_SIZ ; IMG LOC OF NEXT COMPONENT ; +GAM_BNK .EQU BNK_CUR GAM_LOC .EQU $0200 ; GAME 2048 GAM_SIZ .EQU $0900 GAM_END .EQU GAM_LOC + GAM_SIZ -GAM_IMGLOC .EQU TBC_IMGLOC + TBC_SIZ +GAM_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET GAM_IMGLOC + GAM_SIZ ; IMG LOC OF NEXT COMPONENT ; +EGG_BNK .EQU BNK_CUR EGG_LOC .EQU $F000 ; EASTER EGG EGG_SIZ .EQU $0200 EGG_END .EQU EGG_LOC + EGG_SIZ -EGG_IMGLOC .EQU GAM_IMGLOC + GAM_SIZ +EGG_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET EGG_IMGLOC + EGG_SIZ ; IMG LOC OF NEXT COMPONENT ; +NET_BNK .EQU BNK_CUR NET_LOC .EQU $0100 ; NETWORK BOOT NET_SIZ .EQU $1000 NET_END .EQU NET_LOC + NET_SIZ -NET_IMGLOC .EQU EGG_IMGLOC + EGG_SIZ +NET_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET NET_IMGLOC + NET_SIZ ; IMG LOC OF NEXT COMPONENT ; +UPD_BNK .EQU BNK_CUR UPD_LOC .EQU $0200 ; ROM UPDATER UPD_SIZ .EQU $0D00 UPD_END .EQU UPD_LOC + UPD_SIZ -UPD_IMGLOC .EQU NET_IMGLOC + NET_SIZ +UPD_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET UPD_IMGLOC + UPD_SIZ ; IMG LOC OF NEXT COMPONENT ; +NVR_BNK .EQU BNK_CUR NVR_LOC .EQU $0100 ; NVRAM CONFIG NVR_SIZ .EQU $0800 NVR_END .EQU NVR_LOC + NVR_SIZ -NVR_IMGLOC .EQU UPD_IMGLOC + UPD_SIZ +NVR_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET NVR_IMGLOC + NVR_SIZ ; IMG LOC OF NEXT COMPONENT ; +USR_BNK .EQU BNK_CUR USR_LOC .EQU $0200 ; USER USR_SIZ .EQU $0200 USR_END .EQU USR_LOC + USR_SIZ -USR_IMGLOC .EQU NVR_IMGLOC + NVR_SIZ -; -BNK2_IMGEND .EQU USR_IMGLOC + USR_SIZ ; END OF BANK -BNK2_REMAIN .EQU BNKTOP - BNK2_IMGEND ; REMAINING -; -; ============================== -; ROM BANK 3 LAYOUT (osimg2.bin) -; ============================== -; -; not defined here, see build files -; optionally contains S100 monitor -; -; ================= +USR_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET USR_IMGLOC + USR_SIZ ; IMG LOC OF NEXT COMPONENT +; +BNK2_LEN .EQU BNK_NXTLOC ; SIZE OF BANK CONTENTS +BNK2_SLACK .EQU BNKTOP - BNK_NXTLOC ; REMAINING BANK SPACE +; +;-------------------------------------------------------------------------------------------------- +; ROM BANK 3 (BID_IMG2) LAYOUT (ROM3.BIN) +;-------------------------------------------------------------------------------------------------- +; +BNK_NXTLOC .SET $0000 ; RESET TO START OF BANK +BNK_CUR .SET 3 ; THIS IS ROM BANK 3 (BID_IMG2) +; +HWMON_BNK .EQU BNK_CUR +HWMON_LOC .EQU $E000 +HWMON_SIZ .EQU $2000 +HWMON_END .EQU HWMON_LOC + HWMON_SIZ +HWMON_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET HWMON_IMGLOC + HWMON_SIZ ; IMG LOC OF NEXT COMPONENT +; +; Device Inventory Application +DEV_BNK .EQU BNK_CUR +DEV_LOC .EQU $0200 ; LOAD LOCATION +DEV_SIZ .EQU $0B00 ; SIZE OF IMAGE +DEV_END .EQU DEV_LOC + DEV_SIZ ; END LOCATION +DEV_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET DEV_IMGLOC + DEV_SIZ ; IMG LOC OF NEXT COMPONENT +; +; Slice Inventory Application +SLC_BNK .EQU BNK_CUR +SLC_LOC .EQU $0200 ; LOAD LOCATION +SLC_SIZ .EQU $0200 ; SIZE OF IMAGE +SLC_END .EQU SLC_LOC + SLC_SIZ ; END LOCATION +SLC_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET SLC_IMGLOC + SLC_SIZ ; IMG LOC OF NEXT COMPONENT +; +FONTS_BNK .EQU BNK_CUR +FONTS_LOC .EQU BNK_NXTLOC +FONTS_SIZ .EQU $2000 +FONTS_END .EQU FONTS_LOC + FONTS_SIZ +FONTS_IMGLOC .EQU BNK_NXTLOC ; LOCATION OF BINARY LOAD IMAGE IN BANK +BNK_NXTLOC .SET FONTS_IMGLOC + FONTS_SIZ ; IMG LOC OF NEXT COMPONENT +; +BNK3_LEN .EQU BNK_NXTLOC ; SIZE OF BANK CONTENTS +BNK3_SLACK .EQU BNKTOP - BNK_NXTLOC ; REMAINING BANK SPACE +; +;-------------------------------------------------------------------------------------------------- ; #IFDEF BNKINFO +; .ECHO "-------------------------------\n" - .ECHO "ROM BANK INFO \tLENGTH \tREMAIN \n" + .ECHO "ROM BANK INFO \tLENGTH \tSLACK \n" .ECHO "---------------\t-------\t-------\n" - .ECHO "BANK1 BID_IMG0 \t" \ .ECHO BNK1_IMGEND \ .ECHO "\t" \ .ECHO BNK1_REMAIN \ .ECHO "\n" - .ECHO "BANK2 BID_IMG1 \t" \ .ECHO BNK2_IMGEND \ .ECHO "\t" \ .ECHO BNK2_REMAIN \ .ECHO "\n" + .ECHO "BANK1 BID_IMG0 \t" \ .ECHO BNK1_LEN \ .ECHO "\t" \ .ECHO BNK1_SLACK \ .ECHO "\n" + .ECHO "BANK2 BID_IMG1 \t" \ .ECHO BNK2_LEN \ .ECHO "\t" \ .ECHO BNK2_SLACK \ .ECHO "\n" + .ECHO "BANK3 BID_IMG2 \t" \ .ECHO BNK3_LEN \ .ECHO "\t" \ .ECHO BNK3_SLACK \ .ECHO "\n" .ECHO "-------------------------------\n" ; - #IF (BNK1_IMGEND > BNKTOP) - .ECHO "*** BANK 1 IS TOO BIG!!!\n" +#ENDIF +; +#IF (BNK1_SLACK < 0) + .ECHO "*** ROM BANK 1 IS TOO BIG!!!\n" !!! ; FORCE AN ASSEMBLY ERROR IF BANK SIZE EXCEEDS SPACE - #ENDIF - #IF (BNK2_IMGEND > BNKTOP) - .ECHO "*** BANK 2 IS TOO BIG!!!\n" +#ENDIF +; +#IF (BNK2_SLACK < 0) + .ECHO "*** ROM BANK 2 IS TOO BIG!!!\n" !!! ; FORCE AN ASSEMBLY ERROR IF BANK SIZE EXCEEDS SPACE - #ENDIF +#ENDIF ; +#IF (BNK3_SLACK < 0) + .ECHO "*** ROM BANK 3 IS TOO BIG!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR IF BANK SIZE EXCEEDS SPACE #ENDIF - - - - diff --git a/Source/HBIOS/lcd.asm b/Source/HBIOS/lcd.asm index 0a49df9b..05e0becd 100644 --- a/Source/HBIOS/lcd.asm +++ b/Source/HBIOS/lcd.asm @@ -90,21 +90,7 @@ LCD_PREINIT: LD DE,LCD_STR_XPU CALL LCD_OUTDS ; - ; "12.345 MHz" RIGHT JUSTIFIED - LD HL,$010A ; ROW 2, COL 10 - CALL LCD_GOTORC - LD HL,(CB_CPUKHZ) - PUSH HL - LD BC,10000 ; 10 MHZ - SBC HL,BC ; SUBTRACT - JR NC,LCD_PREINIT1 - LD A,' ' ; EXTRA PAD - CALL LCD_OUTD -LCD_PREINIT1: - POP HL - CALL LCD_PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA - LD DE,LCD_STR_MHZ - CALL LCD_OUTDS + CALL LCD_EVT_CPUSPD ; ; THIRD LINE LD HL,$0200 ; ROW 2, COL 0 @@ -228,7 +214,22 @@ LCD_EVENT: ; CPU SPEED CHANGE ; LCD_EVT_CPUSPD: - XOR A + ; "12.345 MHz" RIGHT JUSTIFIED + LD HL,$010A ; ROW 2, COL 10 + CALL LCD_GOTORC + LD HL,(CB_CPUKHZ) + PUSH HL + LD BC,10000 ; 10 MHZ + SBC HL,BC ; SUBTRACT + JR NC,LCD_PREINIT1 + LD A,' ' ; EXTRA PAD + CALL LCD_OUTD +LCD_PREINIT1: + POP HL + CALL LCD_PRTD3M ; PRINT AS DECIMAL WITH 3 DIGIT MANTISSA + LD DE,LCD_STR_MHZ + CALL LCD_OUTDS +; RET ; ; FORMAT: "Disk #99 R:12345678" @@ -342,16 +343,23 @@ LCD_DELAY: CALL DELAY ; 16US JP DELAY ; 16US, TOTAL 48US ; +; DELAY USED DURING NORMAL I/O +; REQUIRED FOR HIGH SPEED CPU OPERATION +; +#DEFINE LCD_XDELAY EX (SP),HL \ EX (SP),HL +; ; SEND FUNCTION CODE IN A ; LCD_OUTF: PUSH AF ; SAVE CODE LCD_OUTF1: + LCD_XDELAY EZ80_IO IN A,(LCD_STAT) ; GET STATUS AND $80 ; ISOLATE BUSY FLAG JR NZ,LCD_OUTF1 ; LOOP TILL NOT BUSY POP AF ; RECOVER CODE + LCD_XDELAY EZ80_IO OUT (LCD_FUNC),A ; SEND IT RET ; DONE @@ -372,11 +380,13 @@ LCD_OUTFS: LCD_OUTD: PUSH AF ; SAVE BYTE LCD_OUTD1: + LCD_XDELAY EZ80_IO IN A,(LCD_STAT) ; GET STATUS AND $80 ; ISOLATE BUSY FLAG JR NZ,LCD_OUTD1 ; LOOP TILL NOT BUSY POP AF ; RECOVER BYTE + LCD_XDELAY EZ80_IO OUT (LCD_DATA),A ; SEND IT RET ; DONE @@ -408,11 +418,13 @@ LCD_OUTDS: ; GET DATA BYTE INTO A ; LCD_IND: + LCD_XDELAY EZ80_IO IN A,(LCD_STAT) ; GET STATUS AND $80 ; ISOLATE BUSY FLAG JR NZ,LCD_IND ; LOOP TILL NOT BUSY POP AF ; RECOVER BYTE + LCD_XDELAY EZ80_IO IN A,(LCD_DATA) ; GET IT RET ; DONE @@ -483,10 +495,9 @@ LCD_INIT_SEQ: .DB $00 ; TERMINATOR ; LCD_STR_BAN .DB "RomWBW v", BIOSVER, 0 -LCD_STR_CFG .DB "Build: ", CONFIG, 0 +LCD_STR_CFG .DB CONFIG, 0 LCD_STR_IO .DB "Disk #", 0 LCD_STR_XPU .DB " CPU",0 -;;;LCD_STR_SPD .DB "12.345",0 LCD_STR_MHZ .DB " MHz",0 ; LCD_CPU .DW LCD_CPU_Z80 @@ -498,8 +509,8 @@ LCD_CPU .DW LCD_CPU_Z80 ; LCD_CPU_Z80 .DB "Z80",0 LCD_CPU_Z180 .DB "Z180",0 -LCD_CPU_Z180K .DB "Z180-K",0 -LCD_CPU_Z180N .DB "Z180-N",0 +LCD_CPU_Z180K .DB "Z180K",0 +LCD_CPU_Z180N .DB "Z180N",0 LCD_CPU_Z280 .DB "Z280",0 LCD_CPU_EZ80 .DB "eZ80",0 ; diff --git a/Source/HBIOS/lpt.asm b/Source/HBIOS/lpt.asm index 0445b269..f8703d7e 100644 --- a/Source/HBIOS/lpt.asm +++ b/Source/HBIOS/lpt.asm @@ -95,10 +95,18 @@ LPT_INIT: LD IY,LPT_CFG ; POINT TO START OF CFG TABLE LPT_INIT0: PUSH BC ; SAVE LOOP CONTROL + CALL LPT_PRTCFG ; PRINT CONFIG CALL LPT_INITUNIT ; HAND OFF TO UNIT INIT CODE POP BC ; RESTORE LOOP CONTROL ; - LD A,(IY+1) ; GET THE LPT TYPE DETECTED + JR Z,LPT_INIT1 ; IF DETECTED, CONTINUE INIT + CALL PC_SPACE ; FORMATTING + LD DE,LPT_STR_NOLPT ; NO LPT MESSAGE + CALL WRITESTR ; DISPLAY IT + JR LPT_INIT2 ; AND LOOP AS NEEDED +; +LPT_INIT1: + LD A,(IY+1) ; GET THE LPT TYPE OR A ; SET FLAGS JR Z,LPT_INIT2 ; SKIP IT IF NOTHING FOUND ; @@ -107,7 +115,6 @@ LPT_INIT0: POP DE ; ... TO DE LD BC,LPT_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL NZ,CIO_ADDENT ; ADD ENTRY IF LPT FOUND, BC:DE - CALL LPT_PRTCFG ; PRINT IF NOT ZERO POP BC ; RESTORE LOOP CONTROL ; LPT_INIT2: @@ -123,9 +130,7 @@ LPT_INIT3: ; LPT_INITUNIT: CALL LPT_DETECT ; DETERMINE LPT TYPE - LD (IY+1),A ; SAVE IN CONFIG TABLE - OR A ; SET FLAGS - RET Z ; ABORT IF NOTHING THERE + RET NZ ; ABORT IF NOTHING THERE ; ; UPDATE WORKING LPT DEVICE NUM LD HL,LPT_DEV ; POINT TO CURRENT DEVICE NUM @@ -135,9 +140,7 @@ LPT_INITUNIT: ; ; SET DEFAULT CONFIG LD DE,-1 ; LEAVE CONFIG ALONE - ; CALL INITDEV TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL - ; THE INITDEV ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! - JP LPT_INITDEVX ; IMPLEMENT IT AND RETURN + JP LPT_INITDEV ; IMPLEMENT IT AND RETURN ; ; DRIVER FUNCTION TABLE ; @@ -235,15 +238,17 @@ LPT_OST: ; INITIALIZE DEVICE ; LPT_INITDEV: + ; INTERRUPTS DISABLED DURING INIT + ; ??? IS THIS NEEDED? HB_DI ; AVOID CONFLICTS - CALL LPT_INITDEVX ; DO THE REAL WORK + CALL LPT_INITDEV0 ; DO THE REAL WORK HB_EI ; INTS BACK ON RET ; DONE ; ; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY ; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! ; -LPT_INITDEVX: +LPT_INITDEV0: ; #IF (LPTMODE == LPTMODE_SPP) ; @@ -326,15 +331,7 @@ LPT_DETECT: ; LPT_DETECT: LD C,(IY+3) ; BASE PORT ADDRESS - CALL LPT_DETECT2 ; CHECK IT - JR Z,LPT_DETECT1 ; FOUND IT, RECORD IT - LD A,LPTMODE_NONE ; NOTHING FOUND - RET ; DONE -; -LPT_DETECT1: - ; LPT FOUND, RECORD IT - LD A,LPTMODE_SPP ; RETURN CHIP TYPE - RET ; DONE + JR LPT_DETECT2 ; CHECK IT ; LPT_DETECT2: ; LOOK FOR LPT AT BASE PORT ADDRESS IN C @@ -394,20 +391,13 @@ LPT_DETECT: CALL PRTHEXBYTE #ENDIF CP $A5 ; CHECK FOR TEST VALUE - JR Z,LPT_DETECT1 ; FOUND IT - LD A,LPTMODE_NONE ; NOT FOUND - RET -; -LPT_DETECT1: - ; LPT FOUND, RECORD IT - LD A,LPTMODE_MG014 ; RETURN CHIP TYPE - RET ; DONE + RET ; ZF SET IF DETECTED #ENDIF ; #IF (LPTMODE == LPTMODE_S100) LPT_DETECT: ; PORT ALWAYS EXISTS ON FPGA - LD A,LPTMODE_S100 ; RETURN CHIP TYPE + XOR A ; SIGNAL SUCCESS RET ; DONE #ENDIF ; @@ -417,7 +407,7 @@ LPT_PRTCFG: ; ANNOUNCE PORT CALL NEWLINE ; FORMATTING PRTS("LPT$") ; FORMATTING - LD A,(IY) ; DEVICE NUM + LD A,(IY+2) ; DEVICE NUM CALL PRTDECB ; PRINT DEVICE NUM PRTS(": IO=0x$") ; FORMATTING LD A,(IY+3) ; GET BASE PORT @@ -452,11 +442,13 @@ LPT_TYPE_MAP: .DW LPT_STR_MG014 .DW LPT_STR_S100 ; -LPT_STR_NONE .DB "$" +LPT_STR_NONE .DB "???$" LPT_STR_SPP .DB "SPP$" LPT_STR_MG014 .DB "MG014$" LPT_STR_S100 .DB "S100$" ; +LPT_STR_NOLPT .DB "NOT PRESENT$" +; ; WORKING VARIABLES ; LPT_DEV .DB 0 ; DEVICE NUM USED DURING INIT @@ -468,7 +460,7 @@ LPT_CFG: LPT0_CFG: ; LPT MODULE A CONFIG .DB 0 ; DEVICE NUMBER (SET DURING INIT) - .DB 0 ; LPT TYPE (SET DURING INIT) + .DB LPTMODE ; LPT MODE .DB 0 ; MODULE ID .DB LPT0BASE ; BASE PORT .DW 0 ; LINE CONFIGURATION @@ -494,7 +486,7 @@ LPT_CFGSIZ .EQU $ - LPT_CFG ; SIZE OF ONE CFG TABLE ENTRY LPT1_CFG: ; LPT MODULE B CONFIG .DB 0 ; DEVICE NUMBER (SET DURING INIT) - .DB 0 ; LPT TYPE (SET DURING INIT) + .DB LPTMODE ; LPT MODE .DB 1 ; MODULE ID .DB LPT1BASE ; BASE PORT .DW 0 ; LINE CONFIGURATION diff --git a/Source/HBIOS/md.asm b/Source/HBIOS/md.asm index 1c899228..589419d1 100644 --- a/Source/HBIOS/md.asm +++ b/Source/HBIOS/md.asm @@ -359,6 +359,7 @@ MD_RDSECF: ; CALLED FROM MD_RW ; SAVE THE 4K LBA FOR FUTURE CHECKS ; CALL MD_CALBAS ; SETUP BANK AND SECTOR + RET NZ ; RETURN IF ERROR ; LD IX,MD_F4KBUF ; SET DESTINATION ADDRESS LD HL,MD_FREAD_R ; PUT ROUTINE TO CALL @@ -467,7 +468,18 @@ MD_CALBAS: CALL PRTHEXWORD ; DISPLAY BANK AND CALL PC_SPACE ; SECTOR RESULT #ENDIF - +; + ; CHECK FOR ACCESS BEYOND AVAILABLE ROM BANKS + LD A,B ; BANK ID TO ACCUM + SUB BID_ROMD0 ; ZERO OFFSET + CP ROMD_BNKS ; CHECK FOR OUT OF BOUNDS + JR C,MD_CALBAS1 ; IF NOT, CONTINUE + LD A,ERR_IO ; ELSE SIGNAL IO ERROR + OR A ; SET FLAGS + RET ; AND RETURN +; +MD_CALBAS1: + XOR A ; SIGNAL SUCCESS RET ; ; WRITE FLASH @@ -485,6 +497,7 @@ MD_WRSECF: ; CALLED FROM MD_RW LD (MD_LBA4K),BC ; SAVE 4K LBA ; CALL MD_CALBAS ; SETUP BANK AND SECTOR + RET NZ ; RETURN ON ERROR ; LD IX,MD_F4KBUF ; SET DESTINATION ADDRESS LD HL,MD_FREAD_R ; PUT ROUTINE TO CALL @@ -566,6 +579,12 @@ MD_FBAS .DW $FFFF ; BANK AND SECTOR ; MD_RDSEC: CALL MD_IOSETUP ; SETUP FOR MEMORY COPY + CP $FF ; ERROR? + JR NZ,MD_RDSEC1 ; IF NOT, CONTINUE + LD A,ERR_IO ; SIGNAL IO ERROR + OR A ; SET FLAGS + RET ; AND DONE +MD_RDSEC1: #IF (MDTRACE >= 2) LD (MD_SRC),HL LD (MD_DST),DE @@ -597,6 +616,12 @@ MD_RDSEC: ; MD_WRSEC: CALL MD_IOSETUP ; SETUP FOR MEMORY COPY + CP $FF ; ERROR? + JR NZ,MD_WRSEC1 ; IF NOT, CONTINUE + LD A,ERR_IO ; SIGNAL IO ERROR + OR A ; SET FLAGS + RET ; AND DONE +MD_WRSEC1: EX DE,HL ; SWAP SRC/DEST FOR WRITE #IF (MDTRACE >= 2) LD (MD_SRC),HL @@ -682,13 +707,21 @@ MD_IOSETUP: JR Z,MD_IOSETUP2 ; DO ROM DRIVE, ELSE FALL THRU FOR RAM DRIVE ; MD_IOSETUP1: ; ROM + CP ROMD_BNKS ; WITHIN AVAILABLE ROM DISK BANKS? + JR NC,MD_IOSETUP3 ; HANDLE OUT OF BOUNDS ADD A,BID_ROMD0 RET ; MD_IOSETUP2: ; RAM + CP RAMD_BNKS ; WITHIN AVAILABLE RAM DISK BANKS? + JR NC,MD_IOSETUP3 ; HANDLE OUT OF BOUNDS ADD A,BID_RAMD0 RET ; +MD_IOSETUP3: + OR $FF ; SIGNAL ERROR + RET ; DONE +; ; ; #IF (MDTRACE >= 2) diff --git a/Source/HBIOS/pcf.asm b/Source/HBIOS/pcf.asm index 0d5216c8..1a6789d2 100644 --- a/Source/HBIOS/pcf.asm +++ b/Source/HBIOS/pcf.asm @@ -66,62 +66,10 @@ PCF_BB .EQU 00000001B ; | 12MHz | | | | | | 90Khz | 120Khz | 138Khz | 150Khz | ; +----------------------------------------------------------------------------------+---------+ ; -; CLOCK CHIP FREQUENCIES -; -PCF_CLK3 .EQU 000H -PCF_CLK443 .EQU 010H -PCF_CLK6 .EQU 014H -PCF_CLK8 .EQU 018H -PCF_CLK12 .EQU 01CH -; -; TRANSMISSION FREQUENCIES -; -PCF_TRNS90 .EQU 000H ; 90 kHz */ -PCF_TRNS45 .EQU 001H ; 45 kHz */ -PCF_TRNS11 .EQU 002H ; 11 kHz */ -PCF_TRNS15 .EQU 003H ; 1.5 kHz */ -; -; BELOW VARIABLES CONTROL PCF CLOCK DIVISOR PROGRAMMING -; -#IF (PCFCLK = 3) -PCF_CLK .EQU PCF_CLK3 -#ELSE - #IF (PCFCLK = 443) -PCF_CLK .EQU PCF_CLK443 - #ELSE - #IF (PCFCLK = 6) -PCF_CLK .EQU PCF_CLK6 - #ELSE - #IF (PCFCLK = 8) -PCF_CLK .EQU PCF_CLK8 - #ELSE - #IF (PCFCLK = 12) -PCF_CLK .EQU PCF_CLK12 - #ELSE ***ERROR - .ERROR "PCFCLK UNDEFINED OR WRONG VALUE VALID VALUES ARE (3,443,6,8,12)" - #ENDIF - #ENDIF - #ENDIF - #ENDIF -#ENDIF -; -#IF (PCFTRNS = 90) -PCF_TRNS .EQU PCF_TRNS90 -#ELSE - #IF (PCFTRNS = 45) -PCF_TRNS .EQU PCF_TRNS45 - #ELSE - #IF (PCFTRNS = 11) -PCF_TRNS .EQU PCF_TRNS11 - #ELSE - #IF (PCFTRNS = 15) -PCF_TRNS .EQU PCF_TRNS15 - #ELSE ***ERROR - .ERROR "PCFTRNS UNDEFINED OR WRONG VALUE VALID VALUES ARE (90,45,11,15)" - #ENDIF - #ENDIF - #ENDIF -#ENDIF +; SEE STD.ASM FOR DEFINITIONS OF PCFCLK AND PCFTRNS VALUES +; +PCF_CLK .EQU PCFCLK +PCF_TRNS .EQU PCFTRNS ; ; TIMEOUT AND DELAY VALUES (ARBITRARY) ; diff --git a/Source/HBIOS/pcrtc.asm b/Source/HBIOS/pcrtc.asm new file mode 100644 index 00000000..cd117236 --- /dev/null +++ b/Source/HBIOS/pcrtc.asm @@ -0,0 +1,368 @@ +; +;================================================================================================== +; MC146818/DS1285/DS12885 PC style CLOCK DRIVER +;================================================================================================== +; +PCRTC_BUFSIZ .EQU 6 ; SIX BYTE BUFFER (YYMMDDHHMMSS) + + ;; Addressing is via first writing the address byte to IO port PCRTC_BASE + ;; Then read from or write to PCRTC_DAT + + ;; PCRTC_BASE must be set in config files +PCRTC_REG .EQU PCRTC_BASE +PCRTC_DAT .EQU PCRTC_BASE + $01 + +REG_SEC .EQU $00 +REG_SEC_ALM .EQU $01 +REG_MIN .EQU $02 +REG_MIN_ALM .EQU $03 +REG_HOUR .EQU $04 +REG_HOUR_ALM .EQU $05 +REG_DOW .EQU $06 ; day of week +REG_DAY .EQU $07 +REG_MONTH .EQU $08 +REG_YEAR .EQU $09 +REG_CTLA .EQU $0A +REG_CTLB .EQU $0B +REG_CTLC .EQU $0C +REG_CTLD .EQU $0D + +CTLA_VAL .EQU $2F +CTLB_VAL .EQU $0A + +PCRTC_NVBASE .EQU $10 +PCRTC_NVSIZE .EQU $30 ; 64 bytes in total is what DS1285 and MC146818 had + + DEVECHO "PCRTC: IO=" + DEVECHO PCRTC_BASE + DEVECHO "\n" + +PCRTC_INIT: + LD A, (RTC_DISPACT) ; RTC DISPATCHER ALREADY SET? + OR A ; SET FLAGS + RET NZ ; IF ALREADY ACTIVE, ABORT + + CALL NEWLINE ; FORMATTING + PRTS("PC RTC: $") + + ; PRINT RTC REGISTER NR PORT ADDRESS + PRTS("IO=0x$") ; LABEL FOR IO ADDRESS + LD A,PCRTC_REG ; GET IO ADDRESS + CALL PRTHEXBYTE ; PRINT IT + CALL PC_SPACE ; FORMATTING + + ; CHECK PRESENCE STATUS + CALL PCRTC_DETECT ; HARDWARE DETECTION + JR Z, PCRTC_INIT1 ; IF ZERO, ALL GOOD + PRTS("NOT PRESENT$") ; NOT ZERO, H/W NOT PRESENT + OR $FF ; SIGNAL FAILURE + RET ; BAIL OUT + +PCRTC_INIT1: + CALL PCRTC_RDTIM + + ; DISPLAY CURRENT TIME + LD HL, PCRTC_BCDBUF ; POINT TO BCD BUF + CALL PRTDT +; + LD BC, PCRTC_DISPATCH + CALL RTC_SETDISP +; + XOR A ; SIGNAL SUCCESS + RET +; +; DETECT RTC HARDWARE PRESENCE +; +PCRTC_DETECT: + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_GETBYT ; GET VALUE + LD A, E ; TO ACCUM + LD L, A ; SAVE IT + XOR $FF ; FLIP ALL BITS + LD E, A ; TO E + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_SETBYT ; WRITE IT + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_GETBYT ; GET VALUE + LD A, L ; GET SAVED VALUE + XOR $FF ; FLIP ALL BITS + CP E ; COMPARE WITH VALUE READ + LD A, 0 ; ASSUME OK + JR Z, PCRTC_DETECT1 ; IF MATCH, GO AHEAD + LD A, $FF ; ELSE STATUS IS ERROR + +PCRTC_DETECT1: + PUSH AF ; SAVE STATUS + LD E, L ; GET SAVED VALUE + LD C, 0 ; NVRAM INDEX 0 + CALL PCRTC_SETBYT ; SAVE IT + POP AF ; RECOVER STATUS + OR A ; SET FLAGS + RET +; +; RTC DEVICE FUNCTION DISPATCH ENTRY +; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR +; B: FUNCTION (IN) +; +PCRTC_DISPATCH: + LD A,B ; GET REQUESTED FUNCTION + AND $0F ; ISOLATE SUB-FUNCTION + JP Z,PCRTC_GETTIM ; GET TIME + DEC A + JP Z,PCRTC_SETTIM ; SET TIME + DEC A + JP Z,PCRTC_GETBYT ; GET NVRAM BYTE VALUE + DEC A + JP Z,PCRTC_SETBYT ; SET NVRAM BYTE VALUE + DEC A + JP Z,PCRTC_GETBLK ; GET NVRAM DATA BLOCK VALUES + DEC A + JP Z,PCRTC_SETBLK ; SET NVRAM DATA BLOCK VALUES + DEC A + JP Z,PCRTC_GETALM ; GET ALARM + DEC A + JP Z,PCRTC_SETALM ; SET ALARM + DEC A + JP Z,PCRTC_DEVICE ; REPORT RTC DEVICE INFO + SYSCHKERR(ERR_NOFUNC) + RET +; +; RTC GET NVRAM BYTE +; C: INDEX +; E: VALUE (OUTPUT) +; A:0 IF OK, ERR_RANGE IF OUT OF RANGE +; +PCRTC_GETBYT: + LD A, C + CP PCRTC_NVSIZE + JR NC, PCRTC_BADIDX + + ADD A, PCRTC_NVBASE + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD E, A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN + +PCRTC_BADIDX: + LD E, 00 + LD A, ERR_RANGE + RET +; +; RTC SET NVRAM BYTE +; C: INDEX +; E: VALUE +; A:0 IF OK, ERR_RANGE IF OUT OF RANGE +; +PCRTC_SETBYT: + LD A, C + CP PCRTC_NVSIZE + JR NC, PCRTC_BADIDX + + ADD A, PCRTC_NVBASE + EZ80_IO + OUT (PCRTC_REG), A + LD A, E + EZ80_IO + OUT (PCRTC_DAT), A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN + + +PCRTC_GETBLK: +PCRTC_SETBLK: +PCRTC_GETALM: +PCRTC_SETALM: + SYSCHKERR(ERR_NOTIMPL) + RET +; +; RTC GET TIME +; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR +; HL: DATE/TIME BUFFER (OUT) +; BUFFER FORMAT IS BCD: YYMMDDHHMMSS +; 24 HOUR TIME FORMAT IS ASSUMED +; +PCRTC_GETTIM: + ; GET THE TIME INTO TEMP BUF + PUSH HL ; SAVE PTR TO CALLERS BUFFER +; + CALL PCRTC_RDTIM + + ; NOW COPY TO REAL DESTINATION (INTERBANK SAFE) + LD A,BID_BIOS ; COPY FROM BIOS BANK + LD (HB_SRCBNK),A ; SET IT + LD A,(HB_INVBNK) ; COPY TO CURRENT USER BANK + LD (HB_DSTBNK),A ; SET IT + LD HL,PCRTC_BCDBUF ; SOURCE ADR + POP DE ; DEST ADR + LD BC,PCRTC_BUFSIZ ; LENGTH + CALL HB_BNKCPY ; COPY THE CLOCK DATA + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN +; +; +; RTC SET TIME +; A: RESULT (OUT), 0=OK, Z=OK, NZ=ERR +; HL: DATE/TIME BUFFER (IN) +; BUFFER FORMAT IS BCD: YYMMDDHHMMSSWW +; 24 HOUR TIME FORMAT IS ASSUMED +; +PCRTC_SETTIM: + ; COPY TO BCD BUF + LD A,(HB_INVBNK) ; COPY FROM CURRENT USER BANK + LD (HB_SRCBNK),A ; SET IT + LD A,BID_BIOS ; COPY TO BIOS BANK + LD (HB_DSTBNK),A ; SET IT + LD DE,PCRTC_BCDBUF ; DEST ADR + LD BC,PCRTC_BUFSIZ ; LENGTH + CALL HB_BNKCPY ; COPY THE RPC DATA +; + LD A, REG_CTLA ; Set Ctl Reg A + EZ80_IO + OUT (PCRTC_REG), A + LD A, CTLA_VAL + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_CTLB ; Set Ctl Reg B + EZ80_IO + OUT (PCRTC_REG), A + LD A, CTLB_VAL|0x80 ; Set the SET bit to stop updates + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_SEC ; Set seconds + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_SS) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_MIN ; Set minutes + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_MM) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_HOUR ; Set hours + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_HH) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_DAY ; Set date + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_DT) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_MONTH ; Set month + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_MO) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_YEAR ; Set year + EZ80_IO + OUT (PCRTC_REG), A + LD A, (PCRTC_YR) + EZ80_IO + OUT (PCRTC_DAT), A + + LD A, REG_CTLB ; Set Ctl Reg B + EZ80_IO + OUT (PCRTC_REG), A + LD A, CTLB_VAL ; Reset the SET bit to start clock + EZ80_IO + OUT (PCRTC_DAT), A + + XOR A ; SIGNAL SUCCESS + RET ; AND RETURN +; +; REPORT RTC DEVICE INFO +; +PCRTC_DEVICE: + LD D,RTCDEV_PC ; D := DEVICE TYPE + LD E,0 ; E := PHYSICAL DEVICE NUMBER + LD H,0 ; H := 0, DRIVER HAS NO MODES + LD L, PCRTC_BASE ; L := 0, NO I/O ADDRESS + XOR A ; SIGNAL SUCCESS + RET + +; +; READ OUT THE TIME +PCRTC_RDTIM: + ;; Need to wait until update-in-progress flag is reset + LD A, REG_CTLA ; Set Ctl Reg A + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + BIT 7, A + JP NZ, PCRTC_RDTIM ; Jump back if update in progress. + + LD A, REG_SEC ; Set seconds + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_SS), A + + LD A, REG_MIN ; Set minutes + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_MM), A + + LD A, REG_HOUR ; Set hours + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_HH), A + + LD A, REG_DAY ; Set day + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_DT), A + + LD A, REG_MONTH ; Set month + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_MO), A + + LD A, REG_YEAR ; Set year + EZ80_IO + OUT (PCRTC_REG), A + EZ80_IO + IN A, (PCRTC_DAT) + LD (PCRTC_YR), A + + RET + + +; +; REGISTER EXTRACTED VALUES +; +PCRTC_BCDBUF: +PCRTC_YR .DB $25 +PCRTC_MO .DB $01 +PCRTC_DT .DB $01 +PCRTC_HH .DB $00 +PCRTC_MM .DB $00 +PCRTC_SS .DB $00 + diff --git a/Source/HBIOS/pio.asm b/Source/HBIOS/pio.asm index 444fb64b..8954d3c6 100644 --- a/Source/HBIOS/pio.asm +++ b/Source/HBIOS/pio.asm @@ -85,9 +85,7 @@ PIO_INITUNIT: ; ; SET DEFAULT CONFIG LD DE,-1 ; LEAVE CONFIG ALONE - ; CALL INITDEVX TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL - ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! - JP PIO_INITDEVX ; IMPLEMENT IT AND RETURN + JP PIO_INITDEV ; IMPLEMENT IT AND RETURN ; ; ; @@ -146,17 +144,21 @@ PIO_OST: XOR A ; NO BUFFER SPACE AVAIL RET ; -; NOTE THAT THERE ARE TWO ENTRY POINTS. INITDEV WILL DISABLE/ENABLE INTS -; AND INITDEVX WILL NOT. THIS IS DONE SO THAT THE PREINIT ROUTINE ABOVE -; CAN AVOID ENABLING/DISABLING INTS. -; PIO_INITDEV: + ; INITDEV CAN BE CALLED PRIOR TO INTERRUPTS BEING ENABLED. WE + ; NEED TO LEAVE INTERRUPTS ALONE IN THIS SCENARIO + LD A,(INTSENAB) ; INTS ENABLED? + OR A ; TEST VALUE + JR Z,PIO_INITDEV0 ; BYPASS DI/EI IF NOT ENABLED +; + ; INTERRUPTS DISABLED DURING INIT + ; ??? IS THIS NEEDED? HB_DI ; DISABLE INTS - CALL PIO_INITDEVX ; DO THE WORK + CALL PIO_INITDEV0 ; DO THE WORK HB_EI ; INTS BACK ON RET ; DONE ; -PIO_INITDEVX: +PIO_INITDEV0: ; ; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY ; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! diff --git a/Source/HBIOS/romfonts.asm b/Source/HBIOS/romfonts.asm new file mode 100644 index 00000000..2cfd77be --- /dev/null +++ b/Source/HBIOS/romfonts.asm @@ -0,0 +1,135 @@ +; +;============================================================================= +; ROMFONTS.ASM - ROM HOSTED FONTS +;============================================================================= +; +; THIS ASSEMBLY IS PURELY A DATA ASSEMBLY USED TO INCLUDE THE ROM-HOSTED +; FONTS. +; +; FOR NOW, WE ARE JUST INCLUDING 3 FONTS AND THEY ARE NOT COMPRESSED. +; +#INCLUDE "std.asm" +; +COMP .EQU $80 ; BIT MASK FOR COMPRESSED FONT +RAW .EQU $00 ; BIT MASK FOR RAW FONT +; +; FONT INCLUSION CONTROLS. THE FMT_XXX SETTING CONTROLS WHETHER THE +; FONT DATA WILL BE COMPRESSED OR NOT. GENERALLY, COMPRESSED IS USED +; TO SAVE SPACE. THE 6X8 FONT IS AN EXCEPTION BECAUSE IT IS USED BY +; THE TMS DRIVER WHICH RELOADS THE FONT ON-THE-FLY DURING SYSTEM +; OPERATION. SEE TMS.ASM. +; +USEFONT6X8 .EQU TRUE +FMT_6X8 .EQU RAW +; +USEFONT8X8 .EQU TRUE +FMT_8X8 .EQU COMP +; +USEFONT8X11 .EQU TRUE +FMT_8X11 .EQU COMP +; +USEFONT8X16 .EQU TRUE +FMT_8X16 .EQU COMP +; + .ORG FONTS_LOC +; +; FONT LOCATION MAP +; + .DB 'F','M' ; TABLE SIGNATURE +#IF USEFONT6X8 + .DB FONTID_6X8 | FMT_6X8 + .DW FONT6X8 +#ENDIF +; +#IF USEFONT8X8 + .DB FONTID_8X8 | FMT_8X8 + .DW FONT8X8 +#ENDIF +; +#IF USEFONT8X11 + .DB FONTID_8X11 | FMT_8X11 + .DW FONT8X11 +#ENDIF +; +#IF USEFONT8X16 + .DB FONTID_8X16 | FMT_8X16 + .DW FONT8X16 +#ENDIF +; + .DB 0 ; END OF TABLE +; +; INCLUDE ACTUAL FONT FILES +; +#IF USEFONT6X8 + .ECHO "FONT6X8: " +FONT6X8: + #IF (FMT_6X8 == COMP) + .ECHO "COMPRESSED " + #INCLUDE "font6x8c.asm" + #ELSE + .ECHO "RAW " + #INCLUDE "font6x8u.asm" + #ENDIF + .ECHO $ - FONT6X8 + .ECHO " BYTES\n" +#ENDIF +; +#IF USEFONT8X8 + .ECHO "FONT8X8: " +FONT8X8: + #IF (FMT_8X8 == COMP) + .ECHO "COMPRESSED " + #INCLUDE "font8x8c.asm" + #ELSE + .ECHO "RAW " + #INCLUDE "font8x8u.asm" + #ENDIF + .ECHO $ - FONT8X8 + .ECHO " BYTES\n" +#ENDIF +; +#IF USEFONT8X11 + .ECHO "FONT8X11: " +FONT8X11: + #IF (FMT_8X11 == COMP) + .ECHO "COMPRESSED " + #INCLUDE "font8x11c.asm" + #ELSE + .ECHO "RAW " + #INCLUDE "font8x11u.asm" + #ENDIF + .ECHO $ - FONT8X11 + .ECHO " BYTES\n" +#ENDIF +; +#IF USEFONT8X16 + .ECHO "FONT8X16: " +FONT8X16: + #IF (FMT_8X16 == COMP) + .ECHO "COMPRESSED " + #INCLUDE "font8x16c.asm" + #ELSE + .ECHO "RAW " + #INCLUDE "font8x16u.asm" + #ENDIF + .ECHO $ - FONT8X16 + .ECHO " BYTES\n" +#ENDIF +; +; IT IS CRITICAL THAT THE FINAL BINARY BE EXACTLY USR_SIZ BYTES. +; THIS GENERATES FILLER AS NEEDED. IT WILL ALSO FORCE AN ASSEMBLY +; ERROR IF THE SIZE EXCEEDS THE SPACE ALLOCATED. +; +SLACK .EQU (FONTS_END - $) +; +#IF (SLACK < 0) + .ECHO "*** FONTS IS TOO BIG!!!\n" + !!! ; FORCE AN ASSEMBLY ERROR +#ENDIF +; + .FILL SLACK,$00 + .ECHO "FONTS space remaining: " + .ECHO SLACK + .ECHO " bytes.\n" +; + .END diff --git a/Source/HBIOS/romldr.asm b/Source/HBIOS/romldr.asm index 84177edb..c438d74b 100644 --- a/Source/HBIOS/romldr.asm +++ b/Source/HBIOS/romldr.asm @@ -119,6 +119,7 @@ bid_cur .equ -1 ; used below to indicate current bank ; ; Note: at startup, we should not assume which bank we are operating in. ; + ld a,e ; save startup mode ; Relocate to start of common ram at $8000 ld hl,0 ld de,$8000 @@ -131,6 +132,7 @@ bid_cur .equ -1 ; used below to indicate current bank ; start: ld sp,bl_stack ; setup private stack + ld (startmode),a ; save startup mode call delay_init ; init delay functions ; ; Disable interrupts if IM1 is active because we are switching to page @@ -220,6 +222,20 @@ start2: ld (dskyact),a ; save it #endif +; +;======================================================================= +; Print Device List +;======================================================================= +; +#if (BIOS == BIOS_WBW) +; + ; We don't have a start mode for UNA. So, the device display + ; will only occur when selected from the menu. + ld a,(startmode) ; get start mode + cp START_COLD ; cold start? + call z,prtall ; if so, display Device List. +; +#endif ; ;======================================================================= ; Boot Loader Banner @@ -625,6 +641,10 @@ runcmd0: cp 'R' ; R = reboot system jp z,reboot ; if so, do it #if (BIOS == BIOS_WBW) + cp 'S' ; S = Slice Inventory + jp z,slclst ; if so, do it + cp 'W' ; W = Rom WBW NVR Config Rom App + jp z,nvrconfig ; if so, do it cp 'I' ; C = set console interface jp z,setcon ; if so, do it cp 'V' ; V = diagnostic verbosity @@ -632,18 +652,8 @@ runcmd0: #endif ; ; Attempt ROM application launch - ld ix,(ra_tbl_loc) ; point to start of ROM app tbl - ld c,a ; save command in C -runcmd1: - ld a,(ix+ra_conkey) ; get match char - and ~$80 ; clear "hidden entry" bit - cp c ; compare - jp z,romload ; if match, load it - ld de,ra_entsiz ; table entry size - add ix,de ; bump IX to next entry - ld a,(ix) ; check for end - or (ix+1) ; ... of table - jr nz,runcmd1 ; loop till done + call findcon ; find the application from console Key in A REG + jp z,romload ; if match found, then load it ; ; Attempt disk boot ld de,cmdbuf ; start of buffer @@ -858,8 +868,16 @@ dskycmd1: ; Display Help ; help: - ld hl,str_help ; point to help string + ld hl,str_help1 ; load first help string + call pstr ; display it + ld a,(bootmode) ; get boot mode + cp BM_ROMBOOT ; ROM boot? + jr nz,help1 ; if not, skip str_help2 + ld hl,str_help2 ; load second help string call pstr ; display it +help1: + ld hl,str_help3 ; load third help string + call pstr ; display it ret ; ; List ROM apps @@ -905,6 +923,18 @@ applst2: devlst: jp prtall ; do it ; +; Slice list +; +slclst: + ld a,'S' ; "S"lice Inv App + jp romcall ; Call a Rom App with Return +; +; RomWBW Config +; +nvrconfig: + ld a,'W' ; "W" Rom WBW Configure App + jp romcall ; Call a Rom App with Return +; ; Set console interface unit ; #if (BIOS == BIOS_WBW) @@ -1054,6 +1084,27 @@ reboot: #endif ; ;======================================================================= +; Call a ROM Application (with return) +; This is same as romload: but doesnt display load messages +; Intended for Utility applications (part of RomWBW) not third part apps +; these apps are on Help menu, hidden from Application List +; Parameters A - The app to call. +;======================================================================= +; +romcall: + call findcon ; find the application based on A reg + ret nz ; if not found then return to prompt +; + call romcopy ; Copy ROM App into working memory +; + ld l,(ix+ra_ent) ; HL := app entry address + ld h,(ix+ra_ent+1) ; IX register returned from findcon + jp (hl) ; call to the routine. + ; + ; NOTE It is assumed the Rom App should perform a RET, + ; returning control to the caller of this sub routine. +; +;======================================================================= ; Load and run a ROM application, IX=ROM app table entry ;======================================================================= ; @@ -1066,36 +1117,49 @@ romload: ld h,(ix+ra_name+1) call pstr ; - ;ld hl,msg_load ; point to load message - ;call dsky_show ; display message ld c,DSKY_MSG_LDR_LOAD ; point to load message call dsky_msg ; display message +; + call romcopy ; Copy ROM App into working memory + ld a,'.' ; dot character + call cout ; show progress +; + ld c,DSKY_MSG_LDR_GO ; point to go message + call dsky_msg ; display message +; + ld l,(ix+ra_ent) ; HL := app entry address + ld h,(ix+ra_ent+1) ; ... + jp (hl) ; go +; +;======================================================================= +; Routine - Copy Rom App from Rom to it's running location +; param : IX - Pointer to the Rom App to copy into RAM +;======================================================================= +; +romcopy: ; #if (BIOS == BIOS_WBW) ; - ; Copy image to it's running location ld a,(ix+ra_bnk) ; get image source bank id cp bid_cur ; special value? - jr nz,romload1 ; if not, continue + jr nz,romcopy1 ; if not, continue ld a,(bid_ldr) ; else substitute -romload1: +romcopy1: push af ; save source bank + ; ld e,a ; source bank to E ld d,BID_USR ; dest is user bank ld l,(ix+ra_siz) ; HL := image size ld h,(ix+ra_siz+1) ; ... ld b,BF_SYSSETCPY ; HBIOS func: setup bank copy rst 08 ; do it - ld a,'.' ; dot character - call cout ; show progress + ; ld e,(ix+ra_dest) ; DE := run dest adr ld d,(ix+ra_dest+1) ; ... ld l,(ix+ra_src) ; HL := image source adr ld h,(ix+ra_src+1) ; ... ld b,BF_SYSBNKCPY ; HBIOS func: bank copy rst 08 ; do it - ld a,'.' ; dot character - call cout ; show progress ; ; Record boot information pop af ; recover source bank @@ -1104,8 +1168,6 @@ romload1: ld b,BF_SYSSET ; HBIOS func: system set ld c,BF_SYSSET_BOOTINFO ; BBIOS subfunc: boot info rst 08 ; do it - ld a,'.' ; dot character - call cout ; show progress ; #endif ; @@ -1121,8 +1183,6 @@ romload1: ld bc,$01FB ; UNA func: set bank ld de,(bid_ldr) ; select user bank rst 08 ; do it - ld a,'.' ; dot character - call cout ; show progress ; ; Copy image to running location ld l,(ix+ra_src) ; HL := image source adr @@ -1132,15 +1192,11 @@ romload1: ld c,(ix+ra_siz) ; BC := image size ld b,(ix+ra_siz+1) ; ... ldir ; copy image - ld a,'.' ; dot character - call cout ; show progress ; ; Switch back to user bank ld bc,$01FB ; UNA func: set bank ld de,(bid_ldr) ; select user bank rst 08 ; do it - ld a,'.' ; dot character - call cout ; show progress ; ; Record boot information ld de,(bid_ldr) ; original bank @@ -1150,15 +1206,7 @@ romload1: ; #endif ; - ;ld hl,msg_go ; point to go message - ;call dsky_show ; display message - ld c,DSKY_MSG_LDR_GO ; point to go message - call dsky_msg ; display message -; - ld l,(ix+ra_ent) ; HL := app entry address - ld h,(ix+ra_ent+1) ; ... - jp (hl) ; go -; + ret ;======================================================================= ; Boot ROM Application ;======================================================================= @@ -1166,20 +1214,32 @@ romload1: ; Enter with ROM application menu selection (command) character in A ; romboot: + call findcon ; Match the application base on console command in A + jp z,romload ; if match application found then load it + ret ; no match, just return to - prompt: +; +;======================================================================= +; Find App For Console Command +; Pass in A, the console command character +; Return IX pointer, and Z if found; NZ if not found +;======================================================================= +; +findcon: call upcase ; force uppercase for matching ld ix,(ra_tbl_loc) ; point to start of ROM app tbl ld c,a ; save command char in C -romboot1: +findcon1: ld a,(ix+ra_conkey) ; get match char and ~$80 ; clear "hidden entry" bit cp c ; compare - jp z,romload ; if match, load it + ret z ; if matched, return ld de,ra_entsiz ; table entry size add ix,de ; bump IX to next entry ld a,(ix) ; check for end or (ix+1) ; ... of table - jr nz,romboot1 ; loop till done - ret ; no match, just return + jr nz,findcon1 ; loop if still more table entries + or 0ffh ; set NZ flag, signal not found + ret ; no match, and return ; ;======================================================================= ; Boot disk unit/slice @@ -1553,11 +1613,11 @@ s100mon1: ; Launch S100 Monitor from ROM Bank 3 call ldelay ; wait for UART buf to empty di ; suspend interrupts - ld a,BID_IMG2 ; S100 monitor bank - ld ix,0 ; execution resumes here + ld a,HWMON_BNK ; S100 monitor bank + ld ix,HWMON_IMGLOC ; execution resumes here jp HB_BNKCALL ; do it ; -str_smon .db "S100 Z180 Monitor",0 +str_smon .db "S100 Z180 Hardware Monitor",0 str_s100con .db "\r\n\r\nConsole on S100 Bus",0 ; #endif @@ -2267,12 +2327,11 @@ CST .equ cst ; ; Print list of all drives (WBW) ; -; Just invoke the existing HBIOS routine... +; Call the Rom App to perform this ; prtall: - ld a,BID_BIOS ; BIOS Bank please - ld ix,$0406 ; HBIOS PRTSUM vector - jp HB_BNKCALL ; do it + ld a,'D' ; "D"evice Inventory App + jp romcall ; Call a Rom App with Return ; #endif ; @@ -2280,6 +2339,8 @@ prtall: ; ; Print list of all drives (UNA) ; +; UNA has no place to put this in ROM, so it is done here. +; prtall: ld hl,str_devlst ; device list header string call pstr ; display it @@ -2534,16 +2595,35 @@ str_binfo5 .db "]",0 str_ldsec .db ", Sector 0x",0 str_diaglvl .db "\r\n\r\nHBIOS Diagnostic Level: ",0 ; -str_help .db "\r\n" +; +; Help text is broken into 3 pieces because an application mode boot +; does allow access to the ROM-hosted features. The str_help2 portion +; is only displayed for a ROM boot. +; +str_help1: + .db "\r\n" .db "\r\n L - List ROM Applications" + .db "\r\n [.] - Boot Disk Unit/Slice" + .db 0 +; +str_help2: +#if (BIOS == BIOS_WBW) + .db "\r\n N - Network Boot" +#endif .db "\r\n D - Device Inventory" - .db "\r\n R - Reboot System" #if (BIOS == BIOS_WBW) + .db "\r\n S - Slice Inventory" .db "\r\n W - RomWBW Configure" +#endif + .db 0 +; +str_help3: +#if (BIOS == BIOS_WBW) + .db "\r\n I [] - Set Console Interface/Baud Rate" .db "\r\n V [] - View/Set HBIOS Diagnostic Verbosity" #endif - .db "\r\n [.] - Boot Disk Unit/Slice" + .db "\r\n R - Reboot System" .db 0 ; ;======================================================================= @@ -2629,31 +2709,34 @@ ra_ent .equ 12 ; ra_tbl: ; -; Name Key Dsky Bank Src Dest Size Entry -; --------- ------- ----- -------- ----- ------- ------- ---------- -ra_ent(str_mon, 'M', KY_CL, BID_IMG0, MON_IMGLOC, MON_LOC, MON_SIZ, MON_SERIAL) +; Name Key Dsky Bank Src Dest Size Entry +; --------- ------- ----- -------- ----- ------- ------- ---------- +ra_ent(str_mon, 'M', KY_CL, MON_BNK, MON_IMGLOC, MON_LOC, MON_SIZ, MON_SERIAL) ra_entsiz .equ $ - ra_tbl #if (BIOS == BIOS_WBW) #if (PLATFORM == PLT_S100) -ra_ent(str_smon, 'S', $FF, bid_cur , $8000, $8000, $0001, s100mon) +ra_ent(str_smon, 'O', $FF, bid_cur, $8000, $8000, $0001, s100mon) #endif #endif -ra_ent(str_cpm22, 'C', KY_BK, BID_IMG0, CPM_IMGLOC, CPM_LOC, CPM_SIZ, CPM_ENT) -ra_ent(str_zsys, 'Z', KY_FW, BID_IMG0, ZSYS_IMGLOC, CPM_LOC, CPM_SIZ, CPM_ENT) +ra_ent(str_cpm22, 'C', KY_BK, CPM22_BNK, CPM22_IMGLOC, CPM_LOC, CPM_SIZ, CPM_ENT) +ra_ent(str_zsys, 'Z', KY_FW, ZSYS_BNK, ZSYS_IMGLOC, CPM_LOC, CPM_SIZ, CPM_ENT) #if (BIOS == BIOS_WBW) -ra_ent(str_bas, 'B', KY_DE, BID_IMG1, BAS_IMGLOC, BAS_LOC, BAS_SIZ, BAS_LOC) -ra_ent(str_tbas, 'T', KY_EN, BID_IMG1, TBC_IMGLOC, TBC_LOC, TBC_SIZ, TBC_LOC) -ra_ent(str_fth, 'F', KY_EX, BID_IMG1, FTH_IMGLOC, FTH_LOC, FTH_SIZ, FTH_LOC) -ra_ent(str_play, 'P', $FF, BID_IMG1, GAM_IMGLOC, GAM_LOC, GAM_SIZ, GAM_LOC) -ra_ent(str_net, 'N', $FF, BID_IMG1, NET_IMGLOC, NET_LOC, NET_SIZ, NET_LOC) -ra_ent(str_upd, 'X', $FF, BID_IMG1, UPD_IMGLOC, UPD_LOC, UPD_SIZ, UPD_LOC) -ra_ent(str_nvr, 'W'+$80, $FF, BID_IMG1, NVR_IMGLOC, NVR_LOC, NVR_SIZ, NVR_LOC) -ra_ent(str_user, 'U', $FF, BID_IMG1, USR_IMGLOC, USR_LOC, USR_SIZ, USR_LOC) +ra_ent(str_bas, 'B', KY_DE, BAS_BNK, BAS_IMGLOC, BAS_LOC, BAS_SIZ, BAS_LOC) +ra_ent(str_tbas, 'T', KY_EN, TBC_BNK, TBC_IMGLOC, TBC_LOC, TBC_SIZ, TBC_LOC) +ra_ent(str_fth, 'F', KY_EX, FTH_BNK, FTH_IMGLOC, FTH_LOC, FTH_SIZ, FTH_LOC) +ra_ent(str_play, 'P', $FF, GAM_BNK, GAM_IMGLOC, GAM_LOC, GAM_SIZ, GAM_LOC) +ra_ent(str_net, 'N'+$80, $FF, NET_BNK, NET_IMGLOC, NET_LOC, NET_SIZ, NET_LOC) +ra_ent(str_upd, 'X', $FF, UPD_BNK, UPD_IMGLOC, UPD_LOC, UPD_SIZ, UPD_LOC) +ra_ent(str_blnk, 'W'+$80, $FF, NVR_BNK, NVR_IMGLOC, NVR_LOC, NVR_SIZ, NVR_LOC) +ra_ent(str_blnk, 'D'+$80, $FF, DEV_BNK, DEV_IMGLOC, DEV_LOC, DEV_SIZ, DEV_LOC) +ra_ent(str_blnk, 'S'+$80, $FF, SLC_BNK, SLC_IMGLOC, SLC_LOC, SLC_SIZ, SLC_LOC) +ra_ent(str_user, 'U', $FF, USR_BNK, USR_IMGLOC, USR_LOC, USR_SIZ, USR_LOC) #endif #if (DSKYENABLE) -ra_ent(str_dsky, 'Y'+$80, KY_GO, BID_IMG0, MON_IMGLOC, MON_LOC, MON_SIZ, MON_DSKY) +ra_ent(str_dsky, 'Y'+$80, KY_GO, MON_BNK, MON_IMGLOC, MON_LOC, MON_SIZ, MON_DSKY) #endif -ra_ent(str_egg, 'E'+$80, $FF, BID_IMG1, EGG_IMGLOC, EGG_LOC, EGG_SIZ, EGG_LOC) +ra_ent(str_blnk, 'E'+$80, $FF, EGG_BNK, EGG_IMGLOC, EGG_LOC, EGG_SIZ, EGG_LOC) +; .dw 0 ; table terminator ; ra_tbl_app: @@ -2665,6 +2748,7 @@ ra_ent(str_zsys, 'Z', KY_FW, bid_cur, ZSYS_IMGLOC, CPM_LOC, CPM_SIZ, CPM_EN #if (DSKYENABLE) ra_ent(str_dsky, 'Y'+$80, KY_GO, bid_cur, MON_IMGLOC, MON_LOC, MON_SIZ, MON_DSKY) #endif +; .dw 0 ; table terminator ; str_mon .db "Monitor",0 @@ -2676,9 +2760,8 @@ str_bas .db "BASIC",0 str_tbas .db "Tasty BASIC",0 str_play .db "Play a Game",0 str_upd .db "XModem Flash Updater",0 -str_nvr .db "RomWBW Configure", 0 str_user .db "User App",0 -str_egg .db "",0 +str_blnk .db "",0 str_net .db "Network Boot",0 str_switches .db "FP Switches = 0x",0 str_nvswitches .db "NV Switches Found",0 @@ -2705,6 +2788,7 @@ sps .dw 0 ; sectors per slice mediaid .db 0 ; media id ; bootmode .db 0 ; ROM, APP, or IMG boot +startmode .db 0 ; START_WARM or START_COLD ra_tbl_loc .dw 0 ; points to active ra_tbl bootunit .db 0 ; boot disk unit bootslice .db 0 ; boot disk slice diff --git a/Source/HBIOS/rp5rtc.asm b/Source/HBIOS/rp5rtc.asm index 2a7b99a6..b86ddf70 100644 --- a/Source/HBIOS/rp5rtc.asm +++ b/Source/HBIOS/rp5rtc.asm @@ -136,7 +136,7 @@ RP5RTC_DETECT: RP5RTC_DETECT1: PUSH AF ; SAVE STATUS - LD A, L ; GET SAVED VALUE + LD E, L ; GET SAVED VALUE LD C, 0 ; NVRAM INDEX 0 CALL RP5RTC_SETBYT ; SAVE IT POP AF ; RECOVER STATUS diff --git a/Source/HBIOS/s100mon.z80 b/Source/HBIOS/s100mon.z80 index 49000945..fbcfb5a2 100644 --- a/Source/HBIOS/s100mon.z80 +++ b/Source/HBIOS/s100mon.z80 @@ -432,16 +432,16 @@ CNTLB0_VALUE equ 00H ; For setting final baud rate from ; jp mon_start - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;To clean up PROM for easy reading - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 - Db 0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ;To clean up PROM for easy reading +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +;;; Db 0,0,0,0 ; Jump to monitor!!! ; diff --git a/Source/HBIOS/sio.asm b/Source/HBIOS/sio.asm index 73f5d189..5d0027b1 100644 --- a/Source/HBIOS/sio.asm +++ b/Source/HBIOS/sio.asm @@ -199,9 +199,7 @@ SIO_INITUNIT: ; ; SET DEFAULT CONFIG LD DE,-1 ; LEAVE CONFIG ALONE - ; CALL INITDEVX TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL - ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! - JP SIO_INITDEVX ; IMPLEMENT IT AND RETURN + JP SIO_INITDEV ; IMPLEMENT IT AND RETURN ; ; ; @@ -472,17 +470,20 @@ SIO_OST: ; MARK & SPACE PARITY AND 1.5 STOP BITS IS NOT SUPPORTED BY THE SIO. ; INITIALIZATION WILL NOT BE COMPLETED IF AN INVALID SETTING IS DETECTED. ; -; NOTE THAT THERE ARE TWO ENTRY POINTS. INITDEV WILL DISABLE/ENABLE INTS -; AND INITDEVX WILL NOT. THIS IS DONE SO THAT THE PREINIT ROUTINE ABOVE -; CAN AVOID ENABLING/DISABLING INTS. -; SIO_INITDEV: + ; INITDEV CAN BE CALLED PRIOR TO INTERRUPTS BEING ENABLED. WE + ; NEED TO LEAVE INTERRUPTS ALONE IN THIS SCENARIO + LD A,(INTSENAB) ; INTS ENABLED? + OR A ; TEST VALUE + JR Z,SIO_INITDEV0 ; BYPASS DI/EI IF NOT ENABLED +; + ; INTERRUPTS DISABLED DURING INIT HB_DI ; DISABLE INTS - CALL SIO_INITDEVX ; DO THE WORK + CALL SIO_INITDEV0 ; DO THE WORK HB_EI ; INTS BACK ON RET ; DONE ; -SIO_INITDEVX: +SIO_INITDEV0: ; ; THIS ENTRY POINT BYPASSES DISABLING/ENABLING INTS WHICH IS REQUIRED BY ; PREINIT ABOVE. PREINIT IS NOT ALLOWED TO ENABLE INTS! diff --git a/Source/HBIOS/sn76489.asm b/Source/HBIOS/sn76489.asm index c6e8c42c..a9f1ffe3 100644 --- a/Source/HBIOS/sn76489.asm +++ b/Source/HBIOS/sn76489.asm @@ -452,10 +452,10 @@ SNT_REGWR .DB "\r\nOUT SN76489, $" #ENDIF ; ;====================================================================== -; QUARTER TONE FREQUENCY TABLE +; EIGHTH TONE FREQUENCY TABLE ;====================================================================== ; -; THE FOLLOWING TABLE MAPS A FULL OCTAVE OF QUARTER-NOTES +; THE FOLLOWING TABLE MAPS A FULL OCTAVE OF EIGHTH-TONES ; STARTING AT A# IN OCTAVE 0 TO THE CORRESPONDING PERIOD ; VALUE TO USE ON THE PSG TO ACHIEVE THE DESIRED NOTE FREQUENCY. ; diff --git a/Source/HBIOS/spk.asm b/Source/HBIOS/spk.asm index 3ceb148c..d754aceb 100644 --- a/Source/HBIOS/spk.asm +++ b/Source/HBIOS/spk.asm @@ -1,11 +1,12 @@ ;====================================================================== ; -; BIT MODE SOUND DRIVER FOR SBC V2 USING BIT 0 OF RTC DRIVER +; BIT MODE SOUND DRIVER FOR USING 1 BIT OF AN IO PORT +; TAKING CARE NOT TO CHANGE OTHER BITS ; ;====================================================================== ; ; LIMITATIONS - CPU FREQUENCY ADJUSTMENT LIMITED TO 1MHZ RESOLUTION -; QUARTER TONES NOT SUPPORTED +; EIGHTH TONES NOT SUPPORTED ; DURATION FIXED TO 1 SECOND. ; NO VOLUME ADJUSTMENT DUE TO HARDWARE LIMITATION ;====================================================================== @@ -32,9 +33,7 @@ SP_IDAT .EQU 0 ; NO INSTANCE DATA ASSOCIATED WITH THIS DEVICE ; SP_TONECNT .EQU 1 ; COUNT NUMBER OF TONE CHANNELS SP_NOISECNT .EQU 0 ; COUNT NUMBER OF NOISE CHANNELS -; -SP_RTCIOMSK .EQU 00000100B -; + ; FOR OTHER DRIVERS, THE PERIOD VALUE FOR THE TONE IS STORED AT PENDING_PERIOD ; FOR THE SPK DRIVER THE ADDRESS IN THE TONE TABLE IS STORED IN PENDING_PERIOD ; @@ -43,9 +42,12 @@ SP_PENDING_VOLUME .DB 0 ; PENDING VOL (8 BITS) SP_PENDING_DURATION .DW 0 ; PENDING DURATION (16 BITS) SP_TBLRDY .DB 0 ; IF != 0, NOTE TABLE IS READY ; - DEVECHO "SPK: IO=" - DEVECHO RTCIO - DEVECHO "\n" + DEVECHO "SPK: IO=" + DEVECHO SPKPORT + DEVECHO " MASK=" + DEVECHO SPKMASK + DEVECHO "\n" + ; ;====================================================================== ; DRIVER INITIALIZATION @@ -59,9 +61,12 @@ SP_INIT: ; CALL NEWLINE ; ANNOUNCE DEVICE PRTS("SPK: IO=0x$") - LD A,RTCIO + LD A,SPKPORT CALL PRTHEXBYTE -; + PRTS(" MASK=0x$") + LD A,SPKMASK + CALL PRTHEXBYTE + ; CALL SP_SETTBL ; SETUP TONE TABLE CALL SP_RESET ; RESET PARAMETERS ; @@ -113,7 +118,7 @@ SP_NOTE: AND 00000011B ; TO THE ASSOCIATED ENTRY JR Z,SP_NOTE1 ; IN THE TUNE TABLE. ; - LD HL,$FFFF ; QUARTER NOTES + LD HL,$FFFF ; EIGHTH TONES JR SP_NOTE2 ; NOT SUPPORTED ; SP_NOTE1: @@ -165,7 +170,7 @@ SP_QUERY_VOLUME: ; SP_QUERY_DEV: LD B, SNDDEV_BITMODE ; RETURN DEVICE IDENTIFIER - LD DE, (RTCIO*256)+SP_RTCIOMSK ; AND ADDRESS AND DATA PORT + LD DE, (SPKPORT*256)+SPKMASK ; AND ADDRESS AND DATA PORT XOR A RET ; @@ -283,7 +288,7 @@ SP_BEEPER: LD B,$00 LD IX,SPK_DLYADJ ; The base address of the timing loop. ADD IX,BC ; Alter the length of the timing loop. Use an earlier starting point for each '1' lost by taking INT (L/4). - LD A,(HB_RTCVAL) ; Fetch the present border colour from BORDCR and move it to bits 2, 1 and 0 of the A register. + LD A,(SPKSHADOW) ; Fetch the present border colour from BORDCR and move it to bits 2, 1 and 0 of the A register. ; ; The HL register holds the 'length of the timing loop' with 16 T states being used for each '1' in the L register and 1024 T states for each '1' in the H register. ; @@ -302,8 +307,9 @@ BE_H_L_LP: ; ; The loudspeaker is now alternately activated and deactivated. ; - XOR SP_RTCIOMSK ; Flip bit 2. - OUT (RTCIO),A ; Perform the 'OUT' operation, leaving other bits unchanged. + XOR SPKMASK ; Flip bit. + OUT (SPKPORT),A ; Perform the 'OUT' operation, leaving other bits unchanged. + LD B,H ; Reset the B register. LD C,A ; Save the A register. BIT 4,A ; Jump if at the half-cycle point. @@ -333,8 +339,8 @@ BE_END: ; leaves the bit set to the opposite value it started at. This ; ensures that the bit is properly reset to its original value. ; - LD A,(HB_RTCVAL) ; Get the current RTC latch value - OUT (RTCIO),A ; Set it + LD A,(SPKSHADOW) ; Get the current port value (typically RTC latch) + OUT (SPKPORT),A ; Set it ; RET ; ALWAYS EXITS WITH SUCCESS STATUS (A=0) ; @@ -356,7 +362,7 @@ SP_DEVICE: LD E,0 ; E := PHYSICAL UNIT LD C,$00 ; C := DEVICE TYPE LD H,0 ; H := 0, DRIVER HAS NO MODES - LD L,RTCIO ; L := BASE I/O ADDRESS + LD L,SPKPORT ; L := BASE I/O ADDRESS XOR A RET ; diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm index 38e075fe..e9d77ec3 100644 --- a/Source/HBIOS/std.asm +++ b/Source/HBIOS/std.asm @@ -80,6 +80,11 @@ BM_ROMBOOT .EQU 1 ; ROM BOOT BM_APPBOOT .EQU 2 ; APPLICATION BOOT BM_IMGBOOT .EQU 3 ; IMAGE BOOT (DEPRECATED) ; +; HBIOS STARTUP MODES +; +START_WARM .EQU 1 ; COLD START +START_COLD .EQU 2 ; WARM START +; ; MEMORY MANAGERS ; MM_NONE .EQU 0 @@ -283,6 +288,7 @@ TMSMODE_MBC .EQU 6 ; MBC V9938/58 VIDEO BOARD TMSMODE_COLECO .EQU 7 ; COLECOVISION PORT MAPPING TMSMODE_DUO .EQU 8 ; DUODYNE PORT MAPPING TMSMODE_NABU .EQU 9 ; NABU +TMSMODE_MSXUKY .EQU 10 ; STD MSX PORTS + USB KEYBOARD ; ; CVDU VIDEO MODE SELECTIONS ; @@ -327,6 +333,21 @@ SYQMODE_NONE .EQU 0 ; NONE SYQMODE_SPP .EQU 1 ; IBM PC STANDARD PAR PORT (SPP) SYQMODE_MG014 .EQU 2 ; RCBUS MG014 STYLE INTERFACE ; +; PCF CLOCK CHIP FREQUENCIES +; +PCFCLK_3 .EQU $00 ; 3 MHz +PCFCLK_443 .EQU $10 ; 4.43 MHz +PCFCLK_6 .EQU $14 ; 6 MHz +PCFCLK_8 .EQU $18 ; 8 MHz +PCFCLK_12 .EQU $1C ; 12 MHz +; +; PCF TRANSMISSION FREQUENCIES +; +PCFTRNS_90 .EQU $00 ; 90 KHZ +PCFTRNS_45 .EQU $01 ; 45 KHZ +PCFTRNS_11 .EQU $02 ; 11 KHZ +PCFTRNS_15 .EQU $03 ; 1.5 KHZ +; ; GDC MONITOR SELECTIONS ; GDCMON_NONE .EQU 0 @@ -522,6 +543,7 @@ PPKENABLE .EQU FALSE ; PPK KEYBOARD DRIVER MKYENABLE .EQU FALSE ; MSX KEYBOARD DRIVER NABUKBENABLE .EQU FALSE ; NABU KEYBOARD DRIVER FVKBDENABLE .EQU FALSE ; FPGA KEYBOARD DRIVER +USBKYBENABLE .EQU FALSE ; USB KEYBOARD DRIVER ; ; VIDEO MODES ; @@ -534,6 +556,13 @@ V80X43 .EQU 5 ; ECB-VGA3 V80X60 .EQU 6 ; ECB-VGA3 V40X24 .EQU 7 ; EF9345 ; +; FONT IDS +; +FONTID_6X8 .EQU 1 +FONTID_8X8 .EQU 2 +FONTID_8X11 .EQU 3 +FONTID_8X16 .EQU 4 +; ; KEYBOARD LAYOUTS ; KBD_US .EQU 0 ; US ENGLISH @@ -866,8 +895,8 @@ ROMD_BNKS .SET 0 ; -- TYPICAL -- BID_BOOT .EQU BID_ROM0 + 0 ; BOOT BANK 0x00 BID_IMG0 .EQU BID_ROM0 + 1 ; ROM LOADER AND FIRST IMAGES BANK 0x01 -BID_IMG1 .EQU BID_ROM0 + 2 ; SECOND IMAGES BANK 0x02 -BID_IMG2 .EQU BID_ROM0 + 3 ; RESERVED 0x03 +BID_IMG1 .EQU BID_ROM0 + 2 ; ROM APPS IMAGES BANK 0x02 +BID_IMG2 .EQU BID_ROM0 + 3 ; ROM UTILITIES IMAGES BANK 0x03 BID_ROMD0 .EQU BID_ROM0 + 4 ; FIRST ROM DRIVE BANK 0x04 BID_BIOS .EQU BID_RAM0 + 0 ; HBIOS BANK 0x80 BID_RAMD0 .EQU BID_RAM0 + 1 ; FIRST RAM DRIVE BANK 0x81 @@ -884,8 +913,8 @@ BID_COM .EQU BID_RAMN - 0 ; COMMON BANK, UPPER 32K 0x8F ; -- TYPICAL -- BID_BOOT .EQU BID_RAM0 + 0 ; BOOT BANK 0x80 BID_IMG0 .EQU BID_RAM0 + 1 ; ROM LOADER AND FIRST IMAGES BANK 0x81 -BID_IMG1 .EQU BID_RAM0 + 2 ; SECOND IMAGES BANK 0x82 -BID_IMG2 .EQU BID_RAM0 + 3 ; RESERVED 0x83 +BID_IMG1 .EQU BID_RAM0 + 2 ; ROM APPS IMAGES BANK 0x82 +BID_IMG2 .EQU BID_RAM0 + 3 ; ROM UTILITIES IMAGES BANK 0x83 BID_RAMD0 .EQU BID_RAM0 + 4 ; FIRST RAM DRIVE BANK 0x84 BID_APP0 .EQU BID_RAMD0 + RAMD_BNKS ; FIRST APP BANK 0x89 BID_BUF .EQU BID_RAMN - 3 ; OS BUFFERS (CP/M3) 0x8C @@ -956,9 +985,7 @@ APP_BNKS .SET 0 ; #INCLUDE "layout.inc" ; -; -MON_DSKY .EQU MON_LOC + (0 * 3) ; MONITOR ENTRY (DSKY) -MON_SERIAL .EQU MON_LOC + (1 * 3) ; MONITOR ENTRY (SERIAL PORT) +; --------------------------- ; ; INTERRUPT MODE 2 SLOT ASSIGNMENTS ; @@ -1078,8 +1105,8 @@ INT_PIO1B .EQU 12 ; ZILOG PIO 1, CHANNEL B #ENDIF -#DEFINE IVT(INTX) HB_IVT+(INTX * 4)+1 -#DEFINE VEC(INTX) INTX*2 +#DEFINE IVT(INTX) HB_IVT + (INTX * 4) + 1 +#DEFINE VEC(INTX) INTX * 2 ; ; SET DEFAULT CSIO SPEED (INTERNAL CLOCK, SLOW AS POSSIBLE) diff --git a/Source/HBIOS/sysconf.asm b/Source/HBIOS/sysconf.asm index 81369f02..eb178ac3 100644 --- a/Source/HBIOS/sysconf.asm +++ b/Source/HBIOS/sysconf.asm @@ -8,7 +8,7 @@ ; and RomWBW Operation. Write to RTC NVRAM to store config ; is reliant on HBIOS ; -; NOTE: This program is built as both a CP/M COM and Rom WBW Applicaton +; NOTE: This program is built as both a CP/M COM and Rom WBW Application ; ; ROM APPLICATION THAT IS AUTOMATICALLY INCLUDED IN THE ROMWBW ROM. ; IT IS INVOKED FROM THE BOOT LOADER USING THE 'W' OPTION. (See RomLDR) @@ -18,7 +18,16 @@ ; BASED ON USEROM.ASM ; THANKS AND CREDIT TO MARTIN R. FOR PROVIDING THIS APPLICATION! ; Also Based on The Tasty Basic Configuration -; Utilitity function were also copied from RomLdr, Assign. +; Utility function were also copied from RomLdr, Assign. +; +;----------------------------------------------------------------------- +; +; Change Log: +; 2024-11-08 [MAP] Initial v1.0 release +; 2024-12-06 [WBW] Misc Fixes Improvements after initial release +; 2025-06-30 [MAP] 1.1 Changed to be invoked in CALL RET fashion from RomLdr +; +;----------------------------------------------------------------------- ; #include "../ver.inc" #include "hbios.inc" @@ -56,8 +65,9 @@ DEL .EQU 127 ; ASCII del/rubout .ORG NVR_LOC ; #ifdef ROMWBW + ; Reuse the stack provided by Rom LDR ; PLACE STACK AT THE TOP OF AVAILABLE RAM (JUST BELOW THE HBIOS PROXY). - LD SP,HBX_LOC + ; LD SP,HBX_LOC #endif #ifdef CPM ; setup stack (save old value) @@ -75,9 +85,10 @@ exit: ; call crlf ; formatting ; #ifdef ROMWBW - LD B,BF_SYSRESET ; SYSTEM RESTART - LD C,BF_SYSRES_WARM ; WARM START - RST 08 ; CALL HBIOS (DOES NOT RETURN) + RET ; Return to Rom LDR + ; LD B,BF_SYSRESET ; SYSTEM RESTART + ; LD C,BF_SYSRES_WARM ; WARM START + ; RST 08 ; CALL HBIOS (DOES NOT RETURN) #endif #ifdef CPM ; @@ -205,7 +216,7 @@ helpandloop: ; HELP MENU JR z,printmainhelp ; if empty line, print main help call upcase ; - ; the folloiwng is just testing a single charater + ; the following is just testing a single character cp 'A' ; Auto Boot help menu JP Z,HELP_AB cp 'B' ; Boot Options help menu @@ -234,7 +245,7 @@ setvalueandloop: JR z,setvalueerror ; if empty line, print ? call upcase ; - ; the folloiwng is just testing a single charater + ; the following is just testing a single character cp 'A' ; Auto Boot help menu JP Z,SET_AB cp 'B' ; Boot Options help menu @@ -265,7 +276,7 @@ PRT_STATUS: LD BC,BC_SYSGET_SWITCH LD D,$FF ; check for existence of switches RST 08 - JR NZ,STAT_NOTFOUND ; error means switchs are not enabled + JR NZ,STAT_NOTFOUND ; error means switches are not enabled ; ; print invdividual stats, on all per switch ; @@ -499,7 +510,7 @@ err_ret: ;======================================================================= ; str_banner .db "\r\n" - .db "RomWBW System Config Utility, Version 1.0 Nov-2024\r\n",0 + .db "RomWBW System Config Utility, Version 1.1 June-2025\r\n",0 ; MSG_MENU .DB "\r\n" .DB "Commands:\r\n" @@ -507,7 +518,7 @@ MSG_MENU .DB "\r\n" .DB " (S)et {SW} {val}[,{val}[,{val}]]- Set a switch value(s)\r\n" .DB " (R)eset - Init NVRAM to Defaults\r\n" .DB " (H)elp [{SW}] - This help menu, or help on a switch\r\n" - .DB " (Q)uit - Quit\r\n" + .DB " e(X)it - Exit Configuration\r\n" .DB 0 MSG_PROMPT: .DB "\r\n" .DB "$", 0 @@ -1015,7 +1026,7 @@ CIN: PUSH BC ; stksav .dw 0 ; stack pointer saved at start ; -cmdbuf: .FILL cmdmax,0 ; cmd inut buffer +cmdbuf: .FILL cmdmax,0 ; cmd input buffer ; .fill stksiz,0 ; stack stack .equ $ ; stack top diff --git a/Source/HBIOS/tms.asm b/Source/HBIOS/tms.asm index f2c3bbc7..091509ca 100644 --- a/Source/HBIOS/tms.asm +++ b/Source/HBIOS/tms.asm @@ -48,6 +48,7 @@ TMSKBD_KBD .EQU 1 TMSKBD_PPK .EQU 2 TMSKBD_MKY .EQU 3 TMSKBD_NABU .EQU 4 +TMSKBD_USB .EQU 5 ; TMSKBD .EQU TMSKBD_NONE ; ASSUME NONE ; @@ -93,6 +94,13 @@ TMSKBD .SET TMSKBD_MKY ; MSX KEYBOARD DEVECHO "MSXMKY" #ENDIF ; +#IF (TMSMODE == TMSMODE_MSXUKY) +TMS_DATREG .EQU $98 ; READ/WRITE DATA +TMS_CMDREG .EQU $99 ; READ STATUS / WRITE REG SEL +TMSKBD .SET TMSKBD_USB ; MSX KEYBOARD + DEVECHO "MSX-USB_KYB" +#ENDIF +; #IF (TMSMODE == TMSMODE_MBC) TMS_DATREG .EQU $98 ; READ/WRITE DATA TMS_CMDREG .EQU $99 ; READ STATUS / WRITE REG SEL @@ -150,8 +158,10 @@ TMS_COLS .EQU 40 DEVECHO "X" DEVECHO TMS_ROWS ; -#DEFINE USEFONT8X8 -#DEFINE TMS_FONT FONT8X8 +;;;#DEFINE USEFONT8X8 +;;;#DEFINE TMS_FONT FONT8X8 +#DEFINE USEFONT6X8 +#DEFINE TMS_FONT FONT6X8 ; TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER ; @@ -181,6 +191,11 @@ NABUKBENABLE .SET TRUE ; INCLUDE NABU KEYBOARD SUPPORT DEVECHO "NABU" #ENDIF ; +#IF (TMSKBD == TMSKBD_USB) +USBKYBENABLE .SET TRUE ; INCLUDE USB KEYBOARD SUPPORT + DEVECHO "USB-KYB" +#ENDIF +; #IF (TMSTIMENABLE & (INTMODE > 0)) DEVECHO ", INTERRUPTS ENABLED" #ENDIF @@ -295,6 +310,7 @@ TMS_INIT1: ; CALL TMS_CRTINIT ; SETUP THE TMS CHIP REGISTERS CALL TMS_LOADFONT ; LOAD FONT DATA FROM ROM TO TMS STRORAGE + ; *** DIAGNOSE FONT LOAD ERROR HERE!!! *** CALL TMS_CLEAR ; CLEAR SCREEN, HOME CURSOR #IF (TMSKBD == TMSKBD_PPK) CALL PPK_INIT ; INITIALIZE PPI KEYBOARD DRIVER @@ -308,6 +324,9 @@ TMS_INIT1: #IF (TMSKBD == TMSKBD_NABU) CALL NABUKB_INIT ; INITIALIZE NABU KEYBOARD DRIVER #ENDIF +#IF (TMSKBD == TMSKBD_USB) + CALL CHUKB_INIT +#ENDIF #IF (TMSTIMENABLE & (INTMODE > 0)) ; @@ -391,6 +410,11 @@ TMS_FNTBL: .DW MKY_FLUSH .DW MKY_READ #ENDIF +#IF (TMSKBD == TMSKBD_USB) + .DW UKY_STAT + .DW UKY_FLUSH + .DW UKY_READ +#ENDIF #IF (TMSKBD == TMSKBD_NABU) .DW NABUKB_STAT .DW NABUKB_FLUSH @@ -771,43 +795,23 @@ TMS_LOADFONT: ; SYSTEM INITIALIZATION REQUIRES A LARGE DECOMPRESSION BUFFER THAT WE ; HAVE NO WAY TO ACCOMMODATE WITHOUT TRASHING OS/APP MEMORY. ; -#IF USELZSA2 & FALSE - LD (TMS_STACK),SP ; SAVE STACK - LD HL,(TMS_STACK) ; AND SHIFT IT - LD DE,$2000 ; DOWN 4KB TO - CCF ; CREATE A - SBC HL,DE ; DECOMPRESSION BUFFER - LD SP,HL ; HL POINTS TO BUFFER - EX DE,HL ; START OF STACK BUFFER - PUSH DE ; SAVE IT - LD HL,TMS_FONT ; START OF FONT DATA - CALL DLZSA2 ; DECOMPRESS TO DE - POP HL ; RECALL STACK BUFFER POSITION -#ELSE - LD HL,TMS_FONT ; START OF FONT DATA -#ENDIF + LD A,FONTID_6X8 ; WE WANT 6X8 + CALL FNT_SELECT ; SELECT IT + RET NZ ; ERROR RETURN ; ; FILL TMS_FNTVADDR BYTES FROM FONTDATA LD DE,TMS_FNTSIZE TMS_LOADFONT1: - LD A,(HL) + CALL FNT_NEXT ; NEXT FONT DATA BYTE EZ80_IO OUT (TMS_DATREG),A TMS_IODELAY ; DELAY - INC HL DEC DE LD A,D OR E JR NZ,TMS_LOADFONT1 -; -#IF USELZSA2 & FALSE - LD HL,(TMS_STACK) ; ERASE DECOMPRESS BUFFER - LD SP,HL ; BY RESTORING THE STACK - RET ; DONE -TMS_STACK .DW 0 -#ELSE + XOR A ; SIGNAL SUCCESS RET -#ENDIF ; ;---------------------------------------------------------------------- ; VIRTUAL CURSOR MANAGEMENT @@ -1153,7 +1157,6 @@ TMS_TSTINT: RET TMS_INTHNDL: - CALL HB_TIMINT ; RETURN NZ - HANDLED OR $FF RET diff --git a/Source/HBIOS/uart.asm b/Source/HBIOS/uart.asm index 1ff50ee5..a7362766 100644 --- a/Source/HBIOS/uart.asm +++ b/Source/HBIOS/uart.asm @@ -193,7 +193,7 @@ UART_INITUNIT: UART_INITUNIT1: ; SET DEFAULT CONFIG LD DE,-1 ; LEAVE CONFIG ALONE - JP UART_INITDEVX ; IMPLEMENT IT AND RETURN + JP UART_INITDEV ; IMPLEMENT IT AND RETURN ; ; ; @@ -500,18 +500,20 @@ UART_OST: ; ; ; -; -; NOTE THAT THERE ARE TWO ENTRY POINTS. INITDEV WILL DISABLE/ENABLE INTS -; AND INITDEVX WILL NOT. THIS IS DONE SO THAT THE PREINIT ROUTINE ABOVE -; CAN AVOID ENABLING/DISABLING INTS. -; UART_INITDEV: + ; INITDEV CAN BE CALLED PRIOR TO INTERRUPTS BEING ENABLED. WE + ; NEED TO LEAVE INTERRUPTS ALONE IN THIS SCENARIO + LD A,(INTSENAB) ; INTS ENABLED? + OR A ; TEST VALUE + JR Z,UART_INITDEV0 ; BYPASS DI/EI IF NOT ENABLED +; + ; INTERRUPTS DISABLED DURING INIT HB_DI ; DISABLE INTS - CALL UART_INITDEVX ; DO THE WORK + CALL UART_INITDEV0 ; DO THE WORK HB_EI ; INTS BACK ON RET ; DONE ; -UART_INITDEVX: +UART_INITDEV0: ; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR AND E ; ... VALUE OF -1 diff --git a/Source/HBIOS/util.asm b/Source/HBIOS/util.asm index 6d1ee813..d4e5d98c 100644 --- a/Source/HBIOS/util.asm +++ b/Source/HBIOS/util.asm @@ -54,20 +54,20 @@ PC_GT: LD A,'>' JR PC_PRTCHR -PC_LPAREN: - PUSH AF - LD A,'(' - JR PC_PRTCHR - -PC_RPAREN: - PUSH AF - LD A,')' - JR PC_PRTCHR - -PC_ASTERISK: - PUSH AF - LD A,'*' - JR PC_PRTCHR +;PC_LPAREN: +; PUSH AF +; LD A,'(' +; JR PC_PRTCHR +; +;PC_RPAREN: +; PUSH AF +; LD A,')' +; JR PC_PRTCHR +; +;PC_ASTERISK: +; PUSH AF +; LD A,'*' +; JR PC_PRTCHR PC_CR: PUSH AF @@ -383,12 +383,12 @@ PRTIDXCNT: ; ; ; -TSTPT: - PUSH DE - LD DE,STR_TSTPT - CALL WRITESTR - POP DE - JR REGDMP ; DUMP REGISTERS AND RETURN +;TSTPT: +; PUSH DE +; LD DE,STR_TSTPT +; CALL WRITESTR +; POP DE +; JR REGDMP ; DUMP REGISTERS AND RETURN ; ; ; @@ -479,7 +479,7 @@ RD_STACK .EQU $ ; ; STR_HALT .TEXT "\r\n\r\n*** System Halted ***$" -STR_TSTPT .TEXT "\r\n+++ TSTPT: $" +;STR_TSTPT .TEXT "\r\n+++ TSTPT: $" ;STR_AF .DB " AF=$" ;STR_BC .DB " BC=$" ;STR_DE .DB " DE=$" @@ -684,7 +684,7 @@ DLY16: CALL DLY8 ; 432 400 DLY8: CALL DLY4 ; 216 200 DLY4: CALL DLY2 ; 108 100 DLY2: CALL DLY1 ; 54 50 -DLY1: +DLY1: #IF (CPUFAM == CPU_EZ80) NOP NOP @@ -1107,14 +1107,14 @@ ADD32: INC DE RET ; -DEC32: - LD BC,1 -SUB32: - OR A - SBC HL,BC - RET NC - DEC DE - RET +;DEC32: +; LD BC,1 +;SUB32: +; OR A +; SBC HL,BC +; RET NC +; DEC DE +; RET ; ; INC32 (HL) ; INCREMENT 32 BIT BINARY AT ADDRESS diff --git a/Source/HBIOS/vga.asm b/Source/HBIOS/vga.asm index 97470ff5..df4a8d96 100644 --- a/Source/HBIOS/vga.asm +++ b/Source/HBIOS/vga.asm @@ -51,6 +51,7 @@ VGA_SCANL .EQU 16 VGA_89BIT .EQU VGA_8BIT #DEFINE USEFONT8X16 #DEFINE VGA_FONT FONT8X16 +VGA_FONTID .EQU FONTID_8X16 #ENDIF #IF (VGASIZ=V80X30) VGA_ROWS .EQU 30 @@ -59,6 +60,7 @@ VGA_SCANL .EQU 16 VGA_89BIT .EQU VGA_8BIT #DEFINE USEFONT8X16 #DEFINE VGA_FONT FONT8X16 +VGA_FONTID .EQU FONTID_8X16 #ENDIF #IF (VGASIZ=V80X43) VGA_ROWS .EQU 43 @@ -67,6 +69,7 @@ VGA_SCANL .EQU 11 VGA_89BIT .EQU VGA_8BIT #DEFINE USEFONT8X11 #DEFINE VGA_FONT FONT8X11 +VGA_FONTID .EQU FONTID_8X11 #ENDIF #IF (VGASIZ=V80X60) VGA_ROWS .EQU 60 @@ -75,6 +78,7 @@ VGA_SCANL .EQU 8 VGA_89BIT .EQU VGA_8BIT #DEFINE USEFONT8X8 #DEFINE VGA_FONT FONT8X8 +VGA_FONTID .EQU FONTID_8X8 #ENDIF ; #IF VGA_CSTY=VGA_BLOK @@ -138,6 +142,7 @@ VGA_INIT1: ; HARDWARE INITIALIZATION CALL VGA_CRTINIT ; SETUP THE VGA CHIP REGISTERS CALL VGA_LOADFONT ; LOAD FONT DATA FROM ROM TO VGA STORAGE + ; *** DIAGNOSE FONT LOAD ERROR HERE!!! *** CALL VGA_VDAINI CALL KBD_INIT ; INITIALIZE KEYBOARD DRIVER @@ -550,52 +555,32 @@ VGA_CRTCDUMP1: VGA_LOADFONT: LD HL,$7000 | VGA_89BIT ; CLEAR FONT PAGE NUM CALL VGA_SETCFG - -#IF USELZSA2 & (VGASIZ != V80X60) - LD (VGA_STACK),SP ; SAVE STACK - LD HL,(VGA_STACK) ; AND SHIFT IT - LD DE,$2000 ; DOWN 4KB TO - OR A ; CREATE A - SBC HL,DE ; DECOMPRESSION BUFFER - LD SP,HL ; HL POINTS TO BUFFER - EX DE,HL ; START OF STACK BUFFER - PUSH DE ; SAVE IT - LD HL,VGA_FONT ; START OF FONT DATA - CALL DLZSA2 ; DECOMPRESS TO DE - POP HL ; RECALL STACK BUFFER POSITION -#ELSE - LD HL,VGA_FONT ; START OF FONT DATA -#ENDIF - +; + LD A,VGA_FONTID ; DESIRED FONT + CALL FNT_SELECT ; SELECT IT + RET NZ ; ERROR RETURN +; LD DE,$7000 ; PAGE 7 OF VIDEO RAM VGA_LOADFONT1: LD B,VGA_SCANL ; # BYTES FOR EACH CHAR VGA_LOADFONT2: - LD A,(HL) ; GET NEXT BYTE + CALL FNT_NEXT ; GET NEXT BYTE CALL VGA_MEMWR ; MEM(DE) := A - INC HL ; NEXT FONT BYTE INC DE ; NEXT MEM BYTE DJNZ VGA_LOADFONT2 - +; LD BC,16-VGA_SCANL ; MOVE TO NEXT EX DE,HL ; 16 BYTE ADD HL,BC ; CHARACTER EX DE,HL - +; LD A,D CP $80 ; CHECK FOR END JR NZ,VGA_LOADFONT1 ; LOOP LD HL,$7070 | VGA_89BIT ; SET FONT PAGE NUM TO 7 CALL VGA_SETCFG - -#IF USELZSA2 & (VGASIZ != V80X60) - LD HL,(VGA_STACK) ; ERASE DECOMPRESS BUFFER - LD SP,HL ; BY RESTORING THE STACK - RET ; DONE -VGA_STACK .DW 0 -#ELSE + XOR A RET -#ENDIF ; ;---------------------------------------------------------------------- ; SET CURSOR POSITION TO ROW IN D AND COLUMN IN E diff --git a/Source/HBIOS/vrc.asm b/Source/HBIOS/vrc.asm index 22338298..740dba3d 100644 --- a/Source/HBIOS/vrc.asm +++ b/Source/HBIOS/vrc.asm @@ -21,8 +21,13 @@ VRC_KBDST .EQU $F5 ; KBD CTLR STATUS/CMD PORT VRC_ROWS .EQU 48 VRC_COLS .EQU 64 ; -#DEFINE USEFONTVGARC -#DEFINE VRC_FONT FONTVGARC +#DEFINE USEFONT8X8 +#DEFINE VRC_FONT FONT8X8 +VRC_FONTID .EQU FONTID_8X8 +; +;;;#DEFINE USEFONT6X8 +;;;#DEFINE VRC_FONT FONT6X8 +;;;VRC_FONTID .EQU FONTID_6X8 ; TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER KBDENABLE .SET TRUE ; INCLUDE KBD KEYBOARD SUPPORT @@ -70,6 +75,7 @@ VRC_INIT1: ; HARDWARE INITIALIZATION CALL VRC_CRTINIT ; SETUP THE VGARC CHIP REGISTERS CALL VRC_LOADFONT ; LOAD FONT DATA FROM ROM TO VGARC STORAGE + ; *** DIAGNOSE FONT LOAD ERROR HERE!!! *** CALL VRC_VDAINI ; RESET CALL KBD_INIT ; INITIALIZE KEYBOARD DRIVER @@ -273,67 +279,22 @@ VRC_CRTINIT: ;---------------------------------------------------------------------- ; VRC_LOADFONT: + LD A,VRC_FONTID ; DESIRED FONT ID + CALL FNT_SELECT ; SELECT IT + RET NZ ; ERROR RETURN ; -#IF USELZSA2 - LD (VRC_STACK),SP ; SAVE STACK - LD HL,(VRC_STACK) ; AND SHIFT IT - LD DE,$2000 ; DOWN 4KB TO - OR A ; CREATE A - SBC HL,DE ; DECOMPRESSION BUFFER - LD SP,HL ; HL POINTS TO BUFFER - EX DE,HL ; START OF STACK BUFFER - PUSH DE ; SAVE IT - LD HL,VRC_FONT ; START OF FONT DATA - CALL DLZSA2 ; DECOMPRESS TO DE - POP HL ; RECALL STACK BUFFER POSITION -#ELSE - LD HL,VRC_FONT ; START OF FONT DATA -#ENDIF -; -#IF 0 - ; THIS APPROACH TO LOADING FONTS IS BEST (FASTEST), BUT IS - ; CAUSING ARTIFACTS ON THE DISPLAYED FONTS WHEN RUN ON A - ; Z280. IT IS NOT CLEAR WHAT THE PROBLEM IS (POSSIBLY - ; Z280 BUG), BUT FOR NOW WE AVOID THIS AND USE AN - ; ALTERNATIVE APPROACH BELOW. - LD DE,0+(128*8)-1 ; LENGTH OF FONT DATA - 1 - ADD HL,DE ; ADD TO HL - LD BC,VRC_FONTBASE+3 ; WORK BACKWARDS - OTDR ; DO 4 PAGES - DEC C - OTDR - DEC C - OTDR - DEC C - OTDR - DEC C -#ENDIF -; -#IF 1 - ; ALTERNATIVE APPROACH TO LOADING FONTS. THIS ONE AVOIDS - ; THE USE OF OTDR WHICH SEEMS TO CAUSE PROBLEMS ON Z280. LD B,0 LD C,VRC_FONTBASE VRC_LOADFONT1: - LD A,(HL) + CALL FNT_NEXT OUT (C),A - INC HL INC B JR NZ,VRC_LOADFONT1 INC C LD A,C CP VRC_FONTBASE + 4 JR NZ,VRC_LOADFONT1 -#ENDIF -; -#IF USELZSA2 - LD HL,(VRC_STACK) ; ERASE DECOMPRESS BUFFER - LD SP,HL ; BY RESTORING THE STACK - RET ; DONE -VRC_STACK .DW 0 -#ELSE RET -#ENDIF ; ;---------------------------------------------------------------------- ; SET CURSOR POSITION TO ROW IN D AND COLUMN IN E diff --git a/Source/HBIOS/xosera.asm b/Source/HBIOS/xosera.asm new file mode 100644 index 00000000..13060f71 --- /dev/null +++ b/Source/HBIOS/xosera.asm @@ -0,0 +1,1050 @@ +;====================================================================== +; XOSERA DRIVER FOR RCBUS XOSERA CARD +; +; WRITTEN BY: ROB GOWIN -- 01/19/2025 +;====================================================================== +; +; TODO: +; * LOOK AT FONT STUFF IN MORE DETAIL +; +;====================================================================== +; XOSERA DRIVER - CONSTANTS +;====================================================================== +; +;XOS_BASE .EQU $E0 +; + DEVECHO "XOSERA: " + DEVECHO "IO=" + DEVECHO XOS_BASE + DEVECHO "\n" +; +#IF (XOSSIZ=V80X30) +XOS_ROWS_CONST .EQU 30 +XOS_COLS_CONST .EQU 80 +#ENDIF +#IF (XOSSIZ=V80X60) +XOS_ROWS_CONST .EQU 60 +XOS_COLS_CONST .EQU 80 +#ENDIF + +; XOSERA MAIN REGISTER + +ZXM_SYS_CTRL .EQU XOS_BASE +ZXM_INT_CTRL .EQU XOS_BASE+2 +ZXM_TIMER .EQU XOS_BASE+4 +ZXM_RD_XADDR .EQU XOS_BASE+6 +ZXM_WR_XADDR .EQU XOS_BASE+8 +ZXM_XDATA .EQU XOS_BASE+10 +ZXM_RD_INCR .EQU XOS_BASE+12 +ZXM_RD_ADDR .EQU XOS_BASE+14 +ZXM_WR_INCR .EQU XOS_BASE+16 +ZXM_WR_ADDR .EQU XOS_BASE+18 +ZXM_DATA .EQU XOS_BASE+20 +ZXM_DATA_2 .EQU XOS_BASE+22 +ZXM_PIXEL_X .EQU XOS_BASE+24 +ZXM_PIXEL_Y .EQU XOS_BASE+26 +ZXM_UART .EQU XOS_BASE+28 +ZXM_FEATURE .EQU XOS_BASE+30 + +; See: https:;github.com/XarkLabs/Xosera/blob/master/REFERENCE.md + +; Xosera XR Memory Regions (size in 16-bit words) +XR_CONFIG_REGS .EQU $0000 ; (R/W) 0x0000-0x0007 8 config/ctrl registers +XR_PA_REGS .EQU $0010 ; (R/W) 0x0010-0x0017 8 playfield A video registers +XR_PB_REGS .EQU $0018 ; (R/W) 0x0018-0x001F 8 playfield B video registers +XR_AUDIO_REGS .EQU $0020 ; (-/W) 0x0020-0x002F 16 audio playback registers +XR_BLIT_REGS .EQU $0040 ; (-/W) 0x0040-0x0049 10 blitter registers +XR_TILE_ADDR .EQU $4000 ; (R/W) 0x4000-0x53FF tile glyph/tile map memory +XR_TILE_SIZE .EQU $1400 ; 4096+1024 x 16-bit tile glyph/tile map memory +XR_COLOR_ADDR .EQU $8000 ; (R/W) 0x8000-0x81FF 2 x A & B color lookup memory +XR_COLOR_SIZE .EQU $0200 ; 2 x 256 x 16-bit words (0xARGB) +XR_COLOR_A_ADDR .EQU $8000 ; (R/W) 0x8000-0x80FF A 256 entry color lookup memory +XR_COLOR_A_SIZE .EQU $0100 ; 256 x 16-bit words (0xARGB) +XR_COLOR_B_ADDR .EQU $8100 ; (R/W) 0x8100-0x81FF B 256 entry color lookup memory +XR_COLOR_B_SIZE .EQU $0100 ; 256 x 16-bit words (0xARGB) +XR_POINTER_ADDR .EQU $8200 ; (-/W) 0x8200-0x82FF 256 word 32x32 4-bpp pointer image +XR_POINTER_SIZE .EQU $0100 ; 256 x 16-bit words (4-bit pixels) +XR_COPPER_ADDR .EQU $C000 ; (R/W) 0xC000-0xC5FF copper memory (16-bit words) +XR_COPPER_SIZE .EQU $0600 ; 1024+512 x 16-bit copper memory words + +; XR Extended Register / Region (accessed via XM_RD_XADDR/XM_WR_XADDR and XM_XDATA) +; Video Config and Copper XR Registers +XR_VID_CTRL .EQU $00 ; (R /W) display control and border color index +XR_COPP_CTRL .EQU $01 ; (R /W) display synchronized coprocessor control +XR_AUD_CTRL .EQU $02 ; (- /-) TODO: audio channel control +XR_SCANLINE .EQU $03 ; (R /W) read scanline (incl. offscreen), write signal video interrupt +XR_VID_LEFT .EQU $04 ; (R /W) left edge of active display window (typically 0) +XR_VID_RIGHT .EQU $05 ; (R /W) right edge of active display window +1 (typically 640 or 848) +XR_POINTER_H .EQU $06 ; (- /W) pointer sprite raw H position +XR_POINTER_V .EQU $07 ; (- /W) pointer sprite raw V position / pointer color select +; Playfield A Control XR Registers +XR_PA_GFX_CTRL .EQU $10 ; (R /W ) playfield A graphics control +XR_PA_TILE_CTRL .EQU $11 ; (R /W ) playfield A tile control +XR_PA_DISP_ADDR .EQU $12 ; (R /W ) playfield A display VRAM start address +XR_PA_LINE_LEN .EQU $13 ; (R /W ) playfield A display line width in words +XR_PA_HV_FSCALE .EQU $14 ; (R /W ) playfield A horizontal and vertical fractional scale +XR_PA_H_SCROLL .EQU $15 ; (R /W ) playfield A horizontal and vertical fine scroll +XR_PA_V_SCROLL .EQU $16 ; (R /W ) playfield A horizontal and vertical fine scroll +XR_PA_LINE_ADDR .EQU $17 ; (- /W ) playfield A scanline start address (loaded at start of line) +; Playfield B Control XR Registers +XR_PB_GFX_CTRL .EQU $18 ; (R /W ) playfield B graphics control +XR_PB_TILE_CTRL .EQU $19 ; (R /W ) playfield B tile control +XR_PB_DISP_ADDR .EQU $1A ; (R /W ) playfield B display VRAM start address +XR_PB_LINE_LEN .EQU $1B ; (R /W ) playfield B display line width in words +XR_PB_HV_FSCALE .EQU $1C ; (R /W ) playfield B horizontal and vertical fractional scale +XR_PB_H_SCROLL .EQU $1D ; (R /W ) playfield B horizontal and vertical fine scroll +XR_PB_V_SCROLL .EQU $1E ; (R /W ) playfield B horizontal and vertical fine scroll +XR_PB_LINE_ADDR .EQU $1F ; (- /W ) playfield B scanline start address (loaded at start of line) + +; Default 1-bpp font glyphs in TILE memory (total 0x1400 words) +FONT_ST_8x16_ADDR .EQU XR_TILE_ADDR + $0000 +FONT_ST_8x16_SIZE .EQU $800 +FONT_ST_8x8_ADDR .EQU XR_TILE_ADDR + $0800 +FONT_ST_8x8_SIZE .EQU $400 +FONT_PC_8x8_ADDR .EQU XR_TILE_ADDR + $0C00 +FONT_PC_8x8_SIZE .EQU $400 +FONT_HEX_8x8_ADDR .EQU XR_TILE_ADDR + $1000 +FONT_HEX_8x8_SIZE .EQU $400 + +TILE_CTRL_TILE_VRAM_F .EQU $0100 +TILE_CTRL_DISP_TILEMEM_F .EQU $0200 + +; GET XOSERA MAIN REGISTER REG_NUM VALUE INTO DE. +#DEFINE XM_GETW(REG_NUM) \ +#defcont \ LD C,REG_NUM +#defcont \ IN D,(C) +#defcont \ INC C +#defcont \ IN E,(C) + +; SET XOSERA MAIN REGISTER REG_NUM TO VALUE IN DE. +#DEFINE XM_SETW(REG_NUM) \ +#defcont \ LD C,REG_NUM +#defcont \ OUT (C),D +#defcont \ INC C +#defcont \ OUT (C),E + +; SET LOW BYTE OF XOERA MAIN REGISTER REG_NUM TO VALUE IN A. +#DEFINE XM_SETBL(REG_NUM) \ +#defcont \ LD C,REG_NUM+1 +#defcont \ OUT (C),A + +SYNC_RETRIES .EQU 250 + +TERMENABLE .SET TRUE ; INCLUDE TERMINAL PSEUDODEVICE DRIVER + +;====================================================================== +; XOSERA DRIVER - INITIALIZATION +;====================================================================== +; +XOS_PREINIT: + LD IY,XOS_IDAT ; POINTER TO INSTANCE DATA +; JP KBD_PREINIT ; INITIALIZE KEYBOARD + RET +; +XOS_INIT: + LD IY,XOS_IDAT ; POINTER TO INSTANCE DATA +; + CALL NEWLINE ; FORMATTING + PRTS("XOSERA: IO=0x$") + LD A,XOS_BASE + CALL PRTHEXBYTE + CALL XOS_PROBE ; CHECK FOR HW PRESENCE + JR Z,XOS_INIT1 ; CONTINUE IF HW PRESENT +; + ; HARDWARE NOT PRESENT + PRTS(" NOT PRESENT$") + OR $FF + RET +; +XOS_INIT1: + ; RETRIEVE SOME CONFIGURATION INFO FROM XOSERA AND PRINT IT + LD A,' ' + CALL COUT + CALL XOS_SHOW_INFO + + CALL XOS_VDAINI + + ; ADD OURSELVES TO VDA DISPATCH TABLE + LD BC,XOS_FNTBL ; BC := FUNCTION TABLE ADDRESS + LD DE,XOS_IDAT ; DE := XOSERA INSTANCE DATA PTR + CALL VDA_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED + + ; INITIALIZE EMULATION + LD C,A ; C := ASSIGNED VIDEO DEVICE NUM + LD DE,XOS_FNTBL ; DE := FUNCTION TABLE ADDRESS + LD HL,XOS_IDAT ; HL := XOSERA INSTANCE DATA PTR + CALL TERM_ATTACH ; DO IT + + XOR A ; SIGNAL SUCCESS + RET + +;---------------------------------------------------------------------- +; XOS_SHOW_INFO: +; XOSERA HAS SOME BUILD-TIME INFO STORED IN THE UPPER 128 OF COPPER +; MEMORY. RETRIEVE THAT INFO AND DISPLAY IT. +;---------------------------------------------------------------------- + +XOS_SHOW_INFO: + LD DE,$C580 ; LAST 128 BYTES OF XOSERA COPPER MEM + XM_SETW(ZXM_RD_XADDR) +XOS_SHOW_INFO1: + XM_GETW(ZXM_XDATA) ; GET INFO DATA IN DE + LD A,D + CP 0 + JR Z,XOS_SHOW_INFO2 ; EXIT LOOP IF D == 0 + PUSH DE + CALL COUT ; PRINT THE CHAR IN D (COPIED TO A) + POP DE + LD A,E + CP 0 + JR Z,XOS_SHOW_INFO2 ; EXIT LOOP IF E == 0 + CALL COUT ; PRINT THE CHAR IN E (COPIED TO A) + JR XOS_SHOW_INFO1 +XOS_SHOW_INFO2: + RET + +;---------------------------------------------------------------------- +; XOS_DETECT: DETECT PRESENCE OF A XOSERA BOARD +; +; READ XOSERA RD_INCR REGISTER, THEN XOR WITH CONSTANT TO CHANGE IT. +; WRITE XOR'D VALUE TO RD_INCR, THEN READ BACK. IF A MATCH, +; XOSERA BOARD IS DETECTED. +; EITHER WAY, RESTORE ORIGINAL RD_INCR THEN RETURN RESULT IN A. +; RESULT IN A: 0 IF VALUES MATCH, -8 (HARDWARE NOT PRESENT) OTHERWISE. +;---------------------------------------------------------------------- + +XOS_DETECT: + XM_GETW(ZXM_RD_INCR) ; DE := XOSERA RD_INCR REGISTER + PUSH DE ; SAVE A COPY + LD A,D + XOR $F5 + LD D,A ; XOR RD_INCR MSB WITH $F5 + LD A,E + XOR $FA + LD E,A ; XOR RD_INCR LSB WITH $FA + ; DE = TEST_INCR = RD_INCR ^ 0xF5FA; + LD H,D + LD L,E ; SAVE TEST_INCR TO HL + XM_SETW(ZXM_RD_INCR) ; WRITE NEW RD_INCR VALUE + LD DE,$0000 + XM_GETW(ZXM_RD_INCR) ; READ IT BACK INTO DE + LD A,H + CP D + JR NZ,XOS_DETECT1 ; D & H THE SAME? + LD A,L + CP E + JR NZ,XOS_DETECT1 ; E & L THE SAME? + XOR A ; YEP, LOOKS GOOD + JP XOS_DETECT2 +XOS_DETECT1: + LD A,-8 ; READBACK VALUE DID NOT MATCH. SIGNAL HARDWARE NOT PRESENT +XOS_DETECT2: + ; RESTORE THE ORGINAL VALUE OF RD_INCR + POP DE + XM_SETW(ZXM_RD_INCR) + OR A ; SET FLAGS + RET +; +;---------------------------------------------------------------------- +; XOS_PROBE: PROBE FOR XOSERA, TRY UP TO `SYNC_RETRIES` TIMES, WAITING +; 10MS BETWEEN SYNC ATTEMPTS. +; RETURN IN A: 0 IF A XOSERA_BOARD IS DETECTED, OR -8 (HARDWARE NOT +; DETECTED) OTHERWISE. +;---------------------------------------------------------------------- +; +XOS_PROBE: + LD B,SYNC_RETRIES +XOS_PROBE1: + CALL XOS_DETECT ; Z FLAG SET IF XOSERA DETECTED, CLEAR IF NOT + JR Z,XOS_PROBE2 + ; OUR ATTEMPT TO SYNC DID NOT WORK, SO WAIT 10MS TO TRY AGAIN + PUSH BC + LD DE,625 ; 625 * 16US = 10000US = 10MS + CALL VDELAY + POP BC + DJNZ XOS_PROBE1 + LD A,-8 ; FAILED TO SYNC AFTER SEVERAL ATTEMPTS. +XOS_PROBE2: + ; A WILL BE ZERO OR -8. SET THE Z FLAG ACCORDINGLY. + OR A ; SET FLAGS + RET +; +;---------------------------------------------------------------------- +; XOS_CLR_TEXT_SCR: CALL FILL TO CLEAR ENTIRE ROWS*COLS TEXT SCREEN. +;---------------------------------------------------------------------- +XOS_CLR_TXT_SCR: + LD A,(XOS_COLS) ; COMPUTE HOW MANY WORDS TO FILL + LD H,A + LD A,(XOS_ROWS) + LD E,A + CALL MULT8 + LD B,H + LD C,L ; BC := WORD COUNT = ROWS * COLS + LD HL,(XOS_POS) + PUSH HL ; SAVE CURRENT CURSOR POS + LD HL,(XOS_OFF) + LD (XOS_POS),HL ; TELL FILL TO START AT 0,0 (POS = XOS_OFF) + LD A,$20 ; FILL WITH SPACE (AND CURRENT ATTR) + CALL XOS_FILL + CALL REVERSE_CURSOR_POS ; BIT OF A HACK + POP HL + LD HL,(XOS_POS) ; RESTORE ORIGINAL CURSOR POS + RET +; +;---------------------------------------------------------------------- +; XOS_WRITE_XREGS: WRITE A GROUP OF XOSERA EXTENDED REGISTERS. +; HL POINTS TO SETUP TABLE, B HAS NUMBER OF WORDS. +; DE HAS FIRST XOSERA XREG ADDRESS +;---------------------------------------------------------------------- +; +XOS_WRITE_XREGS: + XM_SETW(ZXM_WR_XADDR) +XOS_WRITE_XREGS1: + LD E,(HL) + INC HL + LD D,(HL) + INC HL + XM_SETW(ZXM_XDATA) + DEC B + JR NZ,XOS_WRITE_XREGS1 + RET +; +;---------------------------------------------------------------------- +; XOS_WRITE_PALETTE_B +; WHEN WRITING PALETTE B, WE NEED TO SET THE ALPHA VALUE TO $F +; SO THAT THE GRAPHICS/TEXT OVERLAP WORKS CORRECTLY. EXCEPT THAT +; WE DON'T WANT THIS FOR THE ZERO ENTRY SO HANDLE THAT SEPERATELY. +;---------------------------------------------------------------------- +; +XOS_WRITE_PALETTE_B: + XM_SETW(ZXM_WR_XADDR) + LD E,(HL) + INC HL + LD D,(HL) + INC HL + XM_SETW(ZXM_XDATA) + DEC B +XOS_WRITE_PALETTE_B1: + LD E,(HL) + INC HL + LD D,(HL) + INC HL + LD A,D + OR $F0 ; SET ALPHA VALUE TO $F + LD D,A + XM_SETW(ZXM_XDATA) + DEC B + JR NZ,XOS_WRITE_PALETTE_B1 + RET +; +;---------------------------------------------------------------------- +; XOS_COPY_FONT_TO_VRAM +; COPY THE 8 X 8 ST FONT IN THE EXTENDED REGISTER AREA TO THE +; UPPER 1K OF VRAM. USED IN 80 X 60 MODE, BUT NOT IN +; 80 X 30 MODE. +;---------------------------------------------------------------------- +; +XOS_COPY_FONT_TO_VRAM: + ; SEE IF THE FONT HAS ALREADY BEEN COPIED. IF SO VRAM ADDRESS + ; $FC04 WILL HAVE THE VALUE $183C. + LD DE,$FC04 + XM_SETW(ZXM_RD_ADDR) + XM_GETW(ZXM_DATA) + LD A,D + CP $18 + JR NZ,XOS_COPY_FONT_TO_VRAM1 + LD A,E + CP $3C + JR NZ,XOS_COPY_FONT_TO_VRAM1 + ; FONT HAS ALREADY BEEN COPIED TO VRAM. JUST RETURN + RET +XOS_COPY_FONT_TO_VRAM1: + LD DE,FONT_ST_8x8_ADDR ; READ FROM FONT AREA + XM_SETW(ZXM_RD_XADDR) + LD DE,$FC00 + XM_SETW(ZXM_WR_ADDR) ; WRITE TO VRAM + LD DE,$0001 + XM_SETW(ZXM_WR_INCR) ; MAKE SURE WR INCR IS NONE + LD BC,FONT_ST_8x8_SIZE ; LOOP COUNTER +XOS_COPY_FONT_TO_VRAM2: + PUSH BC + XM_GETW(ZXM_XDATA) + XM_SETW(ZXM_DATA) + ; CHECK COUNT + POP BC + DEC BC ; DECREMENT COUNT + LD A,B ; TEST FOR + OR C ; ... ZERO + RET Z ; DONE IF SO + JR XOS_COPY_FONT_TO_VRAM2 + +XOS_HW_SETUP: + LD DE,XR_VID_CTRL + LD HL,XOS_BASE_INIT + LD B,8 + CALL XOS_WRITE_XREGS + + ; INITIALIZE PLAYFIELD A FOR BITMAP GRAPHICS + LD DE,XR_PA_REGS + LD HL,PF_640x480x4 + LD B,7 + CALL XOS_WRITE_XREGS + + ; INITIALIZE PLAYFIELD B FOR 80x30 TEXT MODE + LD DE,XR_PB_REGS +#IF (XOSSIZ=V80X60) + LD HL,PF_80X60_TILED +#ELSE + LD HL,PF_80X30_TILED +#ENDIF + LD B,7 + CALL XOS_WRITE_XREGS + + ; INITIALIZE THE PALETTE FOR PLAYFIELD A + LD DE,XR_COLOR_A_ADDR + LD HL,XOS_PALETTE + LD B,16 + CALL XOS_WRITE_XREGS + + ; INITIALIZE THE PALETTE FOR PLAYFIELD B + LD DE,XR_COLOR_B_ADDR + LD HL,XOS_PALETTE + LD B,16 + CALL XOS_WRITE_PALETTE_B + + ; INITIALIZE THE COPPER PROGRAM WE ARE USING TO 'LETTERBOX' + ; A 640 X 400 BITMAP ON A 640 X 480 DISPLAY. SEE COPPER NOTES + ; WAY BELOW. + + LD DE,$C100 + XM_SETW(ZXM_WR_XADDR) + LD DE,(PF_640x480x4) ; DE := PA_GFX_CTRL + XM_SETW(ZXM_XDATA) + LD A,E + OR $80 + LD E,A ; DE := PA_GFX_CTRL WITH BLANK BIT SET + XM_SETW(ZXM_XDATA) + + LD DE,XR_COPPER_ADDR + LD HL,XOS_COPPER + LD B,19 + CALL XOS_WRITE_XREGS + + LD DE,XR_COPP_CTRL ; ENABLE THE COPPER + XM_SETW(ZXM_WR_XADDR) + LD DE,$8000 + XM_SETW(ZXM_XDATA) + + LD A,$0F ; SET DEFAUL PIXEL MASK + XM_SETBL(ZXM_SYS_CTRL) + LD DE,$0001 + XM_SETW(ZXM_WR_INCR) ; SET DEFAULT READ/WRITE INCREMENTS + XM_SETW(ZXM_RD_INCR) + RET +; +;====================================================================== +; XOSERA DRIVER - VIDEO DISPLAY ADAPTER (VDA) FUNCTIONS +;====================================================================== +; +XOS_FNTBL: + .DW XOS_VDAINI + .DW XOS_VDAQRY + .DW XOS_VDARES + .DW XOS_VDADEV + .DW XOS_VDASCS + .DW XOS_VDASCP + .DW XOS_VDASAT + .DW XOS_VDASCO + .DW XOS_VDAWRC + .DW XOS_VDAFIL + .DW XOS_VDACPY + .DW XOS_VDASCR + .DW XKBD_STAT + .DW XKBD_FLUSH + .DW XKBD_READ + .DW XOS_VDARDC +#IF (($ - XOS_FNTBL) != (VDA_FNCNT * 2)) + .ECHO "*** INVALID VGA FUNCTION TABLE ***\n" + !!!!! +#ENDIF + +XOS_VDAINI: + LD A,$0F ; BRIGHT WHITE FG, BLACK BG + LD (XOS_ATTR),A + LD A,0 + LD (XOS_RUB),A + LD A,80 + LD (XOS_COLS),A + LD A,XOS_ROWS_CONST + LD (XOS_ROWS),A +#IF (XOSSIZ=V80X60) + LD HL,$4000 +#ELSE + LD HL,$4800 +#ENDIF + LD (XOS_OFF),HL + LD (XOS_POS),HL + ; FONT DATA FOR 80x30 MODE WILL STAY IN TILE MEM, BUT + ; FONT DATA FOR 80X60 MODE WILL LIVE IN VRAM. SO WE + ; NEED TO COPY THE ST 8X8 FONT TO VRAM. WE MUST DO THIS + ; BEFORE CLEARING THE TEXT SCREEN BECAUSE THE SCREEN + ; DATA IS STORED WHERE FONT CURRENTLY RESIDES. + LD A,$0F + XM_SETBL(ZXM_SYS_CTRL) ; SET VRAM WRITE MASK + CALL XOS_COPY_FONT_TO_VRAM + CALL XOS_CLR_TXT_SCR ; CLEAR THE TEXT SCREEN + CALL XOS_HW_SETUP +; CALL XOS_CLR_GRAPHICS_SCR ; CLEAR THE GRAPHICS SCREEN + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDAQRY: + LD C,$00 ; MODE ZERO IS ALL WE KNOW + LD A,(XOS_ROWS) + LD D,A + LD A,(XOS_COLS) + LD E,A + LD HL,$0 ; EXTRACTION OF CURRENT BITMAP DATA NOT SUPPORTED YET + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDARES: + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDADEV: + LD C,0 ; C := ATTRIBUTES (UNDEFINED) + LD D,VDADEV_XOSERA ; D := DEVICE TYPE + LD E,0 ; E := PHYSICAL UNIT IS ALWAYS ZERO + LD H,0 ; H := 0, DRIVER HAS NO MODES + LD L,XOS_BASE ; L := BASE I/O ADDRESS + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDASCS: + SYSCHKERR(ERR_NOTIMPL) ; NOT IMPLEMENTED (YET) + RET + +XOS_VDASCP: + ; UNREVERSE THE CURRENT CURSOR + CALL REVERSE_CURSOR_POS + CALL XOS_XY ; SET CURSOR POSITION + ; REVERSE VIDEO THE CHARACTER AT THE NEW CURSOR POSITION + CALL REVERSE_CURSOR_POS + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDASAT: + ; INCOMING IS: -----RUB (R=REVERSE, U=UNDERLINE, B=BLINK) + ; + ; JUST SAVE THE VALUE AND FALL THROUGH. ONLY REVERSE IS + ; SUPPORTED WHICH IS IMPLEMENTED BELOW. + LD A,E + LD (XOS_RUB),A ; SAVE IT + JR XOS_VDASCO1 ; IMPLEMENT SETTING + +XOS_VDASCO: + ; WE HANDLE ONLY PER-CHARACTER COLORS (D=0) + LD A,D ; GET CHAR/SCREEN SCOPE + OR A ; CHARACTER? + JR NZ,XOS_VDASCO2 ; IF NOT, JUST RETURN + LD A,E + LD (XOS_ATTR),A ; SAVE COLOR INFO +XOS_VDASCO1: + ; CHECK FOR REVERSE VIDEO + LD A,(XOS_RUB) ; GET RUB SETTING + BIT 2,A ; REVERSE IS BIT 2 + JR Z,XOS_VDASCO2 ; DONE IF REVERSE VID NOT SET + ; IMPLEMENT REVERSE VIDEO + LD A,(XOS_ATTR) ; GET ATTRIBUTE + RLCA ; SWAP FG/BG COLORS + RLCA + RLCA + RLCA + LD (XOS_ATTR),A ; SAVE NEW VALUE +XOS_VDASCO2: + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDAWRC: + CALL REVERSE_CURSOR_POS + LD A,E ; CHARACTER TO WRITE GOES IN A + CALL XOS_PUTCHAR ; PUT IT ON THE SCREEN + CALL REVERSE_CURSOR_POS + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDAFIL: + CALL REVERSE_CURSOR_POS + LD A,E ; FILL CHARACTER GOES IN A + LD B,H + LD C,L ; FILL LENGTH GOES IN BC + CALL XOS_FILL ; DO THE FILL + CALL REVERSE_CURSOR_POS + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDACPY: + ; LENGTH IN HL, SOURCE ROW/COL IN DE, DEST IS XOS_POS + ; BLKCPY USES: HL=SOURCE, DE=DEST, BC=COUNT + CALL REVERSE_CURSOR_POS + PUSH HL ; SAVE LENGTH + CALL XOS_XY2IDX ; ROW/COL IN DE -> SOURCE ADR IN HL + PUSH DE + LD DE,(XOS_OFF) ; ADD IN VRAM START OFFSET + ADD HL,DE + POP DE + POP BC ; RECOVER LENGTH IN BC + LD DE,(XOS_POS) ; PUT DEST IN DE +; LD A,0 ; SOURCE IS MEMORY + CALL XOS_BLKCPY ; DO A BLOCK COPY + CALL REVERSE_CURSOR_POS + XOR A ; SIGNAL SUCCESS + RET + +XOS_VDASCR: + CALL REVERSE_CURSOR_POS + LD A,E + OR A ; SET FLAGS + RET Z ; IF ZERO, WE ARE DONE + JP M,XOS_VDASCR1 ; E IS NEGATIVE, REVERSE SCROLL + CALL XOS_RSCROLL ; SCROLL FORWARD 'E' LINES + CALL REVERSE_CURSOR_POS + XOR A ; SIGNAL SUCCESS + RET +XOS_VDASCR1: + NEG ; A IS NEGATIVE, BUT NEED IT POSITIVE + LD E,A ; LINES TO SCROLL TO E + CALL XOS_SCROLL ; SCROLL REVERSE 'E' LINES + CALL REVERSE_CURSOR_POS + XOR A ; SIGNAL SUCCESS + RET + +XKBD_STAT: +XKBD_FLUSH: +XKBD_READ: + OR $FF ; RETURN FAILURE STATUS + RET + +XOS_VDARDC: + XOR A + RET + +; +;====================================================================== +; XOSERA DRIVER - PRIVATE DRIVER FUNCTIONS +;====================================================================== +; +;---------------------------------------------------------------------- +; SET CURSOR POSITION TO ROW IN D AND COLUMN IN E +;---------------------------------------------------------------------- +; +XOS_XY: + CALL XOS_XY2IDX ; CONVERT ROW/COL TO BUF IDX + LD DE,(XOS_OFF) + ADD HL,DE + LD (XOS_POS),HL ; SAVE THE RESULT (DISPLAY POSITION) + RET +; +;---------------------------------------------------------------------- +; CONVERT XY COORDINATES IN DE INTO LINEAR INDEX IN HL +; D=ROW, E=COL +;---------------------------------------------------------------------- +; +XOS_XY2IDX: + LD A,E ; SAVE COLUMN NUMBER IN A + LD H,D ; SET H TO ROW NUMBER + PUSH AF + LD A,(XOS_COLS) + LD E,A ; SET E TO ROW LENGTH + CALL MULT8 ; MULTIPLY TO GET ROW OFFSET + POP AF + LD E,A ; GET COLUMN BACK + ADD HL,DE ; ADD IT IN + RET +; +;---------------------------------------------------------------------- +; REVERSE_CURSOR_POS - REVERSE VIDEO THE CHARACTER AT THE CURRENT +; CURSOR POSITION. +;---------------------------------------------------------------------- +; +REVERSE_CURSOR_POS: + PUSH AF + PUSH BC + PUSH DE + LD DE,(XOS_POS) + XM_SETW(ZXM_RD_XADDR) + XM_SETW(ZXM_WR_XADDR) + XM_GETW(ZXM_XDATA) ; GET THE ATTRIBUTE/CHAR AT CURSOR INTO DE + LD A,D + RLCA ; SWAP FG/BG COLORS + RLCA + RLCA + RLCA + LD D,A + XM_SETW(ZXM_XDATA) + POP DE + POP BC + POP AF + RET +; +;---------------------------------------------------------------------- +; WRITE VALUE IN A TO CURRENT XOSERA BUFFER POSITION, ADVANCE CURSOR +;---------------------------------------------------------------------- +; +XOS_PUTCHAR: + ; SETUP DE WITH TILEMEM ADDRESS + LD DE,(XOS_POS) + XM_SETW(ZXM_WR_XADDR) + ; SETUP CHAR/ATTR IN DE + LD E,A ; CHARACTER TO E + LD A,(XOS_ATTR) ; ATTRIBUTE + LD D,A ; ... TO D + ; WRITE CHAR & ATTR + XM_SETW(ZXM_XDATA) + ; UPDATE CURRENT POSITION + LD HL,(XOS_POS) ; GET CURSOR POSITION + INC HL ; INCREMENT + LD (XOS_POS),HL + RET +; +;---------------------------------------------------------------------- +; FILL AREA IN BUFFER WITH SPECIFIED CHARACTER AND CURRENT COLOR/ATTRIBUTE +; STARTING AT THE CURRENT FRAME BUFFER POSITION +; A: FILL CHARACTER +; BC: NUMBER OF CHARACTERS TO FILL +;---------------------------------------------------------------------- +; +XOS_FILL: + LD H,A ; CACHE FILL CHAR IN H + ; SETUP DE WITH INITIAL BUFFER ADDRESS + LD DE,(XOS_POS) ; GET CURRENT POSITION + PUSH BC ; PRESERVE BC (C USED BY MACRO) + XM_SETW(ZXM_WR_XADDR) ; SET VRAM WRITE ADDRESS + POP BC ; RESTORE BC + +XOS_FILL1: + ; FILL ONE POSITION (ATTR & CHAR) + LD E,H ; CHARACTER TO E + LD A,(XOS_ATTR) ; ATTRIBUTE + LD D,A ; ... TO D + PUSH BC ; PRESERVE BC (C USED BY MACRO) + XM_SETW(ZXM_XDATA) ; WRITE CHAR & ATTR + POP BC ; RESTORE BC + + ; CHECK COUNT + DEC BC ; DECREMENT COUNT + LD A,B ; TEST FOR + OR C ; ... ZERO + JR Z,XOS_FILL2 ; DONE IF SO + + ; UPDATE CURSOR POSITION + PUSH HL + LD HL,(XOS_POS) ; GET CURSOR POSITION + INC HL ; INCREMENT + LD (XOS_POS),HL + POP HL + JR XOS_FILL1 +XOS_FILL2: + RET +; +;---------------------------------------------------------------------- +; BLOCK COPY BC BYTES FROM HL (SOURCE) TO DE (DEST). +;---------------------------------------------------------------------- +; +XOS_BLKCPY: + PUSH BC ; COUNT ==> TOS + ; SETUP XOSERA VRAM READ ADDRESS FROM HL + PUSH DE + LD D,H + LD E,L + XM_SETW(ZXM_RD_XADDR) + + ; SETUP XOSERA VRAM WRITE ADDRESS FROM DE + POP DE + XM_SETW(ZXM_WR_XADDR) +XOS_BLKCPY1: + ; GET NEXT SOURCE WORD INTO DE + XM_GETW(ZXM_XDATA) + ; WRITE DE TO DEST WORD + XM_SETW(ZXM_XDATA) + + ; DECREMENT BYTE COUNT AND CHECK FOR COMPLETION + EX (SP),HL ; GET COUNT, SAVE HL + DEC H ; DECREMENT + LD A,H ; TEST FOR + CP L ; ... ZERO + EX (SP),HL ; COUNT BACK TO TOS, RESTORE HL + JR NZ,XOS_BLKCPY1 ; LOOP IF NOT ZERO + POP BC ; CLEAN UP STACK + RET ; DONE +; +;---------------------------------------------------------------------- +; SCROLL ENTIRE SCREEN FORWARD BY ONE OR MORE LINES (CURSOR POSITION UNCHANGED) +;---------------------------------------------------------------------- +; NUMBER OF LINES TO SCROLL COMES IN E + +XOS_SCROLL: + ; DEST ADDR IS START OF LAST ROW + PUSH DE ; SAVE SCROLL LINE COUNT + PUSH DE ; SAVE IT TWICE + PUSH DE ; SAVE IT THRICE + LD A,(XOS_ROWS) + DEC A + LD H,A ; H := ROWS - 1 + LD A,(XOS_COLS) + LD E,A + CALL MULT8 + LD B,H + LD C,L + LD HL,(XOS_OFF) + ADD HL,BC ; HL := DEST TILEMEM ADDRESS + ; SOURCE ADDRESS is DEST ADDRESS - (COLS * LINES) + POP DE ; RESTORE LINE COUNT IN E + PUSH HL ; SAVE DEST ADDRESS SO WE CAN USE H + LD A,(XOS_COLS) + LD H,A + CALL MULT8 + LD D,H + LD E,L ; DE := COLS * LINES + POP HL ; RESTORE DEST ADDR BACK TO HL + PUSH HL + OR A ; CLEAR CARRY + SBC HL,DE ; HL := SOURCE ADDR + POP BC ; BC := DEST ADDRESS + LD A,(XOS_ROWS) + POP DE ; GET SCROLL LINE COUNT IN TO E + SUB E + LD D,B + LD E,C ; RESTORE DE AS DEST ADDR + LD B,A ; B := ROWS - LINE COUNT => LOOP COUNTER + ; USE BLKCPY TO COPY ONE ROW +XOS_SCROLL1: + PUSH HL ; HL IS SOURCE ADDR FOR BLOCK COPY + PUSH DE ; DE IS DEST ADDR FOR BLOCK COPY + PUSH BC ; B IS OUR LOOP COUNTER + LD A,(XOS_COLS) ; EXCEPT THAT BLOCK COPY USES BC FOR COPY COUNT + LD C,A + LD B,0 + CALL XOS_BLKCPY + POP BC ; RESTORE LOOP COUNTER + ; CHECK COUNT + DEC B + JR Z,XOS_SCROLL2 ; MOVE ON TO FILL WHEN DONE + + ; DECREMENT SOURCE AND DEST BY ONE ROW + POP HL ; HL := DEST ADDRESS + LD A,(XOS_COLS) + LD E,A + LD D,0 + OR A ; CLEAR CARRY + SBC HL,DE ; HL := UPDATED DEST ADDRESS (DEST ADDR - COLS) + POP DE ; DE := SOURCE ADDR + PUSH HL ; SAVE UPDATED DEST TEMPORARILY + LD H,D + LD L,E + LD A,(XOS_COLS) + LD E,A + LD D,0 + OR A ; CLEAR CARRY + SBC HL,DE ; HL := UPDATED SOURCE ADDRESS + POP DE ; DE := UPDATED DEST ADDRESS + JR XOS_SCROLL1 ; LOOP AROUND +XOS_SCROLL2: + POP DE + POP HL ; CLEAN UP STACK + POP DE ; RESTORE SCROLL LINE COUNT + ; NOW FILL THE E LINES AT THE TOP OF THE SCREEN. + ; FIRST, SAVE OFF CURRENT CURSOR POSITION, THE SET IT TO 0,0 + LD HL,(XOS_POS) + PUSH HL + LD HL,(XOS_OFF) + LD (XOS_POS),HL ; CURSOR POSITION NOW 0,0 + ; COMPUTE THE NUMBER OF BYTES FILL WHICH IS COLS * LINES + LD A,(XOS_COLS) + LD H,A + CALL MULT8 + LD B,H + LD C,L + LD A,$20 ; FILL CHAR IS SPACE + CALL XOS_FILL + POP HL + LD (XOS_POS),HL ; RESTORE ORIGINAL CURSOR POSITION + RET +; +;---------------------------------------------------------------------- +; REVERSE SCROLL ENTIRE SCREEN BY ONE LINE (CURSOR POSITION UNCHANGED) +;---------------------------------------------------------------------- +; NUMBER OF LINES TO SCROLL COMES IN E + +XOS_RSCROLL: + PUSH DE ; SAVE SCROLL LINE COUNT + PUSH DE ; NEED IT OFF THE STACK TWICE + PUSH DE ; NEED IT OFF THE STACK THRICE + ; DEST ADDR IS ROW=0, COL=0 + LD DE,(XOS_OFF) + XM_SETW(ZXM_WR_XADDR) ; SET DEST ADDR IN XOSERA + POP DE ; RESTORE SCROLL LINE COUNT IN E + ; SOURCE ADDR (HL) = XOS_OFF + XOS_COLS * E + LD A,(XOS_COLS) + LD H,A + CALL MULT8 ; HL := XOS_COLS * E + LD BC,(XOS_OFF) + ADD HL,BC ; HL := SOURCE ADDR := XOS_OFF + XOS_COLS * E + LD D,H + LD E,L + XM_SETW(ZXM_RD_XADDR) ; SET SOURCE ADDR IN XOSERA + ; COMPUTE THE COUNT OF WORDS TO MOVE = COLS * (ROWS - LINES) + POP DE ; RESTORE SCROLL LINE COUNT IN E + LD A,(XOS_ROWS) + SUB E + LD H,A ; H := ROWS - LINES + LD A,(XOS_COLS) + LD E,A ; E := COLS + CALL MULT8 + LD B,H + LD C,L ; BC = COUNT := COLS * (ROW - LINES) + PUSH BC ; SAVE FOR LATER USE BY FILL +XOS_RSCROLL1: + PUSH BC ; MACROS BELOW ALTER C, SO SAVE + XM_GETW(ZXM_XDATA) ; TRANSFER A WORD FROM TILEMEM SRC TO DEST + XM_SETW(ZXM_XDATA) + POP BC ; RESTORE LOOP COUNT + ; CHECK COUNT + DEC BC ; DECREMENT COUNT + LD A,B ; TEST FOR + OR C ; ... ZERO + JR Z,XOS_RSCROLL2 ; MOVE ON TO FILL WHEN DONE + JR XOS_RSCROLL1 +XOS_RSCROLL2: + ; NOW DO THE FILL OF THE EXPOSED LINES AT THE BOTTOM OF THE SCREEN. + ; DESTINATION VRAM ADDRESS FOR THIS FILL IS THE COUNT FROM ABOVE PLUS VRAM OFFSET + POP BC ; RESTORE COUNT + POP DE ; RESTORE LINES IN E + LD A,(XOS_COLS) + LD H,A + PUSH BC ; SAVE COUNT AGAINT + CALL MULT8 ; HL := XOS_COLS * LINES + LD B,H + LD C,L ; BC NOW HAS FILL WORD COUNT + POP HL ; RESTORE SCROLL WORD COUNT TO HL + LD DE,(XOS_OFF) + ADD HL,DE ; ADD IN OFFSET + LD D,H + LD E,L ; DE NOW HAS DEST VRAM ADDR + LD HL,(XOS_POS) ; XOS_FILL USES XOS_POS AS DEST + PUSH HL ; SAVE CURRENT CURSOR POSITION + LD (XOS_POS),DE + LD A,$20 ; USE SPACE TO FILL (USING CURRENT COLOR/ATTR) + CALL XOS_FILL + POP HL + LD (XOS_POS),HL ; RESTORE PREVIOUS CURSOR POSITION + XOR A ; SIGNAL SUCCESS + RET +; +;================================================================================================== +; XOSERA DRIVER - DATA +;================================================================================================== +; +XOS_ATTR: .DB 0 ; CURRENT COLOR +XOS_POS: .DW 0 ; CURRENT DISPLAY POSITION +XOS_OFF: .DW 0 ; SCREEN START OFFSET INTO XOSERA VRAM +XOS_RUB: .DB 0 ; REVERSE/UNDERLINE/BLINK (-----RUB) +XOS_COLS: .DB 0 ; NUMBER OF COLUMNS +XOS_ROWS: .DB 0 ; NUMBER OF ROWS + +XOS_BASE_INIT: + .DW $0000 ; XR_VID_CTRL => NO PLAYFIELD COLOR SWAP. BORDER CORDER = 0 + .DW $0000 ; XR_COPP_CTRL => DISABLE COPPER + .DW $0000 ; XR_AUD_CTRL => DISABLE AUDIO + .DW $0000 ; XR_SCANLINE => JUST SET TO ZERO + .DW $0000 ; XR_VID_LEFT => LEFT EDGE OF ACTIVE DISPLAY => 0 + .DW 640 ; XR_VID_RIGHT => RIGHT EDGE OF ACTIVE DISPLAY => 640 + .DW $0000 ; XR_POINTER_H => HIDE POINTER, SO SET TO 0 + .DW $0000 ; XR_POINTER_V => HIDE POINTER, SO SET TO 0 + +PF_640x480x4: + ; CONFIGURE PLAYFIELD FOR 640x480x4BPP BITMAP GRAPHICS (LETTERBOXED TO 640 X 400) + .DW $0050 ; GFX_CTRL + .DW $0000 ; TILE_CTRL => IGNORED IN BITMAP MODE + .DW $0000 ; DISP_ADDR => START OF VRAM + .DW $00A0 ; LINE_LEN => 640 PIXELS WIDE / 4 PIXELS PER WORD = 160d + .DW $0000 ; HV_FSCALE => NO FRACTIONAL SCALING + .DW $0000 ; H_SCROLL => NO HORIZONTAL FINE SCROLLING + .DW $0000 ; V_SCROLL => NO VERTICAL FINE SCROLLING + +PF_80X30_TILED: + ; CONFIGURE PLAYFIELD FOR 80 X 30 TILED MODE + ; TILEMAP AND 8x16 FONT DATA BOTH RESIDE IN TILEMEM (AS OPPOSED TO VRAM) + .DW $0000 ; GFX_CTRL + .DW FONT_ST_8x16_ADDR | TILE_CTRL_DISP_TILEMEM_F | 15; TILE_CTRL => (LAST ONE IS TILE HEIGHT - 1) + .DW FONT_ST_8x16_ADDR + FONT_ST_8x16_SIZE ; DISP_ADDR => TILEMAP STATS JUST AFTER FONT DATA IN TILEMEM. + .DW $0050 ; LINE_LEN => 80 COLS + .DW $0000 ; HV_FSCALE => NO FRACTIONAL SCALING + .DW $0000 ; H_SCROLL => NO HORIZONTAL FINE SCROLLING + .DW $0000 ; V_SCROLL => NO VERTICAL FINE SCROLLING + +PF_80X60_TILED: + ; CONFIGURE PLAYFIELD FOR 80 X 60 TILED MODE + ; TILEMAP WILL RESIDE IN TILEMEM, BUT DATA IS AT $FC00 IN VRAM + .DW $0000 ; GFX_CTRL + .DW $FC00 | TILE_CTRL_DISP_TILEMEM_F | TILE_CTRL_TILE_VRAM_F | 7; TILE_CTRL => (LAST ONE IS TILE HEIGHT - 1) + .DW $4000 ; DISP_ADDR => TILEMAP STARTS AT BEGINNING OF TILEMEM + .DW $0050 ; LINE_LEN => 80 COLS + .DW $0000 ; HV_FSCALE => NO FRACTIONAL SCALING + .DW $0000 ; H_SCROLL => NO HORIZONTAL FINE SCROLLING + .DW $0000 ; V_SCROLL => NO VERTICAL FINE SCROLLING + +XOS_PALETTE: + ; SET THE FIRST SIXTEEN ENTRIES OF A XOSERA PALETTE TO MATCH WHAT IS EXPECTED BY ROMWBW. + .DW $0000 ; 0: BLACK + .DW $0A00 ; 1: RED + .DW $00A0 ; 2: GREEN + .DW $0A50 ; 3: BROWN + .DW $000A ; 4: BLUE + .DW $0A0A ; 5: MAGENTA + .DW $00AA ; 6: CYAN + .DW $0AAA ; 7: WHITE + .DW $0555 ; 8: GRAY + .DW $0F55 ; 9: LIGHT RED + .DW $05F5 ; 10: LIGHT GREEN + .DW $0FF5 ; 11: YELLOW + .DW $055F ; 12: LIGHT BLUE + .DW $0F5F ; 13: LIGHT MAGENTA + .DW $05FF ; 14: LIGHT CYAN + .DW $0FFF ; 15: BRIGHT WHITE + +; XOSERA HAS A BUILT-IN AMIGA-ISH COPROCESSOR. WE USE IT HERE TO LIMIT THE GRAPHICS +; BITMAP DISPLAY TO 600x400. THIS IS REQUIRED BECAUSE WHILE XOSERA OUTPUTS a 640 X 480 +; BY 60 HZ VGA SIGNAL, THERE IS NOT ENOUGH VRAM FOR A FULL 640 X 480 X 4BPP BITMAP. SO WE +; RESTRICT TO 640x400 AND USE SOME COPPER TRICKS TO BLANK THE OTHER 80 LINES OF +; THE DISPLAY. ESSENTIALLY WE ARE 'LETTERBOXING' A 640 X 400 BITMAP IN THE VERTICAL +; CENTER OF A 640 X 480 DISPLAY. NOTE THAT TEXT MODE STILL USES THE ENTIRE 640 X 480 +; DISPLAY. + +XOS_COPPER: + .DW $D101,$0800 ; LDM $C101 + .DW $1800,$0010 ; STM XR_PA_GFX_CTRL ; start the frame by blanking the display + .DW $2828 ; VPOS #40 ; Wait for line 40 + .DW $0800,$0000 ; LDI #0 + .DW $1800,$0017 ; STM XR_PA_LINE_ADDR + .DW $D100,$0800 ; LDM $C100 ; get value of XR_PA_GFX_CTRL with BLANK bit NOT set + .DW $1800,$0010 ; STM XR_PA_GFX_CTRL ; unblank playfield A + .DW $D101,$0800 ; LDM $C101 ; get value of XR_PA_GFX_CTRL with BLANK bit set + .DW $29B8 ; VPOS #440 ; wait until vertical line 440 + .DW $1800,$0010 ; STM XR_PA_GFX_CTRL ; blank playfield A + .DW $2BFF ; VPOS #V_EOF ; wait until end of frame +; +;================================================================================================== +; XOSERA DRIVER - INSTANCE DATA +;================================================================================================== +; +XOS_IDAT: + .DB KBDMODE_NONE + .DB 0 + .DB 0 + +XOS_IDAT2: + .DB KBDMODE_NONE + .DB 0 + .DB 0 diff --git a/Source/HBIOS/ym2612.asm b/Source/HBIOS/ym2612.asm index 018729d6..0516ef42 100644 --- a/Source/HBIOS/ym2612.asm +++ b/Source/HBIOS/ym2612.asm @@ -245,11 +245,11 @@ YM_NOTE: ;CALL PRTHEXWORDHL LD DE,40 ; Calculate the ym2612 block (octave) ADD HL,DE ; This will go into b13-b11 LD DE,48 ; HL / DE - CALL DIV16 ; BC = block (octave) HL = quarter semitone note + CALL DIV16 ; BC = block (octave) HL = quarter semitone ; ADD HL,HL LD DE,ym_notetable ; point HL to frequency entry - ADD HL,DE ; for the quarter semitone note + ADD HL,DE ; for the quarter semitone ;CALL PRTHEXWORDHL ;CALL PC_COLON diff --git a/Source/HBIOS/z2u.asm b/Source/HBIOS/z2u.asm index 60100438..698fa4a2 100644 --- a/Source/HBIOS/z2u.asm +++ b/Source/HBIOS/z2u.asm @@ -133,13 +133,14 @@ Z2U_INITUNIT: ; FAILSAFE CONFIG ONTO THE CHANNEL. IF THE SUBSEQUENT "REAL" ; CONFIG FAILS, AT LEAST THE CHIP WILL BE ABLE TO SPIT DATA OUT ; AT A RATIONAL BAUD/DATA/PARITY/STOP CONFIG. - CALL Z2U_INITSAFE + LD A,%11000010 ; 8N0, DIV 16, NO C/T + LD (Z2U_CFGREG),A ; SAVE IT + LD HL,1 ; C/T DIV 1 + CALL Z2U_INITDEV8 ; DO IT ; ; SET DEFAULT CONFIG LD DE,-1 ; LEAVE CONFIG ALONE - ; CALL INITDEV TO IMPLEMENT CONFIG, BUT NOTE THAT WE CALL - ; THE INITDEVX ENTRY POINT THAT DOES NOT ENABLE/DISABLE INTS! - JP Z2U_INITDEVX ; IMPLEMENT IT AND RETURN + JP Z2U_INITDEV ; IMPLEMENT IT AND RETURN ; ; ; @@ -434,23 +435,20 @@ Z2U_OST: ; REQUIRED BY THE Z2U AND STORED IN A PORT/REGISTER INITIALIZATION TABLE, ; WHICH IS THEN LOADED INTO THE Z2U. ; -; NOTE THAT THERE ARE TWO ENTRY POINTS. INITDEV WILL DISABLE/ENABLE INTS -; AND INITDEVX WILL NOT. THIS IS DONE SO THAT THE PREINIT ROUTINE ABOVE -; CAN AVOID ENABLING/DISABLING INTS. -; Z2U_INITDEV: + ; INITDEV CAN BE CALLED PRIOR TO INTERRUPTS BEING ENABLED. WE + ; NEED TO LEAVE INTERRUPTS ALONE IN THIS SCENARIO + LD A,(INTSENAB) ; INTS ENABLED? + OR A ; TEST VALUE + JR Z,Z2U_INITDEV0 ; BYPASS DI/EI IF NOT ENABLED +; + ; INTERRUPTS DISABLED DURING INIT HB_DI ; DISABLE INTS - CALL Z2U_INITDEVX ; DO THE WORK + CALL Z2U_INITDEV0 ; DO THE WORK HB_EI ; INTS BACK ON RET ; DONE ; -Z2U_INITSAFE: - LD A,%11000010 ; 8N0, DIV 16, NO C/T - LD (Z2U_CFGREG),A ; SAVE IT - LD HL,1 ; C/T DIV 1 - JR Z2U_INITDEV8 ; DO IT -; -Z2U_INITDEVX: +Z2U_INITDEV0: ; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT) LD A,D ; TEST DE FOR AND E ; ... VALUE OF -1 @@ -535,7 +533,7 @@ Z2U_INITDEV2: LD (IY+4),E ; SAVE LOW WORD LD (IY+5),D ; SAVE HI WORD ; -Z2U_INITDEV8: +Z2U_INITDEV8: ; THIS LABEL IS USED IN INITUNIT!!! ; START BY SELECTING I/O PAGE $FE PUSH HL ; SAVE HL LD L,$FE ; Z280 UART REGISTERS AT I/O PAGE $FE diff --git a/Source/Images/Build.cmd b/Source/Images/Build.cmd index f9b9aa04..af05daa9 100644 --- a/Source/Images/Build.cmd +++ b/Source/Images/Build.cmd @@ -1,91 +1,36 @@ +:: This script will build all slice images and all aggregate disk +:: images. + @echo off setlocal -:: call BuildDisk.cmd bp hd wbw_hd1k ..\zsdos\zsys_wbw.sys -:: copy /b hd1k_prefix.dat + ..\..\Binary\hd1k_bp.img + ..\..\Binary\hd1k_cpm22.img + ..\..\Binary\hd1k_zsdos.img + ..\..\Binary\hd1k_nzcom.img + ..\..\Binary\hd1k_cpm3.img + ..\..\Binary\hd1k_zpm3.img + ..\..\Binary\hd1k_ws4.img ..\..\Binary\hd1k_combo_bp.img || exit /b -:: goto :eof +SETLOCAL EnableDelayedExpansion + +copy hd1k_prefix.dat ..\..\Binary\ || exit /b -echo. -echo Building Floppy Disk Images... -echo. -call BuildDisk.cmd cpm22 fd wbw_fd144 ..\cpm22\cpm_wbw.sys || exit /b -call BuildDisk.cmd zsdos fd wbw_fd144 ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd nzcom fd wbw_fd144 ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd cpm3 fd wbw_fd144 ..\cpm3\cpmldr.sys || exit /b -call BuildDisk.cmd zpm3 fd wbw_fd144 ..\zpm3\zpmldr.sys || exit /b -call BuildDisk.cmd z3plus fd wbw_fd144 ..\cpm3\cpmldr.sys || exit /b -call BuildDisk.cmd ws4 fd wbw_fd144 || exit /b -call BuildDisk.cmd qpm fd wbw_fd144 ..\qpm\qpm_wbw.sys || exit /b -call BuildDisk.cmd z80asm fd wbw_fd144 || exit /b -call BuildDisk.cmd aztecc fd wbw_fd144 || exit /b -call BuildDisk.cmd hitechc fd wbw_fd144 || exit /b -call BuildDisk.cmd tpascal fd wbw_fd144 || exit /b -call BuildDisk.cmd bascomp fd wbw_fd144 || exit /b -call BuildDisk.cmd cobol fd wbw_fd144 || exit /b -call BuildDisk.cmd fortran fd wbw_fd144 || exit /b -call BuildDisk.cmd games fd wbw_fd144 || exit /b -call BuildDisk.cmd cowgol fd wbw_fd144 || exit /b +:: For each floppy disk image definition (fd_*.txt), invoke PowerShell +:: to build the image. -echo. -echo Building Hard Disk Images (512 directory entry format)... -echo. -call BuildDisk.cmd blank hd wbw_hd512 || exit /b -call BuildDisk.cmd cpm22 hd wbw_hd512 ..\cpm22\cpm_wbw.sys || exit /b -call BuildDisk.cmd zsdos hd wbw_hd512 ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd nzcom hd wbw_hd512 ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd cpm3 hd wbw_hd512 ..\cpm3\cpmldr.sys || exit /b -call BuildDisk.cmd zpm3 hd wbw_hd512 ..\zpm3\zpmldr.sys || exit /b -call BuildDisk.cmd z3plus hd wbw_hd512 ..\cpm3\cpmldr.sys || exit /b -call BuildDisk.cmd ws4 hd wbw_hd512 || exit /b -call BuildDisk.cmd dos65 hd wbw_hd512 ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd qpm hd wbw_hd512 ..\qpm\qpm_wbw.sys || exit /b -call BuildDisk.cmd z80asm hd wbw_hd512 || exit /b -call BuildDisk.cmd aztecc hd wbw_hd512 || exit /b -call BuildDisk.cmd hitechc hd wbw_hd512 || exit /b -call BuildDisk.cmd tpascal hd wbw_hd512 || exit /b -call BuildDisk.cmd bascomp hd wbw_hd512 || exit /b -call BuildDisk.cmd cobol hd wbw_hd512 || exit /b -call BuildDisk.cmd fortran hd wbw_hd512 || exit /b -call BuildDisk.cmd games hd wbw_hd512 || exit /b -call BuildDisk.cmd cowgol hd wbw_hd512 || exit /b -call BuildDisk.cmd msxroms1 hd wbw_hd512 || exit /b -call BuildDisk.cmd msxroms2 hd wbw_hd512 || exit /b +for %%f in (fd_*.txt) do ( + set Image=%%~nf + PowerShell -ExecutionPolicy Unrestricted .\BuildImg.ps1 fd144_!Image:fd_=! || exit /b +) -echo. -echo Building Combo Disk (512 directory entry format) Images... -copy /b ..\..\Binary\hd512_cpm22.img + ..\..\Binary\hd512_zsdos.img + ..\..\Binary\hd512_nzcom.img + ..\..\Binary\hd512_cpm3.img + ..\..\Binary\hd512_zpm3.img + ..\..\Binary\hd512_ws4.img ..\..\Binary\hd512_combo.img || exit /b -copy /b ..\..\Binary\hd512_cpm22.img + ..\..\Binary\hd512_ws4.img + ..\..\Binary\hd512_aztecc.img + ..\..\Binary\hd512_bascomp.img + ..\..\Binary\hd512_tpascal.img + ..\..\Binary\hd512_fortran.img + ..\..\Binary\hd512_cobol.img + ..\..\Binary\hd512_z80asm.img + ..\..\Binary\hd512_games.img ..\..\Binary\hd512_combo_demo.img || exit /b +:: For each hard disk slice image definition (hd_*.txt), invoke +:: PowerShell to build the slice image. Note that both hd512 and +:: hd1k style images are built. -echo. -echo Building Hard Disk Images (1024 directory entry format)... -echo. -call BuildDisk.cmd blank hd wbw_hd1k || exit /b -call BuildDisk.cmd cpm22 hd wbw_hd1k ..\cpm22\cpm_wbw.sys || exit /b -call BuildDisk.cmd zsdos hd wbw_hd1k ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd nzcom hd wbw_hd1k ..\zsdos\zsys_wbw.sys || exit /b -call BuildDisk.cmd cpm3 hd wbw_hd1k ..\cpm3\cpmldr.sys || exit /b -call BuildDisk.cmd zpm3 hd wbw_hd1k ..\zpm3\zpmldr.sys || exit /b -call BuildDisk.cmd z3plus hd wbw_hd1k ..\cpm3\cpmldr.sys || exit /b -call BuildDisk.cmd ws4 hd wbw_hd1k || exit /b -call BuildDisk.cmd qpm hd wbw_hd1k ..\qpm\qpm_wbw.sys || exit /b -call BuildDisk.cmd z80asm hd wbw_hd1k || exit /b -call BuildDisk.cmd aztecc hd wbw_hd1k || exit /b -call BuildDisk.cmd hitechc hd wbw_hd1k || exit /b -call BuildDisk.cmd tpascal hd wbw_hd1k || exit /b -call BuildDisk.cmd bascomp hd wbw_hd1k || exit /b -call BuildDisk.cmd cobol hd wbw_hd1k || exit /b -call BuildDisk.cmd fortran hd wbw_hd1k || exit /b -call BuildDisk.cmd games hd wbw_hd1k || exit /b -call BuildDisk.cmd cowgol hd wbw_hd1k || exit /b -call BuildDisk.cmd msxroms1 hd wbw_hd1k || exit /b -call BuildDisk.cmd msxroms2 hd wbw_hd1k || exit /b +for %%f in (hd_*.txt) do ( + set Image=%%~nf + PowerShell -ExecutionPolicy Unrestricted .\BuildImg.ps1 hd512_!Image:hd_=! || exit /b + PowerShell -ExecutionPolicy Unrestricted .\BuildImg.ps1 hd1k_!Image:hd_=! || exit /b +) -if exist ..\BPBIOS\bp*.rel call BuildDisk.cmd bp hd wbw_hd1k ..\zsdos\zsys_wbw.sys || exit /b +:: For each aggregate disk image definition (*.def), invoke PowerShell +:: to build the disk image. -copy hd1k_prefix.dat ..\..\Binary\ || exit /b +for %%f in (*.def) do ( + PowerShell -ExecutionPolicy Unrestricted .\BuildDsk.ps1 hd512_%%~nf || exit /b + PowerShell -ExecutionPolicy Unrestricted .\BuildDsk.ps1 hd1k_%%~nf || exit /b +) -echo. -echo Building Combo Disk (1024 directory entry format) Images... -copy /b hd1k_prefix.dat + ..\..\Binary\hd1k_cpm22.img + ..\..\Binary\hd1k_zsdos.img + ..\..\Binary\hd1k_nzcom.img + ..\..\Binary\hd1k_cpm3.img + ..\..\Binary\hd1k_zpm3.img + ..\..\Binary\hd1k_ws4.img ..\..\Binary\hd1k_combo.img || exit /b -copy /b hd1k_prefix.dat + ..\..\Binary\hd1k_cpm22.img + ..\..\Binary\hd1k_ws4.img + ..\..\Binary\hd1k_aztecc.img + ..\..\Binary\hd1k_bascomp.img + ..\..\Binary\hd1k_tpascal.img + ..\..\Binary\hd1k_fortran.img + ..\..\Binary\hd1k_cobol.img + ..\..\Binary\hd1k_z80asm.img + ..\..\Binary\hd1k_games.img ..\..\Binary\hd1k_combo_demo.img || exit /b -echo. diff --git a/Source/Images/BuildDisk.cmd b/Source/Images/BuildDisk.cmd deleted file mode 100644 index 4f865ae8..00000000 --- a/Source/Images/BuildDisk.cmd +++ /dev/null @@ -1,4 +0,0 @@ -@echo off -setlocal - -PowerShell -ExecutionPolicy Unrestricted .\BuildDisk.ps1 %* || exit /b \ No newline at end of file diff --git a/Source/Images/BuildDisk.ps1 b/Source/Images/BuildDisk.ps1 deleted file mode 100644 index 9f870713..00000000 --- a/Source/Images/BuildDisk.ps1 +++ /dev/null @@ -1,110 +0,0 @@ -Param($Disk, $Type="", $Format="", $SysFile="") - -$ErrorAction = 'Stop' - -$CpmToolsPath = '../../Tools/cpmtools' - -$env:PATH = $CpmToolsPath + ';' + $env:PATH - -if ($Type.Length -eq 0) -{ - Write-Error "No disk type specified!" -ErrorAction Stop - return -} - -if ($Format.Length -eq 0) -{ - Write-Error "No disk format specified!" -ErrorAction Stop - return -} - -switch ($Format) -{ - "wbw_fd144" - { - # 1.44MB Floppy Disk - $Desc = "1.44MB Floppy Disk" - $ImgFile = "fd144_${Disk}.img" - $CatFile = "fd144_${Disk}.cat" - $MediaID = 6 - $Size = 1440KB - } - - "wbw_hd512" - { - # 512 Directory Entry Hard Disk Format - $Desc = "Hard Disk (512 directory entry format)" - $ImgFile = "hd512_${Disk}.img" - $CatFile = "hd512_${Disk}.cat" - $MediaID = 4 - $Size = 8MB + 128KB - } - - "wbw_hd1k" - { - # 1024 Directory Entry Hard Disk Format - $Desc = "Hard Disk (1024 directory entry format)" - $ImgFile = "hd1k_${Disk}.img" - $CatFile = "hd1k_${Disk}.cat" - $MediaID = 10 - $Size = 8MB - } -} - -if (-not (Test-Path("d_${Disk}/"))) -{ - Write-Error "Source directory d_${Disk} for disk ${Disk} not found!" -ErrorAction Stop - return -} - -"Generating $Disk $Desc..." - -if ($SysFile.Length -gt 0) - { [byte[]]$SysImg = [System.IO.File]::ReadAllBytes($SysFile) } -else - { [byte[]]$SysImg = @() } - -$Image = ($SysImg + ([byte[]](0xE5) * ($Size - $SysImg.length))) - -# $Image[1410] = 0x4D -# $Image[1411] = 0x49 -# $Image[1412] = 0x44 -# $Image[1413] = $MediaID - -[System.IO.File]::WriteAllBytes($ImgFile, $Image) - -for ($Usr=0; $Usr -lt 16; $Usr++) -{ - if (Test-Path ("d_${Disk}/u${Usr}/*")) - { - $Cmd = "cpmcp -f $Format $ImgFile d_${Disk}/u${Usr}/*.* ${Usr}:" - $Cmd - Invoke-Expression $Cmd - if ($LASTEXITCODE -gt 0) {throw "Command returned exit code $LASTEXITCODE"} - } -} - -if (Test-Path("${Type}_${Disk}.txt")) -{ - foreach($Line in Get-Content "${Type}_${Disk}.txt") - { - $Spec = $Line.Trim() - if (($Spec.Length -gt 0) -and ($Spec.Substring(0,1) -ne "#")) - { - $Cmd = "cpmcp -f $Format $ImgFile ${Spec}" - $Cmd - Invoke-Expression $Cmd - if ($LASTEXITCODE -gt 0) {throw "Command returned exit code $LASTEXITCODE"} - } - } -} - -$Cmd = "cpmls -f $Format -D $ImgFile" -$Cmd -Invoke-Expression $Cmd > $CatFile - -"Moving image $ImgFile into output directory..." - -Move-Item $ImgFile -Destination "..\..\Binary\" -Force - -return \ No newline at end of file diff --git a/Source/Images/BuildDsk.ps1 b/Source/Images/BuildDsk.ps1 new file mode 100644 index 00000000..220b367d --- /dev/null +++ b/Source/Images/BuildDsk.ps1 @@ -0,0 +1,65 @@ +# This PowerShell script will build an aggregate hard disk +# image based on the parameter passed in. The single +# input parameter is the name of the desired image. E.g., +# hd1k_combo.img will build a combo disk image (defined in combo.def) +# using the hd1k format. + +param([string]$Disk) + +# If a PowerShell exception occurs, just stop the script immediately. +$ErrorAction = 'Stop' + +# $ImgFile = "..\..\Binary\hd1k_" + $Image + ".img" + +$Format, $Def = $Disk.Split("_") + +$DefFile = $Def + ".def" + +$SliceList = @() + +ForEach ($Line in Get-Content $DefFile) +{ + $Line = $Line.Trim() + + if (($Line.Length -eq 0) -or ($Line[0] -eq "#")) + { + continue + } + + $SliceList += $Line +} + +$ImgFile = "..\..\Binary\" + $Disk + ".img" + +$FileList = "" + +"Generating $ImgFile using $DefFile..." + +ForEach ($Slice in $SliceList) +{ + $File = "..\..\Binary\" + $Format + "_" + $Slice + ".img" + + if (!(Test-Path $File)) + { + "Slice input file """ + $File + """ not found!!!" + exit 1 + } + + if ($FileList.Length -gt 0) + { + $FileList += "+" + } + + $FileList += $File +} + +if ($Format -eq "hd1k") +{ + $FileList = "hd1k_prefix.dat+" + $FileList +} + +$Cmd = "$env:ComSpec /c copy /b $FileList $ImgFile" +$Cmd +Invoke-Expression $Cmd + +exit 0 diff --git a/Source/Images/BuildImg.ps1 b/Source/Images/BuildImg.ps1 new file mode 100644 index 00000000..1e9177fc --- /dev/null +++ b/Source/Images/BuildImg.ps1 @@ -0,0 +1,150 @@ +# This PowerShell script will build a floppy disk or hard disk +# slice image based on the parameter passed in. The single +# input parameter is the name of the desired image. E.g., +# hd1k_zsdos.img will build a zsdos slice image as defined in +# hd_zsdos.txt using the hd1k format. + +param([string]$Image) + +# If a PowerShell exception occurs, just stop the script immediately. +$ErrorAction = 'Stop' + +$CpmToolsPath = '../../Tools/cpmtools' + +$env:PATH = $CpmToolsPath + ';' + $env:PATH + +$Format, $Disk = $Image.Split("_") + +$Format = "wbw_" + $Format + +if ($Format.Length -eq 0) +{ + Write-Error "No disk format specified!" -ErrorAction Stop + return +} + +switch ($Format) +{ + "wbw_fd144" + { + # 1.44MB Floppy Disk + $Type = "fd" + $Desc = "1.44MB Floppy Disk" + $ImgFile = "fd144_${Disk}.img" + $CatFile = "fd144_${Disk}.cat" + $MediaID = 6 + $Size = 1440KB + } + + "wbw_hd512" + { + # 512 Directory Entry Hard Disk Format + $Type = "hd" + $Desc = "Hard Disk (512 directory entry format)" + $ImgFile = "hd512_${Disk}.img" + $CatFile = "hd512_${Disk}.cat" + $MediaID = 4 + $Size = 8MB + 128KB + } + + "wbw_hd1k" + { + # 1024 Directory Entry Hard Disk Format + $Type = "hd" + $Desc = "Hard Disk (1024 directory entry format)" + $ImgFile = "hd1k_${Disk}.img" + $CatFile = "hd1k_${Disk}.cat" + $MediaID = 10 + $Size = 8MB + } +} + +if (-not (Test-Path("d_${Disk}/"))) +{ + Write-Error "Source directory d_${Disk} for disk ${Disk} not found!" -ErrorAction Stop + return +} + +"Generating $Disk $Desc..." + +if (Test-Path("${Type}_${Disk}.txt")) +{ + foreach($Line in Get-Content "${Type}_${Disk}.txt") + { + $Spec = $Line.Trim() + if (($Spec.Length -gt 0) -and ($Spec.Substring(0,1) -eq '@')) + { + $Directive = $Spec.Substring(1); + $VarName, $VarVal = $Directive.Split("=") + Invoke-Expression "`$$VarName = $VarVal" + continue + } + } +} + +# "Label: '$Label'" +# "SysImage: '$SysImage'" + +if ($SysImage.Length -gt 0) + { [byte[]]$SysImg = [System.IO.File]::ReadAllBytes($SysImage) } +else + { [byte[]]$SysImg = @() } + +$ImageBin = ($SysImg + ([byte[]](0xE5) * ($Size - $SysImg.length))) + +if ($Label.Length -gt 0) +{ + $LabelBytes = [System.Text.Encoding]::ASCII.GetBytes($Label) + $nLabel = 0; + for ($nImg = 0x5E7; $nImg -lt 0x5F7; $nImg++) + { + if ($nLabel -lt $Label.Length) + { + $ImageBin[$nImg] = $LabelBytes[$nLabel] + } + else + { + $ImageBin[$nImg] = [byte][char]'$' + } + $nLabel++ + } + $ImageBin[0x5F7] = [byte][char]'$' +} + +[System.IO.File]::WriteAllBytes($ImgFile, $ImageBin) + +for ($Usr=0; $Usr -lt 16; $Usr++) +{ + if (Test-Path ("d_${Disk}/u${Usr}/*")) + { + $Cmd = "cpmcp -f $Format $ImgFile d_${Disk}/u${Usr}/*.* ${Usr}:" + $Cmd + Invoke-Expression $Cmd + if ($LASTEXITCODE -gt 0) {throw "Command returned exit code $LASTEXITCODE"} + } +} + +if (Test-Path("${Type}_${Disk}.txt")) +{ + foreach($Line in Get-Content "${Type}_${Disk}.txt") + { + $Spec = $Line.Trim() + if (($Spec.Length -gt 0) -and ($Spec.Substring(0,1) -ne "#") -and ($Spec.Substring(0,1) -ne "@")) + { + $Cmd = "cpmcp -f $Format $ImgFile ${Spec}" + $Cmd + Invoke-Expression $Cmd + if ($LASTEXITCODE -gt 0) {throw "Command returned exit code $LASTEXITCODE"} + } + } +} + +$Cmd = "cpmls -f $Format -D $ImgFile" +$Cmd +Invoke-Expression $Cmd > $CatFile + +# "Moving image $ImgFile into output directory..." + +Move-Item $ImgFile -Destination "..\..\Binary\" -Force + +return diff --git a/Source/Images/Common/All/u10/FLASH.DOC b/Source/Images/Common/All/u10/FLASH.DOC index d149ad3d..a696e961 100644 --- a/Source/Images/Common/All/u10/FLASH.DOC +++ b/Source/Images/Common/All/u10/FLASH.DOC @@ -1,206 +1,207 @@ - - FLASH4 (c) 2014-2020 William R Sowerbutts - http://sowerbutts.com/8bit/ - -= Supported machines = - -FLASH4 has been tested and confirmed working on: - * N8VEM SBCv2 - * N8VEM SBCv2 MegaFlash - * N8VEM N8-2312 - * N8VEM Mark IV SBC - * DX-Designs P112 - * ZETA SBC v1 - * ZETA SBC v2 - * RC2014 with 512KB ROM 512KB RAM module - -It should work on many other machines that run RomWBW or UNA BIOS. If you test -it on another machine please let me know the outcome. - -FLASH030 (also included) is a Linux version of the same software. It is -targetted at my 68030 machine but should be very easy to port to other -machines. It expects a machine with a larger address space, and thus omits much -of the bank switching and other tricks required on Z80 platforms. - - -= Introduction = - -FLASH4 is a CP/M program which can read, write and verify Flash ROM contents to -or from an image file stored on a CP/M filesystem. It is intended for in-system -programming of Flash ROM chips on Z80 and Z180 systems. - -FLASH4 aims to support a range of Flash ROM chips and machines. Ideally I would -like to support all Z80/Z180 machines. If FLASH4 does not support your machine -please let me know and I will try to add support. - -When writing to the Flash ROM, FLASH4 will only reprogram the sectors whose -contents have changed. This helps to reduce wear on the flash memory, makes the -reprogram operation faster, and reduces the risk of leaving the system -unbootable if power fails during a reprogramming operation. FLASH4 always -performs a full verify operation after writing to the chip to confirm that the -correct data has been loaded. - -FLASH4 is reasonably fast. Reprogramming and verifying every sector on a 512KB -SST 39F040 chip takes 21 seconds on my Mark IV SBC, versus 45 seconds to -perform the same task using a USB MiniPro TL866 EEPROM programmer under Linux -on my PC. If only a subset of sectors require reprogramming FLASH4 will be -even faster. - -FLASH4 works with binary ROM image files, it does not support Intel Hex format -files. Hex files can be easily converted to or from binaries using "hex2bin" or -the "srec_cat" program from SRecord: - - $ srec_cat image.hex -intel -fill 0xFF 0 0x80000 -output image.bin -binary - $ srec_cat image.bin -binary -output image.hex -intel - -FLASH4 version 1.3 introduces support for programming multiple flash chips. -Some machines use multiple flash chips for larger ROM capacity, for example the -"Megaflash" version of the Retrobrew Computers SBC-V2 contains two 512KB flash -ROMs for a total of 1MB ROM. All flash chips in the system must be of the same -type. - -FLASH4 can use several different methods to access the Flash ROM chips. The -best available method is determined automatically at run time. Alternatively -you may provide a command-line option to force the use of a specific method. - -FLASH4 will detect the presence of RomWBW, UNA BIOS or P112 B/P BIOS and use -the bank switching methods they provide to map in the flash memory. - -If no bank switching method can be auto-detected, and the system has a Z180 -CPU, FLASH4 will use the Z180 DMA engine to access the Flash ROM chip. This -does not require any bank switching but it is slower and will not work on all -platforms. - -Z180 DMA access requires the flash ROM to be linearly mapped into the lower -region of physical memory, as it is on the Mark IV SBC (for example). The -N8-2312 has additional memory mapping hardware, consequently Z180 DMA access on -the N8-2312 is NOT SUPPORTED and if forced will corrupt the contents of RAM; -use one of the supported bank switching methods instead. - -Z180 DMA access requires the Z180 CPU I/O base control register configured to -locate the internal I/O addresses at 0x40 (ie ICR bits IOA7, IOA6 = 0, 1). - - -= Usage = - -The three basic operations are: - - FLASH4 WRITE filename [options] - - FLASH4 VERIFY filename [options] - - FLASH4 READ filename [options] - -The WRITE command will rewrite the flash ROM contents from the named file. The -file size must exactly match the size of the ROM chip. After the WRITE -operation, a VERIFY operation will be performed automatically. - -The VERIFY command will read out the flash ROM contents and report if it -matches the contents of the named file. The file size must exactly match the -size of the ROM chip. - -The READ command will read out the entire flash ROM contents and write it to -the named file. - -FLASH4 will auto-detect most parameters so additional options should not -normally be required. - -The "/V" (verbose) option makes FLASH4 print one line per sector, giving a -detailed log of what it did. - -The "/P" or "/PARTIAL" option can be used if your ROM chip is larger than the -image you wish to write and you only want to reprogram part of it. To avoid -accidentally flashing the wrong file, the image file must be an exact multiple -of 32KB in length. The portion of the ROM not occupied by the image file is -left either unmodified or erased. - -The "/ROM" option can be used when you are using an ROM/EPROM/EEPROM chip which -cannot be programmed in-system and FLASH4 cannot recognise it. Only the "READ" -and "VERIFY" commands are supported with this option. This mode assumes a 512K -ROM is fitted, smaller ROMs will be treated as a 512KB ROM with the data -repeated multiple times. - -One of the following optional command line arguments may be specified at the -end of the command line to force FLASH4 to use a particular method to access -the flash ROM chip: - -BIOS interfaces: - /ROMWBW For ROMWBW BIOS version 2.6 and later - /ROMWBWOLD For ROMWBW BIOS version 2.5 and earlier - /UNABIOS For UNA BIOS - -Direct hardware interfaces: - /Z180DMA For Z180 DMA - /P112 For DX-Designs P112 - /N8VEMSBC For N8VEM SBC (v1, v2), Zeta (v1) SBC - -If no option is specified FLASH4 attempts to determine the best available -method automatically. - -If RomWBW 2.6+ is in use, and correctly configured, then multiple flash chips -can be detected automatically. Multiple chip operation can also be manually -enabled using the command line options "/1", "/2", "/3" etc up to "/9" to -specify the number of flash chips to program. All flash chips in the system -must be of the same type. - - -= Supported flash memory chips = - -FLASH4 will interrogate your flash ROM chip to identify it automatically. - -FLASH4 does not support setting or resetting the protection bits on individual -sectors within Flash ROM devices. If your Flash ROM chip has protected sectors -you will need to unprotect them by other means before FLASH4 can erase and -reprogram them. - -AT29C series chips employ an optional "software data protection" feature. This -is supported by FLASH4 and is left activated after programming the chip to -prevent accidental reprogramming of sectors. - -The following chips are fully supported and will be programmed sector by -sector: - - AMIC A29010B - AMIC A29040B - Atmel AT29C010 - Atmel AT29C020 - Atmel AT29C040 - Atmel AT29C512 - Atmel AT29F010 - Atmel AT29F040 - Macronix MX29F040 - SST 39F010 - SST 39F020 - SST 39F040 - SST M29F010 - SST M29F040 - -The following chips are supported, but have unequal sector sizes, so FLASH4 -will only erase and reprogram the entire chip at once: - - Atmel AT49F001N - Atmel AT49F001NT - Atmel AT49F002N - Atmel AT49F002NT - Atmel AT49F040 - - -= Compiling = - -The software is written in a mix of C and assembler. It builds using the SDCC -toolchain and the SRecord tools. SDCC 3.6 and 3.8 have been tested. A Makefile -is provided to build the executable in Linux and I imagine it can be easily -modified to build in Windows. - -You may need to adjust the path to the SDCC libraries in the Makefile if your -installation is not in /usr/local or /usr - - -= License = - -FLASH4 is licensed under the The GNU General Public License version 3 (see -included "LICENSE.txt" file). - -FLASH4 is provided with NO WARRANTY. In no event will the author be liable for -any damages. Use of this program is at your own risk. May cause rifts in space -and time. + + FLASH4 (c) 2014-2020 William R Sowerbutts + http://sowerbutts.com/8bit/ + += Supported machines = + +FLASH4 has been tested and confirmed working on: + * N8VEM SBCv2 + * N8VEM SBCv2 MegaFlash + * N8VEM N8-2312 + * N8VEM Mark IV SBC + * DX-Designs P112 + * ZETA SBC v1 + * ZETA SBC v2 + * RC2014 with 512KB ROM 512KB RAM module + +It should work on many other machines that run RomWBW or UNA BIOS. If you test +it on another machine please let me know the outcome. + +FLASH030 (also included) is a Linux version of the same software. It is +targetted at my 68030 machine but should be very easy to port to other +machines. It expects a machine with a larger address space, and thus omits much +of the bank switching and other tricks required on Z80 platforms. + + += Introduction = + +FLASH4 is a CP/M program which can read, write and verify Flash ROM contents to +or from an image file stored on a CP/M filesystem. It is intended for in-system +programming of Flash ROM chips on Z80 and Z180 systems. + +FLASH4 aims to support a range of Flash ROM chips and machines. Ideally I would +like to support all Z80/Z180 machines. If FLASH4 does not support your machine +please let me know and I will try to add support. + +When writing to the Flash ROM, FLASH4 will only reprogram the sectors whose +contents have changed. This helps to reduce wear on the flash memory, makes the +reprogram operation faster, and reduces the risk of leaving the system +unbootable if power fails during a reprogramming operation. FLASH4 always +performs a full verify operation after writing to the chip to confirm that the +correct data has been loaded. + +FLASH4 is reasonably fast. Reprogramming and verifying every sector on a 512KB +SST 39F040 chip takes 21 seconds on my Mark IV SBC, versus 45 seconds to +perform the same task using a USB MiniPro TL866 EEPROM programmer under Linux +on my PC. If only a subset of sectors require reprogramming FLASH4 will be +even faster. + +FLASH4 works with binary ROM image files, it does not support Intel Hex format +files. Hex files can be easily converted to or from binaries using "hex2bin" or +the "srec_cat" program from SRecord: + + $ srec_cat image.hex -intel -fill 0xFF 0 0x80000 -output image.bin -binary + $ srec_cat image.bin -binary -output image.hex -intel + +FLASH4 version 1.3 introduces support for programming multiple flash chips. +Some machines use multiple flash chips for larger ROM capacity, for example the +"Megaflash" version of the Retrobrew Computers SBC-V2 contains two 512KB flash +ROMs for a total of 1MB ROM. All flash chips in the system must be of the same +type. + +FLASH4 can use several different methods to access the Flash ROM chips. The +best available method is determined automatically at run time. Alternatively +you may provide a command-line option to force the use of a specific method. + +FLASH4 will detect the presence of RomWBW, UNA BIOS or P112 B/P BIOS and use +the bank switching methods they provide to map in the flash memory. + +If no bank switching method can be auto-detected, and the system has a Z180 +CPU, FLASH4 will use the Z180 DMA engine to access the Flash ROM chip. This +does not require any bank switching but it is slower and will not work on all +platforms. + +Z180 DMA access requires the flash ROM to be linearly mapped into the lower +region of physical memory, as it is on the Mark IV SBC (for example). The +N8-2312 has additional memory mapping hardware, consequently Z180 DMA access on +the N8-2312 is NOT SUPPORTED and if forced will corrupt the contents of RAM; +use one of the supported bank switching methods instead. + +Z180 DMA access requires the Z180 CPU I/O base control register configured to +locate the internal I/O addresses at 0x40 (ie ICR bits IOA7, IOA6 = 0, 1). + + += Usage = + +The three basic operations are: + + FLASH4 WRITE filename [options] + + FLASH4 VERIFY filename [options] + + FLASH4 READ filename [options] + +The WRITE command will rewrite the flash ROM contents from the named file. The +file size must exactly match the size of the ROM chip. After the WRITE +operation, a VERIFY operation will be performed automatically. + +The VERIFY command will read out the flash ROM contents and report if it +matches the contents of the named file. The file size must exactly match the +size of the ROM chip. + +The READ command will read out the entire flash ROM contents and write it to +the named file. + +FLASH4 will auto-detect most parameters so additional options should not +normally be required. + +The "/V" (verbose) option makes FLASH4 print one line per sector, giving a +detailed log of what it did. + +The "/P" or "/PARTIAL" option can be used if your ROM chip is larger than the +image you wish to write and you only want to reprogram part of it. To avoid +accidentally flashing the wrong file, the image file must be an exact multiple +of 32KB in length. The portion of the ROM not occupied by the image file is +left either unmodified or erased. + +The "/ROM" option can be used when you are using an ROM/EPROM/EEPROM chip which +cannot be programmed in-system and FLASH4 cannot recognise it. Only the "READ" +and "VERIFY" commands are supported with this option. This mode assumes a 512K +ROM is fitted, smaller ROMs will be treated as a 512KB ROM with the data +repeated multiple times. + +One of the following optional command line arguments may be specified at the +end of the command line to force FLASH4 to use a particular method to access +the flash ROM chip: + +BIOS interfaces: + /ROMWBW For ROMWBW BIOS version 2.6 and later + /ROMWBWOLD For ROMWBW BIOS version 2.5 and earlier + /UNABIOS For UNA BIOS + +Direct hardware interfaces: + /Z180DMA For Z180 DMA + /P112 For DX-Designs P112 + /N8VEMSBC For N8VEM SBC (v1, v2), Zeta (v1) SBC + +If no option is specified FLASH4 attempts to determine the best available +method automatically. + +If RomWBW 2.6+ is in use, and correctly configured, then multiple flash chips +can be detected automatically. Multiple chip operation can also be manually +enabled using the command line options "/1", "/2", "/3" etc up to "/9" to +specify the number of flash chips to program. All flash chips in the system +must be of the same type. + + += Supported flash memory chips = + +FLASH4 will interrogate your flash ROM chip to identify it automatically. + +FLASH4 does not support setting or resetting the protection bits on individual +sectors within Flash ROM devices. If your Flash ROM chip has protected sectors +you will need to unprotect them by other means before FLASH4 can erase and +reprogram them. + +AT29C series chips employ an optional "software data protection" feature. This +is supported by FLASH4 and is left activated after programming the chip to +prevent accidental reprogramming of sectors. + +The following chips are fully supported and will be programmed sector by +sector: + + AMIC A29010B + AMIC A29040B + Atmel AT29C010 + Atmel AT29C020 + Atmel AT29C040 + Atmel AT29C512 + Atmel AT29F010 + Atmel AT29F040 + Macronix MX29F040 + SST 39F010 + SST 39F020 + SST 39F040 + SST M29F010 + SST M29F040 + +The following chips are supported, but have unequal sector sizes, so FLASH4 +will only erase and reprogram the entire chip at once: + + Atmel AT49F001N + Atmel AT49F001NT + Atmel AT49F002N + Atmel AT49F002NT + Atmel AT49F040 + + += Compiling = + +The software is written in a mix of C and assembler. It builds using the SDCC +toolchain and the SRecord tools. SDCC 3.6 and 3.8 have been tested. A Makefile +is provided to build the executable in Linux and I imagine it can be easily +modified to build in Windows. + +You may need to adjust the path to the SDCC libraries in the Makefile if your +installation is not in /usr/local or /usr + + += License = + +FLASH4 is licensed under the The GNU General Public License version 3 (see +included "LICENSE.txt" file). + +FLASH4 is provided with NO WARRANTY. In no event will the author be liable for +any damages. Use of this program is at your own risk. May cause rifts in space +and time. + \ No newline at end of file diff --git a/Source/Images/Common/CPM22/KERCPM22.COM b/Source/Images/Common/CPM22/KERCPM22.COM index e4d91f7c..10ec899d 100644 Binary files a/Source/Images/Common/CPM22/KERCPM22.COM and b/Source/Images/Common/CPM22/KERCPM22.COM differ diff --git a/Source/Images/Common/CPM3/KERCPM3.COM b/Source/Images/Common/CPM3/KERCPM3.COM index 26d1b3fa..d66eaa10 100644 Binary files a/Source/Images/Common/CPM3/KERCPM3.COM and b/Source/Images/Common/CPM3/KERCPM3.COM differ diff --git a/Source/Images/Makefile b/Source/Images/Makefile index 3738e362..5e0410dc 100644 --- a/Source/Images/Makefile +++ b/Source/Images/Makefile @@ -3,36 +3,40 @@ # SYSTEMS = ../CPM22/cpm_wbw.sys ../ZSDOS/zsys_wbw.sys ../QPM/qpm_wbw.sys ../CPM3/cpmldr.sys ../ZPM3/zpmldr.sys -FDIMGS = fd144_cpm22.img fd144_zsdos.img fd144_nzcom.img \ - fd144_cpm3.img fd144_zpm3.img fd144_ws4.img fd144_qpm.img \ - fd144_z3plus.img \ - fd144_z80asm.img fd144_aztecc.img fd144_hitechc.img \ - fd144_bascomp.img fd144_fortran.img fd144_games.img \ - fd144_tpascal.img fd144_cowgol.img fd144_cobol.img -HD512IMGS = hd512_cpm22.img hd512_zsdos.img hd512_nzcom.img \ - hd512_cpm3.img hd512_zpm3.img hd512_ws4.img -HD512XIMGS = hd512_z80asm.img hd512_aztecc.img hd512_hitechc.img \ - hd512_bascomp.img hd512_fortran.img hd512_games.img \ - hd512_tpascal.img hd512_dos65.img hd512_qpm.img \ - hd512_z3plus.img \ - hd512_cowgol.img hd512_msxroms1.img hd512_msxroms2.img \ - hd512_cobol.img hd512_blank.img -HD1KIMGS = hd1k_cpm22.img hd1k_zsdos.img hd1k_nzcom.img \ - hd1k_cpm3.img hd1k_zpm3.img hd1k_ws4.img -HD1KXIMGS = hd1k_z80asm.img hd1k_aztecc.img hd1k_hitechc.img \ - hd1k_bascomp.img hd1k_fortran.img hd1k_games.img \ - hd1k_tpascal.img hd1k_qpm.img \ - hd1k_z3plus.img \ - hd1k_cowgol.img hd1k_msxroms1.img hd1k_msxroms2.img \ - hd1k_cobol.img hd1k_blank.img -HD1KXIMGS += hd1k_bp.img +# OBJECTS = HD512PREFIX = HD1KPREFIX = hd1k_prefix.dat -OBJECTS = $(FDIMGS) -OBJECTS += $(HD512IMGS) $(HD512XIMGS) hd512_combo.img $(HD512PREFIX) -OBJECTS += $(HD1KIMGS) $(HD1KXIMGS) hd1k_combo.img $(HD1KPREFIX) +# add base images used in *.def files + +FDIMGS = $(wildcard fd_*.txt) +FDIMGS := $(subst fd_,,$(FDIMGS)) +FDIMGS := $(addprefix fd144_,$(FDIMGS)) +FDIMGS := $(FDIMGS:.txt=.img) + +# $(info FDIMGS: $(FDIMGS)) + +HDIMGS = $(wildcard hd_*.txt) +HDIMGS := $(subst hd_,,$(HDIMGS)) +HDIMGS := $(addprefix hd512_,$(HDIMGS)) $(addprefix hd1k_,$(HDIMGS)) +HDIMGS := $(HDIMGS:.txt=.img) + +# $(info HDIMGS: $(HDIMGS)) + +BASEIMGS = $(shell grep -vEh "^\#" *.def) +BASEIMGS := $(addprefix hd512_,$(BASEIMGS)) $(addprefix hd1k_,$(BASEIMGS)) +BASEIMGS := $(addsuffix .img,$(BASEIMGS)) + +# $(info BASEIMGS: $(BASEIMGS)) + +DSKIMGS = $(wildcard *.def) +DSKIMGS := $(addprefix hd512_,$(DSKIMGS)) $(addprefix hd1k_,$(DSKIMGS)) +DSKIMGS := $(DSKIMGS:.def=.img) + +# $(info DSKIMGS: $(DSKIMGS)) + +OBJECTS = $(FDIMGS) $(HDIMGS) $(BASEIMGS) $(DSKIMGS) $(HD512PREFIX) $(HD1KPREFIX) OTHERS = blank144 blankhd512 blankhd1k *.cat @@ -41,17 +45,27 @@ NODELETE = $(HD512PREFIX) $(HD1KPREFIX) DEST=../../Binary TOOLS = ../../Tools + + +# $(info OBJECTS: $(OBJECTS)) + include $(TOOLS)/Makefile.inc .SHELLFLAGS = -ce DIFFPATH = $(DIFFTO)/Binary -hd512_combo.img: $(HD512PREFIX) $(HD512IMGS) - cat $^ > $@ +hd512_%.img: %.def + @echo "Generating hd512 disk image ""$@"" using $^"; \ + files=`grep -vEh "^\s*\#" $^ | grep -vEh "^\s*$$" | tr -d '\r' | awk '{print "hd512_" $$0 ".img"}'`; \ + echo " " $${files}; \ + cat $(HD512PREFIX) $${files} > $@ -hd1k_combo.img: $(HD1KPREFIX) $(HD1KIMGS) - cat $^ > $@ +hd1k_%.img: %.def + @echo "Generating hd1k disk image ""$@"" using $^"; \ + files=`grep -vEh "^\s*\#" $^ | grep -vEh "^\s*$$" | tr -d '\r' | awk '{print "hd1k_" $$0 ".img"}'`; \ + echo " " $${files}; \ + cat $(HD1KPREFIX) $${files} > $@ # # this somewhat impenetrable and fragile code is used to build each of the images @@ -82,16 +96,8 @@ blankhd1k: @LC_ALL=en_US.US-ASCII tr '\000' '\345' [] - -where: - - specifies the disk contents (e.g., "cpm22") - specifies disk type ("fd" for floppy, or "hd" for hard disk) - specifies the disk format which must be one of: - - "fd144": 1.44M floppy disk - - "hd512": hard disk with 512 directory entries - - "hd1k": hard disk with 1024 directory entries - optionally specifies a boot system image to place in the - system tracks of the disk (e.g., "..\cpm22\cpm_wbw.sys" - -For example: - - | BuildDisk.cmd cpm22 hd wbw_hd512 ..\cpm22\cpm_wbw.sys - -will create a hard disk image (512 directory entry format) with the -CP/M 2.2 files from the d_cpm22 directory tree and will place the -CP/M 2.2 system image in the boot system tracks. +"Build" to build all of the disk images including both hard disk +and floppy images. After completion of the script, the resultant image files are placed in the Binary directory with names such as fd144_xxx.img, hd512_xxx.img, and hd1k_xxx.img. -Sample output from running Build.cmd is provided at the end of -this file. - Be aware that the script always builds the image files from scratch. It will not update the previous contents. Any contents of a pre-existing image file will be overwritten. -Slices ------- +Hard Disk Slices +---------------- A RomWBW CP/M filesystem is fixed at 8MB. This is because it is the largest size filesystem supported by all common CP/M variants. Since @@ -142,7 +124,7 @@ to 256 of them) on a single physical hard disk and RomWBW will allow you to assign drive letters to them and treat them as multiple independent CP/M drives. -The disk image creation scripts in this directory will only create a +The disk image creation scripts in this directory will create a single CP/M file system (i.e., a single slice). However, you can easily create a multi-slice disk image by merely concatenating multiple images together (the 1024 directory entry format requires a @@ -159,6 +141,15 @@ have ZSDOS in the first slice and Wordstar in the second slice. The concept of slices applies only to hard disks. Floppy disks are not large enough to support multiple slices. +The build process will create aggregate hard disk images automatically +based on the .def files found in the directory. You will see a file +called combo.def which contains a list of the slices to concatenate +to create the hd512_combo.img and hd1k_combo.img files. You may +create your own .def files to define your own hard disk aggregates. +The build script will automatically find the .def files and build +aggregates for each. For each .def file, both hd512 and hd1k +format aggregates are created. + Hard Disk Formats ----------------- @@ -212,17 +203,17 @@ It provides double the directory space and places all slices inside of a hard disk partition that DOS/Windows should respect as "used" space. -Disk Images ------------ +Aggregate Hard Disk Images +-------------------------- The standard RomWBW build process builds the disk images defined in this directory. The resultant images are placed in the Binary directory and are ready to copy to your media. -Additionally, a "combo" disk image is created in both the hd512 and -hd1k formats that contains a multi-slice image that is handy to -use for initial testing. The combo disk image contains the following -slices: +Additionally, a "combo" aggregate disk image is created in both the +hd512 and hd1k formats that contains a multi-slice image that is handy +to use for initial testing. The combo disk image contains the +following slices: | Slice 0: CP/M 2.2 (bootable) | Slice 1: ZSDOS 1.1 (bootable) @@ -231,285 +222,14 @@ slices: | Slice 4: ZPM3 (bootable) | Slice 5: WordStar 4 -A description of the specific image files is found in the file -called DiskList.txt in the Binary directory of the distribution. +Aggregate disk images are defined using .def files. You will see there +is a combo.def file in the directory that defines the slices for the +Combo disk image. You can create your own .def files as desired to +automatically create custom aggregate disk images. There is an example +of this in the directory called all.def.example. You can remove the +".example" suffix to cause this aggregate to be built. This example +creates an aggregate with all of the possible slices. NOTE: The hd1k_combo.img file is already prefixed with hd1k_prefix.dat, so you do not need to add the prefix file. It is ready to write to your media. - -Sample Run ----------- - -Below is sample output from building the hard disk images: - -C:\Users\Wayne\Projects\RBC\Build\RomWBW\Source\Images>Build.cmd - - | Building Floppy Disk Images... - | - | Generating cpm22 1.44MB Floppy Disk... - | cpmcp -f wbw_fd144 fd144_cpm22.img d_cpm22/u0/*.* 0: - | cpmcp -f wbw_fd144 fd144_cpm22.img d_cpm22/u1/*.* 1: - | cpmcp -f wbw_fd144 fd144_cpm22.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_fd144 fd144_cpm22.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_fd144 fd144_cpm22.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_fd144 fd144_cpm22.img ../CPM22/cpm_wbw.sys 0:cpm.sys - | cpmcp -f wbw_fd144 fd144_cpm22.img Common/*.* 0: - | Moving image fd144_cpm22.img into output directory... - | Generating zsdos 1.44MB Floppy Disk... - | cpmcp -f wbw_fd144 fd144_zsdos.img d_zsdos/u0/*.* 0: - | cpmcp -f wbw_fd144 fd144_zsdos.img d_zsdos/u1/*.* 1: - | cpmcp -f wbw_fd144 fd144_zsdos.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_fd144 fd144_zsdos.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_fd144 fd144_zsdos.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_fd144 fd144_zsdos.img ../ZSDOS/zsys_wbw.sys 0:zsys.sys - | cpmcp -f wbw_fd144 fd144_zsdos.img Common/*.* 0: - | Moving image fd144_zsdos.img into output directory... - | Generating nzcom 1.44MB Floppy Disk... - | cpmcp -f wbw_fd144 fd144_nzcom.img d_nzcom/u0/*.* 0: - | cpmcp -f wbw_fd144 fd144_nzcom.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_fd144 fd144_nzcom.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_fd144 fd144_nzcom.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_fd144 fd144_nzcom.img ../CPM22/cpm_wbw.sys 0:cpm.sys - | cpmcp -f wbw_fd144 fd144_nzcom.img ../ZSDOS/zsys_wbw.sys 0:zsys.sys - | cpmcp -f wbw_fd144 fd144_nzcom.img Common/*.* 0: - | Moving image fd144_nzcom.img into output directory... - | Generating cpm3 1.44MB Floppy Disk... - | cpmcp -f wbw_fd144 fd144_cpm3.img d_cpm3/u0/*.* 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/cpmldr.com 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/cpmldr.sys 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/ccp.com 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/gencpm.com 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/genres.dat 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/genbnk.dat 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/bios3.spr 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/bnkbios3.spr 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/bdos3.spr 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/bnkbdos3.spr 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/resbdos3.spr 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/cpm3res.sys 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/cpm3bnk.sys 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/gencpm.dat 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/cpm3.sys 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/readme.1st 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../CPM3/cpm3fix.pat 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_fd144 fd144_cpm3.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_fd144 fd144_cpm3.img Common/*.* 0: - | Moving image fd144_cpm3.img into output directory... - | Generating zpm3 1.44MB Floppy Disk... - | cpmcp -f wbw_fd144 fd144_zpm3.img d_zpm3/u0/*.* 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img d_zpm3/u10/*.* 10: - | cpmcp -f wbw_fd144 fd144_zpm3.img d_zpm3/u14/*.* 14: - | cpmcp -f wbw_fd144 fd144_zpm3.img d_zpm3/u15/*.* 15: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/zpmldr.com 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/zpmldr.sys 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../CPM3/cpmldr.com 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../CPM3/cpmldr.sys 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/autotog.com 15: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/clrhist.com 15: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/setz3.com 15: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/cpm3.sys 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/zccp.com 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/zinstal.zpm 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/startzpm.com 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/makedos.com 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/gencpm.dat 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/bnkbios3.spr 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/bnkbdos3.spr 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../ZPM3/resbdos3.spr 0: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../../Binary/Apps/*.com 15: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_fd144 fd144_zpm3.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_fd144 fd144_zpm3.img Common/*.* 15: - | Moving image fd144_zpm3.img into output directory... - | Generating ws4 1.44MB Floppy Disk... - | cpmcp -f wbw_fd144 fd144_ws4.img d_ws4/u0/*.* 0: - | Moving image fd144_ws4.img into output directory... - | - | Building Hard Disk Images (512 directory entry format)... - | - | Generating cpm22 Hard Disk (512 directory entry format)... - | cpmcp -f wbw_hd512 hd512_cpm22.img d_cpm22/u0/*.* 0: - | cpmcp -f wbw_hd512 hd512_cpm22.img d_cpm22/u1/*.* 1: - | cpmcp -f wbw_hd512 hd512_cpm22.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd512 hd512_cpm22.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd512 hd512_cpm22.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd512 hd512_cpm22.img ../CPM22/cpm_wbw.sys 0:cpm.sys - | cpmcp -f wbw_hd512 hd512_cpm22.img Common/*.* 0: - | Moving image hd512_cpm22.img into output directory... - | Generating zsdos Hard Disk (512 directory entry format)... - | cpmcp -f wbw_hd512 hd512_zsdos.img d_zsdos/u0/*.* 0: - | cpmcp -f wbw_hd512 hd512_zsdos.img d_zsdos/u1/*.* 1: - | cpmcp -f wbw_hd512 hd512_zsdos.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd512 hd512_zsdos.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd512 hd512_zsdos.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd512 hd512_zsdos.img ../ZSDOS/zsys_wbw.sys 0:zsys.sys - | cpmcp -f wbw_hd512 hd512_zsdos.img Common/*.* 0: - | Moving image hd512_zsdos.img into output directory... - | Generating nzcom Hard Disk (512 directory entry format)... - | cpmcp -f wbw_hd512 hd512_nzcom.img d_nzcom/u0/*.* 0: - | cpmcp -f wbw_hd512 hd512_nzcom.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd512 hd512_nzcom.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd512 hd512_nzcom.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd512 hd512_nzcom.img ../CPM22/cpm_wbw.sys 0:cpm.sys - | cpmcp -f wbw_hd512 hd512_nzcom.img ../ZSDOS/zsys_wbw.sys 0:zsys.sys - | cpmcp -f wbw_hd512 hd512_nzcom.img Common/*.* 0: - | Moving image hd512_nzcom.img into output directory... - | Generating cpm3 Hard Disk (512 directory entry format)... - | cpmcp -f wbw_hd512 hd512_cpm3.img d_cpm3/u0/*.* 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/cpmldr.com 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/cpmldr.sys 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/ccp.com 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/gencpm.com 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/genres.dat 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/genbnk.dat 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/bios3.spr 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/bnkbios3.spr 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/bdos3.spr 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/bnkbdos3.spr 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/resbdos3.spr 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/cpm3res.sys 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/cpm3bnk.sys 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/gencpm.dat 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/cpm3.sys 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/readme.1st 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../CPM3/cpm3fix.pat 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd512 hd512_cpm3.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd512 hd512_cpm3.img Common/*.* 0: - | Moving image hd512_cpm3.img into output directory... - | Generating zpm3 Hard Disk (512 directory entry format)... - | cpmcp -f wbw_hd512 hd512_zpm3.img d_zpm3/u0/*.* 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img d_zpm3/u10/*.* 10: - | cpmcp -f wbw_hd512 hd512_zpm3.img d_zpm3/u14/*.* 14: - | cpmcp -f wbw_hd512 hd512_zpm3.img d_zpm3/u15/*.* 15: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/zpmldr.com 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/zpmldr.sys 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../CPM3/cpmldr.com 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../CPM3/cpmldr.sys 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/autotog.com 15: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/clrhist.com 15: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/setz3.com 15: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/cpm3.sys 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/zccp.com 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/zinstal.zpm 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/startzpm.com 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/makedos.com 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/gencpm.dat 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/bnkbios3.spr 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/bnkbdos3.spr 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../ZPM3/resbdos3.spr 0: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../../Binary/Apps/*.com 15: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd512 hd512_zpm3.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd512 hd512_zpm3.img Common/*.* 15: - | Moving image hd512_zpm3.img into output directory... - | Generating ws4 Hard Disk (512 directory entry format)... - | cpmcp -f wbw_hd512 hd512_ws4.img d_ws4/u0/*.* 0: - | Moving image hd512_ws4.img into output directory... - | - | Building Combo Disk (512 directory entry format) Image... - | ..\..\Binary\hd512_cpm22.img - | ..\..\Binary\hd512_zsdos.img - | ..\..\Binary\hd512_nzcom.img - | ..\..\Binary\hd512_cpm3.img - | ..\..\Binary\hd512_zpm3.img - | ..\..\Binary\hd512_ws4.img - | 1 file(s) copied. - | - | Building Hard Disk Images (1024 directory entry format)... - | - | Generating cpm22 Hard Disk (1024 directory entry format)... - | cpmcp -f wbw_hd1k hd1k_cpm22.img d_cpm22/u0/*.* 0: - | cpmcp -f wbw_hd1k hd1k_cpm22.img d_cpm22/u1/*.* 1: - | cpmcp -f wbw_hd1k hd1k_cpm22.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd1k hd1k_cpm22.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd1k hd1k_cpm22.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd1k hd1k_cpm22.img ../CPM22/cpm_wbw.sys 0:cpm.sys - | cpmcp -f wbw_hd1k hd1k_cpm22.img Common/*.* 0: - | Moving image hd1k_cpm22.img into output directory... - | Generating zsdos Hard Disk (1024 directory entry format)... - | cpmcp -f wbw_hd1k hd1k_zsdos.img d_zsdos/u0/*.* 0: - | cpmcp -f wbw_hd1k hd1k_zsdos.img d_zsdos/u1/*.* 1: - | cpmcp -f wbw_hd1k hd1k_zsdos.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd1k hd1k_zsdos.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd1k hd1k_zsdos.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd1k hd1k_zsdos.img ../ZSDOS/zsys_wbw.sys 0:zsys.sys - | cpmcp -f wbw_hd1k hd1k_zsdos.img Common/*.* 0: - | Moving image hd1k_zsdos.img into output directory... - | Generating nzcom Hard Disk (1024 directory entry format)... - | cpmcp -f wbw_hd1k hd1k_nzcom.img d_nzcom/u0/*.* 0: - | cpmcp -f wbw_hd1k hd1k_nzcom.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd1k hd1k_nzcom.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd1k hd1k_nzcom.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd1k hd1k_nzcom.img ../CPM22/cpm_wbw.sys 0:cpm.sys - | cpmcp -f wbw_hd1k hd1k_nzcom.img ../ZSDOS/zsys_wbw.sys 0:zsys.sys - | cpmcp -f wbw_hd1k hd1k_nzcom.img Common/*.* 0: - | Moving image hd1k_nzcom.img into output directory... - | Generating cpm3 Hard Disk (1024 directory entry format)... - | cpmcp -f wbw_hd1k hd1k_cpm3.img d_cpm3/u0/*.* 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/cpmldr.com 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/cpmldr.sys 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/ccp.com 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/gencpm.com 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/genres.dat 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/genbnk.dat 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/bios3.spr 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/bnkbios3.spr 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/bdos3.spr 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/bnkbdos3.spr 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/resbdos3.spr 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/cpm3res.sys 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/cpm3bnk.sys 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/gencpm.dat 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/cpm3.sys 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/readme.1st 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../CPM3/cpm3fix.pat 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../../Binary/Apps/*.com 0: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd1k hd1k_cpm3.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd1k hd1k_cpm3.img Common/*.* 0: - | Moving image hd1k_cpm3.img into output directory... - | Generating zpm3 Hard Disk (1024 directory entry format)... - | cpmcp -f wbw_hd1k hd1k_zpm3.img d_zpm3/u0/*.* 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img d_zpm3/u10/*.* 10: - | cpmcp -f wbw_hd1k hd1k_zpm3.img d_zpm3/u14/*.* 14: - | cpmcp -f wbw_hd1k hd1k_zpm3.img d_zpm3/u15/*.* 15: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/zpmldr.com 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/zpmldr.sys 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../CPM3/cpmldr.com 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../CPM3/cpmldr.sys 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/autotog.com 15: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/clrhist.com 15: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/setz3.com 15: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/cpm3.sys 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/zccp.com 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/zinstal.zpm 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/startzpm.com 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/makedos.com 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/gencpm.dat 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/bnkbios3.spr 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/bnkbdos3.spr 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../ZPM3/resbdos3.spr 0: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../../Binary/Apps/*.com 15: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../../Binary/Apps/Tunes/*.pt? 3: - | cpmcp -f wbw_hd1k hd1k_zpm3.img ../../Binary/Apps/Tunes/*.mym 3: - | cpmcp -f wbw_hd1k hd1k_zpm3.img Common/*.* 15: - | Moving image hd1k_zpm3.img into output directory... - | Generating ws4 Hard Disk (1024 directory entry format)... - | cpmcp -f wbw_hd1k hd1k_ws4.img d_ws4/u0/*.* 0: - | Moving image hd1k_ws4.img into output directory... - | 1 file(s) copied. - | - | Building Combo Disk (1024 directory entry format) Image... - | hd1k_prefix.dat - | ..\..\Binary\hd1k_cpm22.img - | ..\..\Binary\hd1k_zsdos.img - | ..\..\Binary\hd1k_nzcom.img - | ..\..\Binary\hd1k_cpm3.img - | ..\..\Binary\hd1k_zpm3.img - | ..\..\Binary\hd1k_ws4.img - | 1 file(s) copied. diff --git a/Source/Images/all.def.example b/Source/Images/all.def.example new file mode 100644 index 00000000..2caed21b --- /dev/null +++ b/Source/Images/all.def.example @@ -0,0 +1,25 @@ +# This image definition shows how to generate +# an disk image containing all of the available +# slices. + +aztecc +bascomp +blank +cobol +cowgol +cpm22 +cpm3 +fortran +games +hitechc +infocom +msxroms1 +msxroms2 +nzcom +qpm +tpascal +ws4 +z3plus +z80asm +zpm3 +zsdos diff --git a/Source/Images/combo.def b/Source/Images/combo.def new file mode 100644 index 00000000..2dc41f15 --- /dev/null +++ b/Source/Images/combo.def @@ -0,0 +1,8 @@ +# This is the ubiquituous Combo image for RomWBW + +cpm22 +zsdos +nzcom +cpm3 +zpm3 +ws4 diff --git a/Source/Images/d_cowgol/u0/CGEN.COM b/Source/Images/d_cowgol/u0/CGEN.COM index 3604a64b..aecb7a85 100644 Binary files a/Source/Images/d_cowgol/u0/CGEN.COM and b/Source/Images/d_cowgol/u0/CGEN.COM differ diff --git a/Source/Images/d_cowgol/u0/CPP.COM b/Source/Images/d_cowgol/u0/CPP.COM index 2709d54c..cb1d70f2 100644 Binary files a/Source/Images/d_cowgol/u0/CPP.COM and b/Source/Images/d_cowgol/u0/CPP.COM differ diff --git a/Source/Images/d_cowgol/u0/HEXDUMP.COM b/Source/Images/d_cowgol/u0/HEXDUMP.COM deleted file mode 100644 index 1bf04abe..00000000 Binary files a/Source/Images/d_cowgol/u0/HEXDUMP.COM and /dev/null differ diff --git a/Source/Images/d_cowgol/u0/OPTIM.COM b/Source/Images/d_cowgol/u0/OPTIM.COM index 238dc8a5..6e152dae 100644 Binary files a/Source/Images/d_cowgol/u0/OPTIM.COM and b/Source/Images/d_cowgol/u0/OPTIM.COM differ diff --git a/Source/Images/d_cowgol/u0/P1.COM b/Source/Images/d_cowgol/u0/P1.COM index cbb1f3e9..314842c3 100644 Binary files a/Source/Images/d_cowgol/u0/P1.COM and b/Source/Images/d_cowgol/u0/P1.COM differ diff --git a/Source/Images/d_games/Readme.txt b/Source/Images/d_games/Readme.txt index 1a7de748..1ca1cbf8 100644 --- a/Source/Images/d_games/Readme.txt +++ b/Source/Images/d_games/Readme.txt @@ -2,6 +2,8 @@ This disk contains several games for CP/M including the Infocom games Zork 1 through 3, Planetfall and Hitchhiker's Guide to the Galaxy. +A complete collection of all infocom games is available on the separate +INFOCOM disk image Nemesis and Dungeon Master is a Rogue-like game released in 1981. It is playable on a text terminal using ASCII graphics to represent the dungeon. Only a few diff --git a/Source/Images/d_hitechc/Readme.txt b/Source/Images/d_hitechc/Readme.txt index 671c532d..2fd60e7f 100644 --- a/Source/Images/d_hitechc/Readme.txt +++ b/Source/Images/d_hitechc/Readme.txt @@ -1,20 +1,20 @@ ===== HI-TECH Z80 CP/M C compiler V3.09-17 ===== -The HI-TECH C Compiler is a set of software which -translates programs written in the C language to executable -machine code programs. Versions are available which compile -programs for operation under the host operating system, or -which produce programs for execution in embedded systems +The HI-TECH C Compiler is a set of software which +translates programs written in the C language to executable +machine code programs. Versions are available which compile +programs for operation under the host operating system, or +which produce programs for execution in embedded systems without an operating system. -This is the Mar 21, 2023 update 17 released by Tony Nicholson who currently -maintains HI-TECH C at https://github.com/agn453/HI-TECH-Z80-C +This is the Jun 2, 2025 update 19 released by Tony Nicholson who currently +maintains HI-TECH C at https://github.com/agn453/HI-TECH-Z80-C. The manual is available in the Doc/Language directory, -HI-TECH Z80 C Compiler Manual.txt +HI-TECH Z80 C Compiler Manual.txt. A good blog post about the HI-TECH C Compiler is available at -https://techtinkering.com/2008/10/22/installing-the-hi-tech-z80-c-compiler-for-cpm/ +https://techtinkering.com/2008/10/22/installing-the-hi-tech-z80-c-compiler-for-cpm/. == License == @@ -24,3 +24,30 @@ support is offered or implied. You may use this software for whatever you like, providing you acknowledge that the copyright to this software remains with HI-TECH Software. + +== Enhanced Version == + +User area 1 contains another complete copy of the HI-TECH C Compiler. +It is identical to the copy in user area 0 except for the following files +which were enhanced by Ladislau Szilagyi from his GitHub Repository at +https://github.com/Laci1953/HiTech-C-compiler-enhanced. The files +take advantage of additional banked memory using the RomWBW HBIOS API. +As such, they require RomWBW to operate. They should be compatible with +all CP/M and compatible operating systems provided in RomWBW. + +The enhanced files are: + +- CGEN.COM +- CPP.COM +- OPTIM.COM +- P1.COM +- ZAS.COM + +A thread discussing this enhanced version of HI-TECH C is found at +https://groups.google.com/g/rc2014-z80/c/sBCCIpOnnGg. + +One of the size optimizations of P1.COM is the removal of the textual +warning and error messages. The code number for each of these +messages will still be printed. The textual description for all of +these warnings/errors can be found in the Doc/Language directory, +HI-TECH Z80 C Compiler Messages.txt. diff --git a/Source/Images/d_hitechc/u0/C.COM b/Source/Images/d_hitechc/u0/C.COM index 5c48dd02..121b0aa2 100644 Binary files a/Source/Images/d_hitechc/u0/C.COM and b/Source/Images/d_hitechc/u0/C.COM differ diff --git a/Source/Images/d_hitechc/u0/LIBC.LIB b/Source/Images/d_hitechc/u0/LIBC.LIB index f31ad7bc..26840dc1 100644 Binary files a/Source/Images/d_hitechc/u0/LIBC.LIB and b/Source/Images/d_hitechc/u0/LIBC.LIB differ diff --git a/Source/Images/d_hitechc/u0/LIBF.LIB b/Source/Images/d_hitechc/u0/LIBF.LIB index 328f068f..b368e9c8 100644 Binary files a/Source/Images/d_hitechc/u0/LIBF.LIB and b/Source/Images/d_hitechc/u0/LIBF.LIB differ diff --git a/Source/Images/d_hitechc/u0/STDIO.H b/Source/Images/d_hitechc/u0/STDIO.H index 0475b896..4f4c581b 100644 --- a/Source/Images/d_hitechc/u0/STDIO.H +++ b/Source/Images/d_hitechc/u0/STDIO.H @@ -2,8 +2,17 @@ #define _HTC_STDIO_H /* - * STDIO.H Modified version from Tesseract vol 91 + * STDIO.H HI-TECH C standard I/O for V3.09-xx + * + * This version incorporates changes to stdio routines + * resulting from backporting features from V4.11 */ + +#define _HTC_VERSION "3.09-19" +#define _HTC_MAJOR 3 +#define _HTC_MINOR 9 +#define _HTC_REV 19 + #if z80 #define BUFSIZ 512 #define _NFILE 8 @@ -12,18 +21,27 @@ #define _NFILE 20 #endif z80 +#ifndef _STDDEF +typedef int ptrdiff_t; +typedef unsigned size_t; +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif _STDDEF + #ifndef FILE -#define uchar unsigned char +#define uchar unsigned char extern struct _iobuf { - char *_ptr; - int _cnt; - char *_base; - unsigned short _flag; - char _file; + char *_ptr; + int _cnt; + char *_base; + unsigned short _flag; + char _file; + size_t _size; } _iob[_NFILE]; +#define FILE struct _iobuf #endif FILE #ifndef SEEK_SET @@ -32,25 +50,26 @@ extern struct _iobuf #define SEEK_END 2 #endif -#define _IOREAD 01 -#define _IOWRT 02 -#define _IORW 03 -#define _IONBF 04 -#define _IOMYBUF 010 -#define _IOEOF 020 -#define _IOERR 040 -#define _IOSTRG 0100 -#define _IOBINARY 0200 - /* New flags */ -#define _IODIRN 01000 /* Set if writing to a R/W file */ -#define _IOAPPEND 02000 /* Set if in append mode */ -#define _IOWROTE 04000 /* Write occurred since last seek */ +/* I/O status flag word bits */ +#define _IOREAD 01 /* Allow file reading */ +#define _IOWRT 02 /* Allow file writing */ +#define _IORW 03 /* Mask for reading or writing */ +#define _IONBF 04 /* Not being buffered */ +#define _IOMYBUF 010 /* Using buffer */ +#define _IOEOF 020 /* At end-of-file */ +#define _IOERR 040 /* An I/O error has occurred */ +#define _IOSTRG 0100 /* End of string reached */ +#define _IOBINARY 0200 /* Binary mode */ +#define _IOLBF 0400 /* Using line buffering */ +#define _IODIRN 01000 /* Direction - writing to a R/W file */ +#define _IOAPPEND 02000 /* Append mode */ +#define _IOSEEKED 04000 /* A seek has occurred since last write */ +#define _IOFBF 010000 /* Using full buffering */ #ifndef NULL #define NULL ((void *)0) #endif NULL -#define FILE struct _iobuf #define EOF (-1) #define stdin (&_iob[0]) @@ -79,9 +98,6 @@ extern struct _iobuf #define clrerr(p) p->_flag &= ~_IOERR #define clreof(p) p->_flag &= ~_IOEOF -#define L_tmpnam 34 /* max length of temporary names */ -#define L_TMPNAM (L_tmpnam) /* max length of temporary names */ - extern int fclose(FILE *); extern int fflush(FILE *); extern int fgetc(FILE *); @@ -96,7 +112,8 @@ extern int fread(void *, unsigned, unsigned, FILE *); extern int fwrite(void *, unsigned, unsigned, FILE *); extern int fseek(FILE *, long, int); extern int rewind(FILE *); -extern int setbuf(FILE *, char *); +extern void setbuf(FILE *, char *); +extern int setvbuf(FILE *, char *, int, size_t); extern int printf(char *, ...); extern int fprintf(FILE *, char *, ...); extern int sprintf(char *, char *, ...); @@ -111,5 +128,5 @@ extern long ftell(FILE *); extern char *fgets(char *, int, FILE *); extern char *_bufallo(void); -#endif - \ No newline at end of file +#endif _HTC_STDIO_H + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u0/SYS.H b/Source/Images/d_hitechc/u0/SYS.H index 36d16de5..5f8a4b9e 100644 --- a/Source/Images/d_hitechc/u0/SYS.H +++ b/Source/Images/d_hitechc/u0/SYS.H @@ -34,6 +34,7 @@ extern char **_getargs(char *, char *); extern int _argc_; extern int inp(int); extern void outp(int, int); +extern void * sbrk(size_t); #endif - \ No newline at end of file + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/$EXEC.COM b/Source/Images/d_hitechc/u1/$EXEC.COM new file mode 100644 index 00000000..a6ae8f51 Binary files /dev/null and b/Source/Images/d_hitechc/u1/$EXEC.COM differ diff --git a/Source/Images/d_hitechc/u1/ASSERT.H b/Source/Images/d_hitechc/u1/ASSERT.H new file mode 100644 index 00000000..b07e103d --- /dev/null +++ b/Source/Images/d_hitechc/u1/ASSERT.H @@ -0,0 +1,23 @@ +#ifndef _HTC_ASSERT_H +#define _HTC_ASSERT_H + +/* + * Assertion - use liberally for debugging. Defining NDEBUG + * turns assertions off. + * assert(exp) where exp is non-zero does nothing, while + * assert(exp) where exp evaluates to zero aborts the program + * with a message like + * + * Assertion failed: prog.c line 123: "exp" + * + */ + +#ifndef NDEBUG +extern void _fassert(int, char *, char *); +#define assert(exp) if(!(exp)) {_fassert(__LINE__, __FILE__, "exp");} +#else +#define assert(exp) +#endif + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/C.COM b/Source/Images/d_hitechc/u1/C.COM new file mode 100644 index 00000000..121b0aa2 Binary files /dev/null and b/Source/Images/d_hitechc/u1/C.COM differ diff --git a/Source/Images/d_hitechc/u1/C309.COM b/Source/Images/d_hitechc/u1/C309.COM new file mode 100644 index 00000000..deaa1b67 Binary files /dev/null and b/Source/Images/d_hitechc/u1/C309.COM differ diff --git a/Source/Images/d_hitechc/u1/CGEN.COM b/Source/Images/d_hitechc/u1/CGEN.COM new file mode 100644 index 00000000..aecb7a85 Binary files /dev/null and b/Source/Images/d_hitechc/u1/CGEN.COM differ diff --git a/Source/Images/d_hitechc/u1/CONIO.H b/Source/Images/d_hitechc/u1/CONIO.H new file mode 100644 index 00000000..d7b60408 --- /dev/null +++ b/Source/Images/d_hitechc/u1/CONIO.H @@ -0,0 +1,30 @@ +#ifndef _HTC_CONIO_H +#define _HTC_CONIO_H + +/* + * Low-level console I/O functions + */ + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif _STDDEF + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +extern int errno; /* system error number */ + +extern char getch(void); +extern char getche(void); +extern void putch(int); +extern void ungetch(int); +extern int kbhit(void); +extern char * cgets(char *); +extern void cputs(char *); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/CPM.H b/Source/Images/d_hitechc/u1/CPM.H new file mode 100644 index 00000000..499d8f62 --- /dev/null +++ b/Source/Images/d_hitechc/u1/CPM.H @@ -0,0 +1,215 @@ +#ifndef _HTC_CPM_H +#define _HTC_CPM_H + +/* Header file for CP/M routines for Z-80 C */ + +/* get basic definitions */ + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ +#define _STDDEF + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +extern int errno; /* system error number */ +#endif _STDDEF + +/* hitech.h has definitions for uchar, ushort etc */ + +#include +#if z80 +#define MAXFILE 8 /* max number of files open */ +#else z80 +#define MAXFILE 15 /* max number of files open */ +#endif z80 +#define SECSIZE 128 /* no. of bytes per sector */ + +extern struct fcb +{ + uchar dr; /* 0: drive code */ + char name[8]; /* 1: file name */ + char ft[3]; /* 9: file type */ + uchar ex; /* 12: file extent */ + char fil[2]; /* 13: not used */ + char rc; /* 15: number of records in present extent */ + char dm[16]; /* 16: CP/M disk map */ + char nr; /* 32: next record to read or write */ + uchar ranrec[3]; /* 35: random record number (24 bit no.) */ + long rwp; /* 38: read/write pointer in bytes */ + uchar use; /* 42: use flag */ + uchar uid; /* 43: user id belonging to this file */ + long fsize; /* 44: file length in bytes */ +} _fcb[MAXFILE]; + +extern short bdos(int, ...); +#define bdoshl bdos +#define bdose bdos +extern struct fcb* getfcb(void); +extern char * fcbname(short i); +extern short getuid(void); +extern short setuid(short); +extern uchar setfcb(struct fcb *, char *); +extern char * (*_passwd)(struct fcb *); +extern short bios(short fn, ...); +#define bios3 bios + +/* flag values in fcb use */ + +#define U_READ 1 /* file open for reading */ +#define U_WRITE 2 /* file open for writing */ +#define U_RDWR 3 /* open for read and write */ +#define U_CON 4 /* device is console */ +#define U_RDR 5 /* device is reader */ +#define U_PUN 6 /* device is punch */ +#define U_LST 7 /* list device */ +#define U_RSX 8 /* PIPEMGR RSX */ +#define U_ERR 9 /* PIPEMGR stderr channel */ + +/* special character values */ + +#define CPMETX 032 /* ctrl-Z, CP/M end of file for text */ +#define CPMRBT 003 /* ctrl-C, reboot CPM */ + +/* operating systems */ + +#define MPM 0x100 /* bit to test for MP/M */ +#define CCPM 0x400 /* bit to test for CCP/M */ + +#define ISMPM() (bdoshl(CPMVERS)&MPM) /* macro to test for MPM */ + +/* what to do after you hit return */ + +#define EXIT (*(int (*)())0) /* where to go to reboot CP/M */ + +/* BDOS calls etc. */ + +#define CPMRCON 1 /* read console */ +#define CPMWCON 2 /* write console */ +#define CPMRRDR 3 /* read reader */ +#define CPMWPUN 4 /* write punch */ +#define CPMWLST 5 /* write list */ +#define CPMDCIO 6 /* direct console I/O */ +#define CPMGIOB 7 /* get I/O byte */ +#define CPMSIOB 8 /* set I/O byte */ +#define CPMWCOB 9 /* write console buffered */ +#define CPMRCOB 10 /* read console buffered */ +#define CPMICON 11 /* interrogate console ready */ +#define CPMVERS 12 /* return version number */ +#define CPMRDS 13 /* reset disk system */ +#define CPMLGIN 14 /* log in and select disk */ +#define CPMOPN 15 /* open file */ +#define CPMCLS 16 /* close file */ +#define CPMFFST 17 /* find first */ +#define CPMFNXT 18 /* find next */ +#define CPMDEL 19 /* delete file */ +#define CPMREAD 20 /* read next record */ +#define CPMWRIT 21 /* write next record */ +#define CPMMAKE 22 /* create file */ +#define CPMREN 23 /* rename file */ +#define CPMILOG 24 /* get bit map of logged in disks */ +#define CPMIDRV 25 /* interrogate drive number */ +#define CPMSDMA 26 /* set DMA address for i/o */ +#define CPMGALL 27 /* get allocation vector address */ +#define CPMWPRD 28 /* write protect disk */ +#define CPMGROV 29 /* get read-only vector */ +#define CPMSATT 30 /* set file attributes */ +#define CPMDPB 31 /* get disk parameter block */ +#define CPMSUID 32 /* set/get user id */ +#define CPMRRAN 33 /* read random record */ +#define CPMWRAN 34 /* write random record */ +#define CPMCFS 35 /* compute file size */ +#define CPMSRAN 36 /* set random record */ +#define CPMRDRV 37 /* reset drive */ +#define CPMACDV 38 /* MP/M access drive */ +#define CPMFRDV 39 /* MP/M free drive */ +#define CPMWRZF 40 /* write random with zero fill */ +#define CPMTWR 41 /* MP/M test and write record */ +#define CPMLOKR 42 /* MP/M lock record */ +#define CPMUNLR 43 /* MP/M unlock record */ +#define CPMSMSC 44 /* CP/M+ set multi-sector count */ +#define CPMERRM 45 /* CP/M+ set BDOS error mode */ +#define CPMDFS 46 /* CP/M+ get disk free space */ +#define CPMCHN 47 /* CP/M+ chain to program */ +#define CPMFLSH 48 /* CP/M+ flush buffers */ +#define CPMGZSD 48 /* ZSDOS get ZSDOS/ZDDOS version */ +#define CPMSCB 49 /* access CP/M+ system control block */ +#define CPMBIOS 50 /* CP/M+ direct BIOS call */ +#define CPMDSEG 51 /* set DMA segment */ +#define CPMGFTM 54 /* Z80DOS/ZPM3 get file time-stamp */ +#define CPMSFTM 55 /* Z80DOS/ZPM3 set file time-stamp */ +#define CPMLDOV 59 /* CP/M+ Load Overlay - requires LOADER RSX */ +#define CPMRSX 60 /* CP/M+ call RSX */ +#define CPMLGI 64 /* CP/Net login */ +#define CPMLGO 65 /* CP/Net logout */ +#define CPMSMSG 66 /* CP/Net send message */ +#define CPMRMSG 67 /* CP/Net receive message */ +#define CPMNETS 68 /* CP/Net get network status */ +#define CPMGCFT 69 /* CP/Net get configuration table address */ +#define CPMSCAT 70 /* CP/Net set compatibility attributes */ +#define CPMGSVC 71 /* CP/Net get server configuration */ +#define CPMFRBL 98 /* CP/M+ free blocks */ +#define CPMTRNC 99 /* CP/M+ truncate file */ +#define CPMSLBL 100 /* CP/M+ set directory label */ +#define CPMDLD 101 /* CP/M+ get directory label data */ +#define CPMGFTS 102 /* CP/M+ get file timestamp and password mode */ +#define CPMWXFC 103 /* CP/M+ write file XFCB */ +#define CPMSDAT 104 /* CP/M+ set date and time */ +#define CPMGDAT 105 /* CP/M+ get date and time */ +#define CPMSPWD 106 /* CP/M+ set default password */ +#define CPMGSER 107 /* CP/M+ get serial number */ +#define CPMRCOD 108 /* CP/M+ get/set return code */ +#define CPMCMOD 109 /* CP/M+ get/set console mode */ +#define CPMODEL 110 /* CP/M+ get/set output delimiter */ +#define CPMPBLK 111 /* CP/M+ print block */ +#define CPMLBLK 112 /* CP/M+ list block */ +#define CPMPARS 152 /* CP/M+ parse filename */ + +/* CP/M BIOS functions. Numbers above 16 pertain to CP/M 3 only. */ + +enum BIOSfns +{ + _BOOT = 0, + _WBOOT = 1, + + _CONST = 2, + _CONIN = 3, + _CONOUT = 4, + _LIST = 5, + _PUNOUT = 6, /* CP/M 2.2 name */ + _AUXOUT = 6, /* CP/M 3.1 name */ + _RDRIN = 7, /* CP/M 2.2 name */ + _AUXIN = 7, /* CP/M 3.1 name */ + _LISTST = 15, + _CONOST = 17, + _AUXIST = 18, + _AUXOST = 19, + + _DEVTBL = 20, + _DEVINI = 21, + _DRVTBL = 22, + + _HOME = 8, + _SELDSK = 9, + _SETTRK = 10, + _SETSEC = 11, + _SETDMA = 12, + _READ = 13, + _WRITE = 14, + _SECTRN = 16, + _MULTIO = 23, + _FLUSH = 24, + + _MOVE = 25, + _SELMEM = 27, + _SETBNK = 28, + _XMOVE = 29, + + _TIME = 26, + _USERF = 30 +}; + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/CPP.COM b/Source/Images/d_hitechc/u1/CPP.COM new file mode 100644 index 00000000..cb1d70f2 Binary files /dev/null and b/Source/Images/d_hitechc/u1/CPP.COM differ diff --git a/Source/Images/d_hitechc/u1/CREF.COM b/Source/Images/d_hitechc/u1/CREF.COM new file mode 100644 index 00000000..d20a44db Binary files /dev/null and b/Source/Images/d_hitechc/u1/CREF.COM differ diff --git a/Source/Images/d_hitechc/u1/CRTCPM.OBJ b/Source/Images/d_hitechc/u1/CRTCPM.OBJ new file mode 100644 index 00000000..6f4ae8f0 Binary files /dev/null and b/Source/Images/d_hitechc/u1/CRTCPM.OBJ differ diff --git a/Source/Images/d_hitechc/u1/CTYPE.H b/Source/Images/d_hitechc/u1/CTYPE.H new file mode 100644 index 00000000..f6512e56 --- /dev/null +++ b/Source/Images/d_hitechc/u1/CTYPE.H @@ -0,0 +1,41 @@ +#ifndef _HTC_CTYPE_H +#define _HTC_CTYPE_H + +#define _U 0x01 +#define _L 0x02 +#define _N 0x04 +#define _S 0x08 +#define _P 0x10 +#define _C 0x20 +#define _X 0x40 + +extern unsigned char _ctype_[]; /* in libc.lib */ + +#define isalpha(c) ((_ctype_+1)[c]&(_U|_L)) +#define isupper(c) ((_ctype_+1)[c]&_U) +#define islower(c) ((_ctype_+1)[c]&_L) +#define isdigit(c) ((_ctype_+1)[c]&_N) +#define isxdigit(c) ((_ctype_+1)[c]&(_N|_X)) +#define isspace(c) ((_ctype_+1)[c]&_S) +#define ispunct(c) ((_ctype_+1)[c]&_P) +#define isalnum(c) ((_ctype_+1)[c]&(_U|_L|_N)) +#define isprint(c) ((_ctype_+1)[c]&(_P|_U|_L|_N|_S)) +#define isgraph(c) ((_ctype_+1)[c]&(_P|_U|_L|_N)) +#define iscntrl(c) ((_ctype_+1)[c]&_C) +#define isascii(c) (!((c)&0xFF80)) +/*--------------------------------------*\ + | Changed 2014-07-04 (Jon Saxton) | + |--------------------------------------| + | Original macro definitions | + | #define toupper(c) ((c)-'a'+'A') | + | #define tolower(c) ((c)-'A'+'a') | + |--------------------------------------| + | Use functions instead | +\*--------------------------------------*/ +extern int toupper(int); /* in LIBC.LIB */ +extern int tolower(int); /* in LIBC.LIB */ + +#define toascii(c) ((c)&0x7F) + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/DEBUG.COM b/Source/Images/d_hitechc/u1/DEBUG.COM new file mode 100644 index 00000000..299a60de Binary files /dev/null and b/Source/Images/d_hitechc/u1/DEBUG.COM differ diff --git a/Source/Images/d_hitechc/u1/DRTCPM.OBJ b/Source/Images/d_hitechc/u1/DRTCPM.OBJ new file mode 100644 index 00000000..b1006d79 Binary files /dev/null and b/Source/Images/d_hitechc/u1/DRTCPM.OBJ differ diff --git a/Source/Images/d_hitechc/u1/EXEC.H b/Source/Images/d_hitechc/u1/EXEC.H new file mode 100644 index 00000000..b9f1fca9 --- /dev/null +++ b/Source/Images/d_hitechc/u1/EXEC.H @@ -0,0 +1,22 @@ +#ifndef _HTC_EXEC_H +#define _HTC_EXEC_H + +/* + * Definitions of the EXEC format + */ + +#define EXITIT 0x80 +#define EXEC 0x81 +#define IGN_ERR 0x82 +#define DEF_ERR 0x83 +#define SKP_ERR 0x84 +#define TRAP 0x85 +#define IF_ERR 0x86 +#define IF_NERR 0x87 +#define ECHO 0x88 +#define PRINT 0x89 +#define RM_FILE 0x8A +#define RM_EXIT 0x8B + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/FLOAT.H b/Source/Images/d_hitechc/u1/FLOAT.H new file mode 100644 index 00000000..d1db206a --- /dev/null +++ b/Source/Images/d_hitechc/u1/FLOAT.H @@ -0,0 +1,73 @@ +#ifndef _HTC_FLOAT_H +#define _HTC_FLOAT_H + +/* Characteristics of floating types */ + +#define DBL_RADIX 2 /* radix of exponent for a double */ +#define DBL_ROUNDS 1 /* doubles round when converted to int */ +#define FLT_RADIX 2 /* radix of float exponent */ +#define FLT_ROUNDS 1 /* float also rounds to int */ + +#if z80 +#define FLT_MANT_DIG 24 /* 24 bits in mantissa */ +#define DBL_MANT_DIG 24 /* ditto for double */ +#define DBL_MANT_DIG 24 /* ditto long double */ +#define FLT_EPSILON -1.192093 /* smallest x, x+1.0 != 1.0 */ +#define DBL_EPSILON -1.192093 /* smallest x, x+1.0 != 1.0 */ +#define FLT_DIG 6 /* decimal significant digs */ +#define DBL_DIG 6 +#define FLT_MIN_EXP -62 /* min binary exponent */ +#define DBL_MIN_EXP -62 +#define FLT_MIN 1.084202e-19 /* smallest floating number */ +#define DBL_MIN 1.084202e-19 +#define FLT_MIN_10_EXP -18 +#define DBL_MIN_10_EXP -18 +#define FLT_MAX_EXP 64 /* max binary exponent */ +#define DBL_MAX_EXP 64 +#define FLT_MAX 1.84467e19 /* max floating number */ +#define DBL_MAX 1.84467e19 +#define FLT_MAX_10_EXP 19 /* max decimal exponent */ +#define DBL_MAX_10_EXP 19 +#endif z80 + +#if i8086 || m68k + +/* The 8086 and 68000 use IEEE 32 and 64 bit floats */ + +#define FLT_RADIX 2 +#define FLT_MANT_DIG 24 +#define FLT_EPSILON 1.19209290e-07 +#define FLT_DIG 6 +#define FLT_MIN_EXP -125 +#define FLT_MIN 1.17549435e-38 +#define FLT_MIN_10_EXP -37 +#define FLT_MAX_EXP 128 +#define FLT_MAX 3.40282347e+38 +#define FLT_MAX_10_EXP 38 +#define DBL_MANT_DIG 53 +#define DBL_EPSILON 2.2204460492503131e-16 +#define DBL_DIG 15 +#define DBL_MIN_EXP -1021 +#define DBL_MIN 2.225073858507201e-308 +#define DBL_MIN_10_EXP -307 +#define DBL_MAX_EXP 1024 +#define DBL_MAX 1.797693134862316e+308 +#define DBL_MAX_10_EXP 308 +#endif i8086 || m68k + + +/* long double equates to double */ + + +#define LDBL_MANT_DIG DBL_MANT_DIG +#define LDBL_EPSILON DBL_EPSILON +#define LDBL_DIG DBL_DIG +#define LDBL_MIN_EXP DBL_MIN_EXP +#define LDBL_MIN DBL_MIN +#define LDBL_MIN_10_EXP DBL_MIN_10_EXP +#define LDBL_MAX_EXP DBL_MAX_EXP +#define LDBL_MAX DBL_MAX +#define LDBL_MAX_10_EXP DBL_MAX_10_EXP + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/HITECH.H b/Source/Images/d_hitechc/u1/HITECH.H new file mode 100644 index 00000000..4a20f955 --- /dev/null +++ b/Source/Images/d_hitechc/u1/HITECH.H @@ -0,0 +1,74 @@ +#ifndef _HTC_HITECH_H +#define _HTC_HITECH_H + +/* Standard types for HI-TECH Software code + These types may need to be tuned for different + machines/compilers. Notes with each one indicate assumptions + that should be maintained for each type. + */ + + +/* + Turn ANSI on if the compiler supports function prototypes and + has the ANSI header files + + + */ + +#if HI_TECH_C +#define ANSI 1 +#endif HI_TECH_C + +/* shorthand types */ + +#define uchar unsigned char +#define ulong unsigned long +#define ushort unsigned short + +/* useful, tuneable types. Change only if: + + 1) compiler does not support type, e.g. unsigned char. + 2) compiler generates bad code for a particular type. + 3) a larger type would generate faster code, e.g. byte counters + on the 65816 are inefficient code-wise. + */ + +#define BOOL unsigned char /* boolean variable. Any integral type + will do. */ +#define FAST char /* fast, small counter. Must permit + values -128 to 127 but may be larger. */ +#define UFAST unsigned char /* fast, small unsigned counter. Must + permit values 0-255 at least */ +#define BYTE unsigned char /* sizeof(BYTE) must == 1 */ +#define INT_16 short /* signed, >= 16 bits */ +#define UINT_16 unsigned short /* unsigned, >= 16 bits */ +#define INT_32 long /* signed, >= 32 bits */ +#define UINT_32 unsigned long /* unsigned, >= 32 bits */ + + +/* Register variable selectors; REG1 is for things that must go + in registers at all costs, REG2 for things that should, REG3 for + things that could go in registers if there are any left over. + Ordering of declarations will of course come into it too. + */ + +#if z80 /* only has one register variable */ +#define REG1 register +#define REG2 auto +#define REG3 auto +#endif z80 + +#if i8086 /* only has two register variable */ +#define REG1 register +#define REG2 register +#define REG3 auto +#endif i8086 + +#if i8096 || m68k /* lots of registers! */ +#define REG1 register +#define REG2 register +#define REG3 register +#endif i8096 || m68k + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/LIBC.LIB b/Source/Images/d_hitechc/u1/LIBC.LIB new file mode 100644 index 00000000..26840dc1 Binary files /dev/null and b/Source/Images/d_hitechc/u1/LIBC.LIB differ diff --git a/Source/Images/d_hitechc/u1/LIBF.LIB b/Source/Images/d_hitechc/u1/LIBF.LIB new file mode 100644 index 00000000..b368e9c8 Binary files /dev/null and b/Source/Images/d_hitechc/u1/LIBF.LIB differ diff --git a/Source/Images/d_hitechc/u1/LIBOVR.LIB b/Source/Images/d_hitechc/u1/LIBOVR.LIB new file mode 100644 index 00000000..06656b43 Binary files /dev/null and b/Source/Images/d_hitechc/u1/LIBOVR.LIB differ diff --git a/Source/Images/d_hitechc/u1/LIBR.COM b/Source/Images/d_hitechc/u1/LIBR.COM new file mode 100644 index 00000000..7b764913 Binary files /dev/null and b/Source/Images/d_hitechc/u1/LIBR.COM differ diff --git a/Source/Images/d_hitechc/u1/LIMITS.H b/Source/Images/d_hitechc/u1/LIMITS.H new file mode 100644 index 00000000..048f2596 --- /dev/null +++ b/Source/Images/d_hitechc/u1/LIMITS.H @@ -0,0 +1,23 @@ +#ifndef _HTC_LIMITS_H +#define _HTC_LIMITS_H + +/* Characteristics of integral types */ + +#define CHAR_BIT 8 /* bits per char */ +#define CHAR_MAX 127 /* max value of a char */ +#define CHAR_MIN -128 /* min value */ +#define SCHAR_MAX CHAR_MAX /* chars are signed */ +#define SCHAR_MIN CHAR_MIN +#define UCHAR_MAX 255 /* for unsigned chars */ +#define SHRT_MAX 32767 /* max value of a short */ +#define SHRT_MIN -32768 +#define USHRT_MAX 65535 /* unsigned short */ +#define INT_MAX 32767 /* max for int */ +#define INT_MIN -32768 /* min for int */ +#define UINT_MAX 65535 /* unsigned int */ +#define LONG_MAX 2147483647 /* max value of long */ +#define LONG_MIN -2147483648 /* min value */ +#define ULONG_MAX 4294967295 /* unsigned long */ + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/LINQ.COM b/Source/Images/d_hitechc/u1/LINQ.COM new file mode 100644 index 00000000..6208ba53 Binary files /dev/null and b/Source/Images/d_hitechc/u1/LINQ.COM differ diff --git a/Source/Images/d_hitechc/u1/MATH.H b/Source/Images/d_hitechc/u1/MATH.H new file mode 100644 index 00000000..a5c25f40 --- /dev/null +++ b/Source/Images/d_hitechc/u1/MATH.H @@ -0,0 +1,13 @@ +#ifndef _HTC_MATH_H +#define _HTC_MATH_H + +extern double fabs(double), floor(double), ceil(double), modf(double, double *); +extern double sqrt(double), atof(char *); +extern double sin(double), cos(double), tan(double); +extern double asin(double), acos(double), atan(double), atan2(double, double); +extern double frexp(double, int *), ldexp(double, int); +extern double log(double), log10(double), pow(double, double), exp(double); +extern double sinh(double), cosh(double), tanh(double); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/NRTCPM.OBJ b/Source/Images/d_hitechc/u1/NRTCPM.OBJ new file mode 100644 index 00000000..b7e726ee Binary files /dev/null and b/Source/Images/d_hitechc/u1/NRTCPM.OBJ differ diff --git a/Source/Images/d_hitechc/u1/OBJTOHEX.COM b/Source/Images/d_hitechc/u1/OBJTOHEX.COM new file mode 100644 index 00000000..65ed2302 Binary files /dev/null and b/Source/Images/d_hitechc/u1/OBJTOHEX.COM differ diff --git a/Source/Images/d_hitechc/u1/OPTIM.COM b/Source/Images/d_hitechc/u1/OPTIM.COM new file mode 100644 index 00000000..6e152dae Binary files /dev/null and b/Source/Images/d_hitechc/u1/OPTIM.COM differ diff --git a/Source/Images/d_hitechc/u1/OPTIONS b/Source/Images/d_hitechc/u1/OPTIONS new file mode 100644 index 00000000..c87efae6 --- /dev/null +++ b/Source/Images/d_hitechc/u1/OPTIONS @@ -0,0 +1,22 @@ +HI-TECH Z80 CP/M C compiler options: + +-A Generate a self-relocating .COM program. +-C Generate object code only; don't link. +-CR Produce a cross-reference listing e.g. -CRfile.crf +-D Define a symbol, e.g. -DDEBUG=1 +-E Specify executable output filename, e.g. -Efile.com +-Ffile Generate a symbol file for debug.com or overlay build (default L.SYM) +-H Output help (the OPTIONS file) and exit. +-I Specify an include directory, e.g. -I1:B: +-L Scan a library, e.g. -LF scans the floating point library. +-M Generate a map file, e.g. -Mfile.map +-N Use the NRTCPM.OBJ start-up with minimal _getargs(). +-O Invoke the peephole optimizer (reduced code-size) +-OF Invoke the optimizer for speed (Fast) +-S Generate assembler code in a .AS file; don't assemble or link. +-U Undefine a predefined symbol, e.g. -UDEBUG +-V Be verbose during compilation. +-W Set warning level, e.g. -w5 or -w-2 +-X Suppress local symbols in symbol tables. +-Y Generate an overlay output file (.OVR file-type) + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/OVERLAY.H b/Source/Images/d_hitechc/u1/OVERLAY.H new file mode 100644 index 00000000..e83a08c4 --- /dev/null +++ b/Source/Images/d_hitechc/u1/OVERLAY.H @@ -0,0 +1,6 @@ +#ifndef _HTC_OVERLAY_H +#define _HTC_OVERLAY_H + +#include +intptr_t ovrload(char *ovr_name,intptr_t args); +#endif diff --git a/Source/Images/d_hitechc/u1/P1.COM b/Source/Images/d_hitechc/u1/P1.COM new file mode 100644 index 00000000..314842c3 Binary files /dev/null and b/Source/Images/d_hitechc/u1/P1.COM differ diff --git a/Source/Images/d_hitechc/u1/RRTCPM.OBJ b/Source/Images/d_hitechc/u1/RRTCPM.OBJ new file mode 100644 index 00000000..f892529f Binary files /dev/null and b/Source/Images/d_hitechc/u1/RRTCPM.OBJ differ diff --git a/Source/Images/d_hitechc/u1/SETJMP.H b/Source/Images/d_hitechc/u1/SETJMP.H new file mode 100644 index 00000000..a34df7dc --- /dev/null +++ b/Source/Images/d_hitechc/u1/SETJMP.H @@ -0,0 +1,24 @@ +#ifndef _HTC_SETJMP_H +#define _HTC_SETJMP_H + +#if z80 +typedef int jmp_buf[4]; +#endif + +#if i8086 +typedef int jmp_buf[8]; +#endif + +#if i8096 +typedef int jmp_buf[10]; +#endif + +#if m68k +typedef int jmp_buf[10]; +#endif + +extern int setjmp(jmp_buf); +extern void longjmp(jmp_buf, int); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/SIGNAL.H b/Source/Images/d_hitechc/u1/SIGNAL.H new file mode 100644 index 00000000..0dcdb54b --- /dev/null +++ b/Source/Images/d_hitechc/u1/SIGNAL.H @@ -0,0 +1,36 @@ +#ifndef _HTC_SIGNAL_H +#define _HTC_SIGNAL_H + +/* + * Signal definitions for CP/M + */ +#ifdef unix +#define NSIG 17 +#define SIGHUP 1 /* hangup (not used by terminal driver) */ +#define SIGINT 2 /* interrupt (^C or BREAK) */ +#define SIGQUIT 3 /* quit (^\) */ +#define SIGILL 4 /* illegal instruction (not reset when caught) */ +#define SIGTRAP 5 /* trace trap (not reset when caught) */ +#define SIGIOT 6 /* IOT instruction */ +#define SIGEMT 7 /* EMT instruction */ +#define SIGFPE 8 /* floating point exception */ +#define SIGKILL 9 /* kill (cannot be caught or ignored) */ +#define SIGBUS 10 /* bus error */ +#define SIGSEGV 11 /* segmentation violation */ +#define SIGSYS 12 /* bad argument to system call */ +#define SIGPIPE 13 /* write on a pipe with no one to read it */ +#define SIGALRM 14 /* alarm clock */ +#define SIGTERM 15 /* software termination signal from kill */ +#else +#define NSIG 1 +#define SIGINT 1 /* control-C */ +#endif + +typedef void* signal_t; +#define SIG_DFL ((signal_t)0) /* default action is to exit */ +#define SIG_IGN ((signal_t)1) /* ignore them */ + +signal_t signal(int sig, signal_t action); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/STAT.H b/Source/Images/d_hitechc/u1/STAT.H new file mode 100644 index 00000000..6166919f --- /dev/null +++ b/Source/Images/d_hitechc/u1/STAT.H @@ -0,0 +1,28 @@ +#ifndef _HTC_STAT_H +#define _HTC_STAT_H + +struct stat +{ + short st_mode; /* flags */ + long st_atime; /* access time */ + long st_mtime; /* modification time */ + long st_size; /* file size in bytes */ +}; + +/* Flag bits in st_mode */ + +#define S_IFMT 0x600 /* type bits */ +#define S_IFDIR 0x400 /* is a directory */ +#define S_IFREG 0x200 /* is a regular file */ +#define S_IREAD 0400 /* file can be read */ +#define S_IWRITE 0200 /* file can be written */ +#define S_IEXEC 0100 /* file can be executed */ +#define S_HIDDEN 0x1000 /* file is hidden */ +#define S_SYSTEM 0x2000 /* file is marked system */ +#define S_ARCHIVE 0x4000 /* file has been written to */ + + +extern int stat(char *, struct stat *); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/STDARG.H b/Source/Images/d_hitechc/u1/STDARG.H new file mode 100644 index 00000000..c8511a93 --- /dev/null +++ b/Source/Images/d_hitechc/u1/STDARG.H @@ -0,0 +1,15 @@ +#ifndef _HTC_STDARG_H +#define _HTC_STDARG_H + +/* Macros for accessing variable arguments */ + +typedef void * va_list[1]; + +#define va_start(ap, parmn) *ap = (char *)&parmn + sizeof parmn + +#define va_arg(ap, type) (*(*(type **)ap)++) + +#define va_end(ap) + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/STDDEF.H b/Source/Images/d_hitechc/u1/STDDEF.H new file mode 100644 index 00000000..00eb9348 --- /dev/null +++ b/Source/Images/d_hitechc/u1/STDDEF.H @@ -0,0 +1,18 @@ +#ifndef _HTC_STDDEF_H +#define _HTC_STDDEF_H + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif _STDDEF + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +extern int errno; /* system error number */ + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/STDINT.H b/Source/Images/d_hitechc/u1/STDINT.H new file mode 100644 index 00000000..e1330dea --- /dev/null +++ b/Source/Images/d_hitechc/u1/STDINT.H @@ -0,0 +1,15 @@ +#ifndef _HTC_STDINT_H +#define _HTC_STDINT_H + +#if z80||i8086||i8096||m68k +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned long uint32_t; +typedef long int32_t; +typedef unsigned short intptr_t; +#endif + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/STDIO.H b/Source/Images/d_hitechc/u1/STDIO.H new file mode 100644 index 00000000..4f4c581b --- /dev/null +++ b/Source/Images/d_hitechc/u1/STDIO.H @@ -0,0 +1,132 @@ +#ifndef _HTC_STDIO_H +#define _HTC_STDIO_H + +/* + * STDIO.H HI-TECH C standard I/O for V3.09-xx + * + * This version incorporates changes to stdio routines + * resulting from backporting features from V4.11 + */ + +#define _HTC_VERSION "3.09-19" +#define _HTC_MAJOR 3 +#define _HTC_MINOR 9 +#define _HTC_REV 19 + +#if z80 +#define BUFSIZ 512 +#define _NFILE 8 +#else z80 +#define BUFSIZ 1024 +#define _NFILE 20 +#endif z80 + +#ifndef _STDDEF +typedef int ptrdiff_t; +typedef unsigned size_t; +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif _STDDEF + +#ifndef FILE +#define uchar unsigned char + +extern struct _iobuf +{ + char *_ptr; + int _cnt; + char *_base; + unsigned short _flag; + char _file; + size_t _size; +} _iob[_NFILE]; + +#define FILE struct _iobuf +#endif FILE + +#ifndef SEEK_SET +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 +#endif + +/* I/O status flag word bits */ +#define _IOREAD 01 /* Allow file reading */ +#define _IOWRT 02 /* Allow file writing */ +#define _IORW 03 /* Mask for reading or writing */ +#define _IONBF 04 /* Not being buffered */ +#define _IOMYBUF 010 /* Using buffer */ +#define _IOEOF 020 /* At end-of-file */ +#define _IOERR 040 /* An I/O error has occurred */ +#define _IOSTRG 0100 /* End of string reached */ +#define _IOBINARY 0200 /* Binary mode */ +#define _IOLBF 0400 /* Using line buffering */ +#define _IODIRN 01000 /* Direction - writing to a R/W file */ +#define _IOAPPEND 02000 /* Append mode */ +#define _IOSEEKED 04000 /* A seek has occurred since last write */ +#define _IOFBF 010000 /* Using full buffering */ + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +#define EOF (-1) + +#define stdin (&_iob[0]) +#define stdout (&_iob[1]) +#define stderr (&_iob[2]) +#define getchar() getc(stdin) +#define putchar(x) putc(x,stdout) + +/* + * getc() and putc() must be functions for CP/M to allow the special + * handling of '\r', '\n' and '\032'. The same for MSDOS except that + * it at least knows the length of a file. + */ + +#if UNIX +#define getc(p) (--(p)->_cnt>=0?(unsigned)*(p)->_ptr++:_filbuf(p)) +#define putc(x,p) (--(p)->_cnt>=0?((unsigned)(*(p)->_ptr++=x)):_flsbuf((unsigned)(x),p)) +#else UNIX +#define getc(p) fgetc(p) +#define putc(x,p) fputc(x,p) +#endif UNIX + +#define feof(p) (((p)->_flag&_IOEOF)!=0) +#define ferror(p) (((p)->_flag&_IOERR)!=0) +#define fileno(p) ((uchar)p->_file) +#define clrerr(p) p->_flag &= ~_IOERR +#define clreof(p) p->_flag &= ~_IOEOF + +extern int fclose(FILE *); +extern int fflush(FILE *); +extern int fgetc(FILE *); +extern int ungetc(int, FILE *); +extern int fputc(int, FILE *); +extern int getw(FILE *); +extern int putw(int, FILE *); +extern char *gets(char *); +extern int puts(char *); +extern int fputs(char *, FILE *); +extern int fread(void *, unsigned, unsigned, FILE *); +extern int fwrite(void *, unsigned, unsigned, FILE *); +extern int fseek(FILE *, long, int); +extern int rewind(FILE *); +extern void setbuf(FILE *, char *); +extern int setvbuf(FILE *, char *, int, size_t); +extern int printf(char *, ...); +extern int fprintf(FILE *, char *, ...); +extern int sprintf(char *, char *, ...); +extern int scanf(char *, ...); +extern int fscanf(FILE *, char *, ...); +extern int sscanf(char *, char *, ...); +extern int remove(char *); +extern FILE *fopen(char *, char *); +extern FILE *freopen(char *, char *, FILE *); +extern FILE *fdopen(int, char *); +extern long ftell(FILE *); +extern char *fgets(char *, int, FILE *); +extern char *_bufallo(void); + +#endif _HTC_STDIO_H + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/STDLIB.H b/Source/Images/d_hitechc/u1/STDLIB.H new file mode 100644 index 00000000..4066c6fc --- /dev/null +++ b/Source/Images/d_hitechc/u1/STDLIB.H @@ -0,0 +1,42 @@ +#ifndef _HTC_STDLIB_H +#define _HTC_STDLIB_H + +/* Standard utility functions */ + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ + +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) + +#define _STDDEF + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +extern int errno; /* system error number */ +#endif _STDDEF + +#define RAND_MAX 32767 /* max value returned by rand() */ + +extern double atof(char *); +extern int atoi(char *); +extern long atol(char *); +extern int rand(void); +extern void srand(unsigned int); +extern void *calloc(size_t, size_t); +extern void free(void *); +extern void *malloc(size_t); +extern void *realloc(void *, size_t); +extern void abort(void); +extern void exit(int); +extern char *getenv(char *); +extern int system(char *); +typedef int (*__qsort_compf)(void *, void *); /* workaround compiler bug */ +extern void qsort(void *, size_t, size_t, __qsort_compf); +extern int abs(int); +extern long labs(long); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/STRING.H b/Source/Images/d_hitechc/u1/STRING.H new file mode 100644 index 00000000..7ae3e51a --- /dev/null +++ b/Source/Images/d_hitechc/u1/STRING.H @@ -0,0 +1,54 @@ +#ifndef _HTC_STRING_H +#define _HTC_STRING_H + +/* String functions v3.09-4 */ + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif _STDDEF + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +extern int errno; /* system error number */ + +extern void *memcpy(void *, void *, size_t); +extern void *memmove(void *, void *, size_t); +extern char *strcpy(char *, char *); +extern char *strncpy(char *, char *, size_t); +extern char *strcat(char *, char *); +extern char *strncat(char *, char *, size_t); +extern int memcmp(void *, void *, size_t); +extern int strcmp(char *, char *); +extern int strcasecmp(char *, char *); +#define stricmp strcasecmp +extern int strncmp(char *, char *, size_t); +extern int strncasecmp(char *, char *, size_t); +#define strnicmp strncasecmp +/* extern size_t strcoll(char *, size_t, char *); */ /* missing */ +extern void *memchr(void *, int, size_t); +/* extern size_t strcspn(char *, char *); */ /* missing */ +/* extern char *strpbrk(char *, char *); */ /* missing */ +/* extern size_t strspn(char *, char *); *//* missing */ +extern char *strstr(char *, char *); +extern char *strtok(char *, char *); +extern void *memset(void *, int, size_t); +extern char *strerror(int); +extern size_t strlen(char *); +extern char *strchr(char *, int); +/* #define index strchr */ /* these are equivalent */ +extern char *index(char *, int); +extern char *strrchr(char *, int); +/* #define rindex *strrchr */ /* these are equivalent */ +extern char *rindex(char *, int); +extern char *strcasestr(char *, char *); +#define stristr strcasestr +extern char *strncasestr(char *, char *, size_t); +#define strnistr strncasestr + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/SYMTOAS.COM b/Source/Images/d_hitechc/u1/SYMTOAS.COM new file mode 100644 index 00000000..ffdbf679 Binary files /dev/null and b/Source/Images/d_hitechc/u1/SYMTOAS.COM differ diff --git a/Source/Images/d_hitechc/u1/SYS.H b/Source/Images/d_hitechc/u1/SYS.H new file mode 100644 index 00000000..5f8a4b9e --- /dev/null +++ b/Source/Images/d_hitechc/u1/SYS.H @@ -0,0 +1,40 @@ +#ifndef _HTC_SYS_H +#define _HTC_SYS_H + +/* + * System-dependent functions. + */ + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif _STDDEF + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +extern int errno; /* system error number */ + +extern int execl(char *, char *, char *, ...); +extern int execv(char *, char **); +extern int spawnl(char *, char *, char *, ...); +extern int spawnv(char *, char **); +extern int spawnle(char *, char *, char *, char *, ...); +extern int spawnve(char *, char **, char *); +extern short getuid(void); +extern short setuid(short); +extern int chdir(char *); +extern int mkdir(char *); +extern int rmdir(char *); +extern int getcwd(int); +extern char **_getargs(char *, char *); +extern int _argc_; +extern int inp(int); +extern void outp(int, int); +extern void * sbrk(size_t); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/TIME.H b/Source/Images/d_hitechc/u1/TIME.H new file mode 100644 index 00000000..f1094d73 --- /dev/null +++ b/Source/Images/d_hitechc/u1/TIME.H @@ -0,0 +1,44 @@ +#ifndef _HTC_TIME_H +#define _HTC_TIME_H + +/* time.h for HI-TECH C Z80 v3.09-4*/ + +#ifndef _HTC_TIME_T + +typedef long time_t; /* for representing times in seconds */ +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; +#define _HTC_TIME_T +#endif _HTC_TIME_T + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif + +extern int time_zone; /* minutes WESTWARD of Greenwich */ + /* this value defaults to 0 since with + operating systems like MS-DOS there is + no time zone information available */ + +extern time_t time(time_t *); /* seconds since 00:00:00 Jan 1 1970 */ +extern char * asctime(struct tm *); /* converts struct tm to ascii time */ +extern char * ctime(time_t *); /* current local time in ascii form */ +extern struct tm * gmtime(time_t *); /* Universal time */ +extern struct tm * localtime(time_t *); /* local time */ +extern size_t strftime(char *s, size_t maxs, char *f, struct tm *t); +extern time_t mktime(struct tm *); /* convert struct tm to time value */ + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/UNIXIO.H b/Source/Images/d_hitechc/u1/UNIXIO.H new file mode 100644 index 00000000..82bfb14d --- /dev/null +++ b/Source/Images/d_hitechc/u1/UNIXIO.H @@ -0,0 +1,34 @@ +#ifndef _HTC_UNIXIO_H +#define _HTC_UNIXIO_H + +/* + * Declarations for Unix style low-level I/O functions. + */ + +#ifndef _STDDEF +typedef int ptrdiff_t; /* result type of pointer difference */ +typedef unsigned size_t; /* type yielded by sizeof */ +#define _STDDEF +#define offsetof(ty, mem) ((int)&(((ty *)0)->mem)) +#endif _STDDEF + +#ifndef NULL +#define NULL ((void *)0) +#endif NULL + +extern int errno; /* system error number */ + +extern int open(char *, int); +extern int close(int); +extern int creat(char *, int); +extern int dup(int); +extern long lseek(int, long, int); +extern int read(int, void *, int); +extern int rename(char *, char *); +extern int unlink(char *); +extern int write(int, void *, int); +extern int isatty(int); +extern int chmod(char *, int); + +#endif + \ No newline at end of file diff --git a/Source/Images/d_hitechc/u1/ZAS.COM b/Source/Images/d_hitechc/u1/ZAS.COM new file mode 100644 index 00000000..57d82a81 Binary files /dev/null and b/Source/Images/d_hitechc/u1/ZAS.COM differ diff --git a/Source/Images/d_infocom/Readme.txt b/Source/Images/d_infocom/Readme.txt new file mode 100644 index 00000000..47aa9b70 --- /dev/null +++ b/Source/Images/d_infocom/Readme.txt @@ -0,0 +1,117 @@ + +===== INFOCOM GAMES ===== + +A collection of all official releases of the interactive fiction games +produced by Infocom in the 1980's. The copyright rests with Activision, +and since 2022 that transferred to Microsoft + +Game List follows including the revision number and release date + +amfv.z4 - (A Mind Forever Voyaging) - r77-s850814.z4 +arthur.z6 - (Arthur) - r74-s890714 +ballyhoo.z3 - (Ballyhoo) - r97-s851218 +beyond.z5 - (Beyond Zork) - r57-s871221 +border.z5 - (Border Zone) - r9-s871008 +bureau.z4 - (Bureaucracy) - r116-s870602 +cutthr.z3 - (Cutthroats) - r23-s840809 +deadline.z3 - (Deadline) - r27-s831005 +enchant.z3 - (Enchanter) - r29-s860820 +h2g2.z3 - (The Hitchhiker's Guide to the Galaxy) - r59-s851108 +hollyw.z3 - (Hollywood Hijinx) - r37-s861215 +infidel.z3 - (Infidel) - r22-s830916 +journey.z6 - (Journey) - r83-s890706 +leather.z3 - (Leather Goddesses of Phobos) - r59-s860730 +lurking.z3 - (The Lurking Horror) - r203-s870506 +moonmist.z3 - (Moonmist) - r9-s861022 +nordbert.z4 - (Nord and Bert Couldn't Make Head or Tail of It) - r19-s870722 +planet.z3 - (Planetfall) - r37-s851003 +plunder.z3 - (Plundered Hearts) - r26-s870730 +seastalk.z3 - (Seastalker) - r16-s850603 +sherlock.z5 - (Sherlock) - r26-s880127 +shogun.z6 - (Shogun) - r322-s890706 +sorcerer.z3 - (Sorcerer) - r15-s851108 +spellb.z3 - (Spellbreaker) - r87-s860904 +starcros.z3 - (Starcross) - r17-s821021 +stationf.z3 - (Stationfall) - r107-s870430 +suspect.z3 - (Suspect) - r14-s841005 +suspend.z3 - (Suspended) - r8-s840521 +trinity.z4 - (Trinity) - r12-s860926 +wishb.z3 - (Wishbringer) - r69-s850920 +witness.z3 - (Witness) - r22-s840924 +zork0.z6 - (Zork 0) - r393-s890714 +zork1.z3 - (Zork 1) - r88-s840726 +zork2.z3 - (Zork 2) - r48-s840904 +zork3.z3 - (Zork 3) - r17-s840727 + +The versions above are generally from the "Classic Text Adventure +Masterpieces" released by Activision in (1996) which is the source of +most modern releases. + +The version of Hitchhiker is the one that Douglas Adams postedon his web +site in the mid-90s. The BBC later posted an illustrated version based +on the same game file. + +The above games have been curated from here . +Full game documentation can be found here + +The game files are a virtual machine code commonly known as Z-Machine, they +are portable and will run on any machine that has a Z-Machine interpreter. + +All the Z3 games come with the official CP/M interpreter (Version C) last +updated by Inforcom on 5th Feb 1985 + +All latter games Z4, Z5,.. and above, are more sophisticated and require +a better interpreter. i.e. VEZZA. + +VEZZA + +Vezza is a modern Infocom/Inform/Z-machine text adventure interpreter for +8 bit z80 based computers. What makes it modern is that it is written in +hand-crafted z80 assembler for maximum speed, and can load not only the +classics such as Zork 1,2 and 3 but also the latter games. + +It can run Z1 up to Z8 inform format interactive fiction game files. To run +a game with Vezza just type Vezza followed by the game you want to run. e.g. + +`VEZZA ZORK0.Z6` + +**Note:** One of the bigger constraints is available RAM. An OS such as ZPM +since it uses banked RAM does have a good amount of available RAM and was +used to test these games work. + +This tool is free but the developer accepts your support by letting you +pay what you think is fair for the tool. If you find this useful consider +donating at: + +https://sijnstra.itch.io/vezza + +The following files are located in user area 15 + +Available builds (requires CP/M version 3 or compatible system): + vezza-b.com - 80x24 screen, vt52 + Banked CP/M 3 + vezza-FG.com - 80x30 screen, VT100/ANSI CP/M 3 (tested on Z80-MBC2 & FabGL) + +Other builds (Large memory CP/M 2.2, no timed input): + vezza-C2.com - 80x24 RunCPM VT100 - no colour + vezza-CC.com - 80x24 RunCPM VT100 with 256 ANSI colour codes + +Slow builds due to BIOS limitations (extra register presevation, less cache, +smaller memory build): + vezza-AV.com - CP/M 2.2 with VT100 codes plus 16 bit ANSI colour & high + RAM. Works on Agon Light CP/M 2.2 + Note: Issues with very high I/O such as screen animations + vezza-AX.com - CP/M 2.2 with VT100 codes plus 16 bit ANSI colour, high + RAM & FabGL Italic. Works on Agon Light CP/M 2.2 + Note: Issues with very high I/O such as screen animations + vezza-RW.com - CP/M 2.2 with VT100 codes plus 16 bit ANSI colour with low + RAM. Tested on RC 2014 SC-126 using TeraTerm + +You should (test and) choose one that works on you configuration, and +ideally copy and rename it as vezza.com, so the Alias COM files can find +and execute the game. + +The above is a subset of available builds. The full repository is available +at https://gitlab.com/sijnstra1/vezza/ + + + diff --git a/Source/Images/d_infocom/u0/AMFV.Z4 b/Source/Images/d_infocom/u0/AMFV.Z4 new file mode 100644 index 00000000..05e2518b Binary files /dev/null and b/Source/Images/d_infocom/u0/AMFV.Z4 differ diff --git a/Source/Images/d_infocom/u0/ARTHUR.Z6 b/Source/Images/d_infocom/u0/ARTHUR.Z6 new file mode 100644 index 00000000..a28c3d3e Binary files /dev/null and b/Source/Images/d_infocom/u0/ARTHUR.Z6 differ diff --git a/Source/Images/d_infocom/u0/BALLYHOO.COM b/Source/Images/d_infocom/u0/BALLYHOO.COM new file mode 100755 index 00000000..7328c178 Binary files /dev/null and b/Source/Images/d_infocom/u0/BALLYHOO.COM differ diff --git a/Source/Images/d_infocom/u0/BALLYHOO.Z3 b/Source/Images/d_infocom/u0/BALLYHOO.Z3 new file mode 100644 index 00000000..5b6fb026 Binary files /dev/null and b/Source/Images/d_infocom/u0/BALLYHOO.Z3 differ diff --git a/Source/Images/d_infocom/u0/BEYOND.Z5 b/Source/Images/d_infocom/u0/BEYOND.Z5 new file mode 100644 index 00000000..30d7905a Binary files /dev/null and b/Source/Images/d_infocom/u0/BEYOND.Z5 differ diff --git a/Source/Images/d_infocom/u0/BORDER.Z5 b/Source/Images/d_infocom/u0/BORDER.Z5 new file mode 100644 index 00000000..60c1f030 Binary files /dev/null and b/Source/Images/d_infocom/u0/BORDER.Z5 differ diff --git a/Source/Images/d_infocom/u0/BUREAU.Z4 b/Source/Images/d_infocom/u0/BUREAU.Z4 new file mode 100644 index 00000000..d52069a1 Binary files /dev/null and b/Source/Images/d_infocom/u0/BUREAU.Z4 differ diff --git a/Source/Images/d_infocom/u0/CUTTHR.COM b/Source/Images/d_infocom/u0/CUTTHR.COM new file mode 100755 index 00000000..fce3db86 Binary files /dev/null and b/Source/Images/d_infocom/u0/CUTTHR.COM differ diff --git a/Source/Images/d_infocom/u0/CUTTHR.Z3 b/Source/Images/d_infocom/u0/CUTTHR.Z3 new file mode 100644 index 00000000..a9d33fc7 Binary files /dev/null and b/Source/Images/d_infocom/u0/CUTTHR.Z3 differ diff --git a/Source/Images/d_infocom/u0/DEADLINE.COM b/Source/Images/d_infocom/u0/DEADLINE.COM new file mode 100755 index 00000000..3b3eb6ea Binary files /dev/null and b/Source/Images/d_infocom/u0/DEADLINE.COM differ diff --git a/Source/Images/d_infocom/u0/DEADLINE.Z3 b/Source/Images/d_infocom/u0/DEADLINE.Z3 new file mode 100644 index 00000000..ebbe2603 Binary files /dev/null and b/Source/Images/d_infocom/u0/DEADLINE.Z3 differ diff --git a/Source/Images/d_infocom/u0/ENCHANT.COM b/Source/Images/d_infocom/u0/ENCHANT.COM new file mode 100755 index 00000000..39264364 Binary files /dev/null and b/Source/Images/d_infocom/u0/ENCHANT.COM differ diff --git a/Source/Images/d_infocom/u0/ENCHANT.Z3 b/Source/Images/d_infocom/u0/ENCHANT.Z3 new file mode 100644 index 00000000..749a4d94 Binary files /dev/null and b/Source/Images/d_infocom/u0/ENCHANT.Z3 differ diff --git a/Source/Images/d_infocom/u0/H2G2.COM b/Source/Images/d_infocom/u0/H2G2.COM new file mode 100755 index 00000000..962f35e5 Binary files /dev/null and b/Source/Images/d_infocom/u0/H2G2.COM differ diff --git a/Source/Images/d_infocom/u0/H2G2.Z3 b/Source/Images/d_infocom/u0/H2G2.Z3 new file mode 100644 index 00000000..3a3e338e Binary files /dev/null and b/Source/Images/d_infocom/u0/H2G2.Z3 differ diff --git a/Source/Images/d_infocom/u0/HOLLYW.COM b/Source/Images/d_infocom/u0/HOLLYW.COM new file mode 100755 index 00000000..0b51176c Binary files /dev/null and b/Source/Images/d_infocom/u0/HOLLYW.COM differ diff --git a/Source/Images/d_infocom/u0/HOLLYW.Z3 b/Source/Images/d_infocom/u0/HOLLYW.Z3 new file mode 100644 index 00000000..9652a646 Binary files /dev/null and b/Source/Images/d_infocom/u0/HOLLYW.Z3 differ diff --git a/Source/Images/d_infocom/u0/INFIDEL.COM b/Source/Images/d_infocom/u0/INFIDEL.COM new file mode 100755 index 00000000..e5fc4e62 Binary files /dev/null and b/Source/Images/d_infocom/u0/INFIDEL.COM differ diff --git a/Source/Images/d_infocom/u0/INFIDEL.Z3 b/Source/Images/d_infocom/u0/INFIDEL.Z3 new file mode 100644 index 00000000..c31b145b Binary files /dev/null and b/Source/Images/d_infocom/u0/INFIDEL.Z3 differ diff --git a/Source/Images/d_infocom/u0/JOURNEY.Z6 b/Source/Images/d_infocom/u0/JOURNEY.Z6 new file mode 100644 index 00000000..d0952f11 Binary files /dev/null and b/Source/Images/d_infocom/u0/JOURNEY.Z6 differ diff --git a/Source/Images/d_infocom/u0/LEATHER.COM b/Source/Images/d_infocom/u0/LEATHER.COM new file mode 100755 index 00000000..110447c3 Binary files /dev/null and b/Source/Images/d_infocom/u0/LEATHER.COM differ diff --git a/Source/Images/d_infocom/u0/LEATHER.Z3 b/Source/Images/d_infocom/u0/LEATHER.Z3 new file mode 100644 index 00000000..76c5ea77 Binary files /dev/null and b/Source/Images/d_infocom/u0/LEATHER.Z3 differ diff --git a/Source/Images/d_infocom/u0/LURKING.COM b/Source/Images/d_infocom/u0/LURKING.COM new file mode 100755 index 00000000..8998179e Binary files /dev/null and b/Source/Images/d_infocom/u0/LURKING.COM differ diff --git a/Source/Images/d_infocom/u0/LURKING.Z3 b/Source/Images/d_infocom/u0/LURKING.Z3 new file mode 100644 index 00000000..a03dd600 Binary files /dev/null and b/Source/Images/d_infocom/u0/LURKING.Z3 differ diff --git a/Source/Images/d_infocom/u0/MOONMIST.COM b/Source/Images/d_infocom/u0/MOONMIST.COM new file mode 100755 index 00000000..2d665b4b Binary files /dev/null and b/Source/Images/d_infocom/u0/MOONMIST.COM differ diff --git a/Source/Images/d_infocom/u0/MOONMIST.Z3 b/Source/Images/d_infocom/u0/MOONMIST.Z3 new file mode 100644 index 00000000..0948e500 Binary files /dev/null and b/Source/Images/d_infocom/u0/MOONMIST.Z3 differ diff --git a/Source/Images/d_infocom/u0/NORDBERT.Z4 b/Source/Images/d_infocom/u0/NORDBERT.Z4 new file mode 100644 index 00000000..68368993 Binary files /dev/null and b/Source/Images/d_infocom/u0/NORDBERT.Z4 differ diff --git a/Source/Images/d_infocom/u0/PLANET.COM b/Source/Images/d_infocom/u0/PLANET.COM new file mode 100755 index 00000000..4d71bb49 Binary files /dev/null and b/Source/Images/d_infocom/u0/PLANET.COM differ diff --git a/Source/Images/d_infocom/u0/PLANET.Z3 b/Source/Images/d_infocom/u0/PLANET.Z3 new file mode 100644 index 00000000..c9d3489b Binary files /dev/null and b/Source/Images/d_infocom/u0/PLANET.Z3 differ diff --git a/Source/Images/d_infocom/u0/PLUNDER.COM b/Source/Images/d_infocom/u0/PLUNDER.COM new file mode 100755 index 00000000..15f55982 Binary files /dev/null and b/Source/Images/d_infocom/u0/PLUNDER.COM differ diff --git a/Source/Images/d_infocom/u0/PLUNDER.Z3 b/Source/Images/d_infocom/u0/PLUNDER.Z3 new file mode 100644 index 00000000..b5e076d3 Binary files /dev/null and b/Source/Images/d_infocom/u0/PLUNDER.Z3 differ diff --git a/Source/Images/d_infocom/u0/SEASTALK.COM b/Source/Images/d_infocom/u0/SEASTALK.COM new file mode 100755 index 00000000..62347efe Binary files /dev/null and b/Source/Images/d_infocom/u0/SEASTALK.COM differ diff --git a/Source/Images/d_infocom/u0/SEASTALK.Z3 b/Source/Images/d_infocom/u0/SEASTALK.Z3 new file mode 100644 index 00000000..a5d7c42b Binary files /dev/null and b/Source/Images/d_infocom/u0/SEASTALK.Z3 differ diff --git a/Source/Images/d_infocom/u0/SHERLOCK.Z5 b/Source/Images/d_infocom/u0/SHERLOCK.Z5 new file mode 100644 index 00000000..2f87cd86 Binary files /dev/null and b/Source/Images/d_infocom/u0/SHERLOCK.Z5 differ diff --git a/Source/Images/d_infocom/u0/SHOGUN.Z6 b/Source/Images/d_infocom/u0/SHOGUN.Z6 new file mode 100644 index 00000000..ac1b620a Binary files /dev/null and b/Source/Images/d_infocom/u0/SHOGUN.Z6 differ diff --git a/Source/Images/d_infocom/u0/SORCERER.COM b/Source/Images/d_infocom/u0/SORCERER.COM new file mode 100755 index 00000000..f90fbd39 Binary files /dev/null and b/Source/Images/d_infocom/u0/SORCERER.COM differ diff --git a/Source/Images/d_infocom/u0/SORCERER.Z3 b/Source/Images/d_infocom/u0/SORCERER.Z3 new file mode 100644 index 00000000..0925ddfc Binary files /dev/null and b/Source/Images/d_infocom/u0/SORCERER.Z3 differ diff --git a/Source/Images/d_infocom/u0/SPELLB.COM b/Source/Images/d_infocom/u0/SPELLB.COM new file mode 100755 index 00000000..86b887d0 Binary files /dev/null and b/Source/Images/d_infocom/u0/SPELLB.COM differ diff --git a/Source/Images/d_infocom/u0/SPELLB.Z3 b/Source/Images/d_infocom/u0/SPELLB.Z3 new file mode 100644 index 00000000..b4ba6fd2 Binary files /dev/null and b/Source/Images/d_infocom/u0/SPELLB.Z3 differ diff --git a/Source/Images/d_infocom/u0/STARCROS.COM b/Source/Images/d_infocom/u0/STARCROS.COM new file mode 100755 index 00000000..dc2b076e Binary files /dev/null and b/Source/Images/d_infocom/u0/STARCROS.COM differ diff --git a/Source/Images/d_infocom/u0/STARCROS.Z3 b/Source/Images/d_infocom/u0/STARCROS.Z3 new file mode 100644 index 00000000..71b419de Binary files /dev/null and b/Source/Images/d_infocom/u0/STARCROS.Z3 differ diff --git a/Source/Images/d_infocom/u0/STATIONF.COM b/Source/Images/d_infocom/u0/STATIONF.COM new file mode 100755 index 00000000..9ed4cf9a Binary files /dev/null and b/Source/Images/d_infocom/u0/STATIONF.COM differ diff --git a/Source/Images/d_infocom/u0/STATIONF.Z3 b/Source/Images/d_infocom/u0/STATIONF.Z3 new file mode 100644 index 00000000..f7bc4334 Binary files /dev/null and b/Source/Images/d_infocom/u0/STATIONF.Z3 differ diff --git a/Source/Images/d_infocom/u0/SUSPECT.COM b/Source/Images/d_infocom/u0/SUSPECT.COM new file mode 100755 index 00000000..3d929d07 Binary files /dev/null and b/Source/Images/d_infocom/u0/SUSPECT.COM differ diff --git a/Source/Images/d_infocom/u0/SUSPECT.Z3 b/Source/Images/d_infocom/u0/SUSPECT.Z3 new file mode 100644 index 00000000..b40920ec Binary files /dev/null and b/Source/Images/d_infocom/u0/SUSPECT.Z3 differ diff --git a/Source/Images/d_infocom/u0/SUSPEND.COM b/Source/Images/d_infocom/u0/SUSPEND.COM new file mode 100755 index 00000000..c32174c0 Binary files /dev/null and b/Source/Images/d_infocom/u0/SUSPEND.COM differ diff --git a/Source/Images/d_infocom/u0/SUSPEND.Z3 b/Source/Images/d_infocom/u0/SUSPEND.Z3 new file mode 100644 index 00000000..8bc66674 Binary files /dev/null and b/Source/Images/d_infocom/u0/SUSPEND.Z3 differ diff --git a/Source/Images/d_infocom/u0/TRINITY.Z4 b/Source/Images/d_infocom/u0/TRINITY.Z4 new file mode 100644 index 00000000..b5dfa4a0 Binary files /dev/null and b/Source/Images/d_infocom/u0/TRINITY.Z4 differ diff --git a/Source/Images/d_infocom/u0/WISHB.COM b/Source/Images/d_infocom/u0/WISHB.COM new file mode 100755 index 00000000..9717a1eb Binary files /dev/null and b/Source/Images/d_infocom/u0/WISHB.COM differ diff --git a/Source/Images/d_infocom/u0/WISHB.Z3 b/Source/Images/d_infocom/u0/WISHB.Z3 new file mode 100644 index 00000000..b3cc3b40 Binary files /dev/null and b/Source/Images/d_infocom/u0/WISHB.Z3 differ diff --git a/Source/Images/d_infocom/u0/WITNESS.COM b/Source/Images/d_infocom/u0/WITNESS.COM new file mode 100755 index 00000000..91636f53 Binary files /dev/null and b/Source/Images/d_infocom/u0/WITNESS.COM differ diff --git a/Source/Images/d_infocom/u0/WITNESS.Z3 b/Source/Images/d_infocom/u0/WITNESS.Z3 new file mode 100644 index 00000000..71b46590 Binary files /dev/null and b/Source/Images/d_infocom/u0/WITNESS.Z3 differ diff --git a/Source/Images/d_infocom/u0/ZORK0.Z6 b/Source/Images/d_infocom/u0/ZORK0.Z6 new file mode 100644 index 00000000..7ab221a1 Binary files /dev/null and b/Source/Images/d_infocom/u0/ZORK0.Z6 differ diff --git a/Source/Images/d_infocom/u0/ZORK1.COM b/Source/Images/d_infocom/u0/ZORK1.COM new file mode 100755 index 00000000..e8a9bfdb Binary files /dev/null and b/Source/Images/d_infocom/u0/ZORK1.COM differ diff --git a/Source/Images/d_infocom/u0/ZORK1.Z3 b/Source/Images/d_infocom/u0/ZORK1.Z3 new file mode 100644 index 00000000..2de2d996 Binary files /dev/null and b/Source/Images/d_infocom/u0/ZORK1.Z3 differ diff --git a/Source/Images/d_infocom/u0/ZORK2.COM b/Source/Images/d_infocom/u0/ZORK2.COM new file mode 100755 index 00000000..65c3c984 Binary files /dev/null and b/Source/Images/d_infocom/u0/ZORK2.COM differ diff --git a/Source/Images/d_infocom/u0/ZORK2.Z3 b/Source/Images/d_infocom/u0/ZORK2.Z3 new file mode 100644 index 00000000..635caaf2 Binary files /dev/null and b/Source/Images/d_infocom/u0/ZORK2.Z3 differ diff --git a/Source/Images/d_infocom/u0/ZORK3.COM b/Source/Images/d_infocom/u0/ZORK3.COM new file mode 100755 index 00000000..040debba Binary files /dev/null and b/Source/Images/d_infocom/u0/ZORK3.COM differ diff --git a/Source/Images/d_infocom/u0/ZORK3.Z3 b/Source/Images/d_infocom/u0/ZORK3.Z3 new file mode 100644 index 00000000..d02c9dbc Binary files /dev/null and b/Source/Images/d_infocom/u0/ZORK3.Z3 differ diff --git a/Source/Images/d_infocom/u0/ZORKNOTE.TXT b/Source/Images/d_infocom/u0/ZORKNOTE.TXT new file mode 100644 index 00000000..6601644e --- /dev/null +++ b/Source/Images/d_infocom/u0/ZORKNOTE.TXT @@ -0,0 +1,93 @@ + + Forward - MAP - July 2025 + + The following article describes how to configure the game Interpreters +(COM files) included with this distribution. Specifically this allows +the terminal control codes to be changed to your specific needs. + +Additional to the addresses below, the following address is relevant + +02D0h File name extension of the data file + must be 3 bytes long, fill with ascii spaces (20H) + +The following link containing the interpreter source code is also useful: +https://github.com/erkyrath/infocom-zcode-terps/blob/master/cpm80/zorkcpm.prn + +========================================================================= + + Customizing INFOCOM(tm) Games + notes on CP/M addresses + + I don't know wheather or not this is a duplicate effort, but since +I haven't found a similar listing....... + + When I first saw that Infocom was selling off all their CP/M compatible +games for only $14.95 I was overjoyed. Now I could buy all the titles that +I always wanted but could not really afford. Atlast, guilt free software. + + I ended up buying Zork1 for the Osborne I, Zork2 and Zork3 for the DEC +Rainbow, and Wishbringer for the Kaypro II. (My computer system is an Ampro +Little Board with Teac 55b and 55f drives. The terminal emulates a DEC +VT100. With my current hardware I can read or write to almost any 5.25" +format.) I thought everything was going to be so simple, use MULTIDSK and +MCOPY to transfer the programs to Ampro format and away I go! Wrong answer. +Although all the programs would execute, the terminal was confused beyond +belief. + + Some rainy day time with all the .com files and a trusty debugger +got me all the data I needed to unconfuse the terminal and allow me to +customize the display to just the way I wanted it. Now I'd like to 'share +the wealth' with anyone else bitten by the Infocom bug. + + The program starts off with an initial jump to 0200h, the start of +the actual program code. Next comes all the good stuff; + +0103h Charactors per line + a 78 charactor line is 4Eh + +0104h Lines per screen + a 23 line terminal (excluding status) is 17h + +0105h File name of the data file without file extent + must be 8 bytes long, fill with ascii spaces (20H) + if you have ZORK1.dat then 'ZORK1',20h,20h,20h goes here + +010Dh Screen LF after CR (1 = yes;0 = no) + +010Eh Printer LF after CR (1 = yes;0 = no) + +010Fh Inverse video offset + if you can add a 80h to the ascii charactor value to get + inverse video, this byte's for you + + The following strings start with a one byte charactor count, + the charactor string, and then a null fill (00H) + +0110h Terminal init. string + Clear screen, move cursor to lower left, set scroll region + VT100 = 12 1b 5b 32 4a 1b 5b 32 33 3b 31 48 1b 5b 32 3b 32 33 72 00 + +0131h Terminal reset string + Put everything back the way it was + +0152h Begin status line display + Move cursor to upper left and set video attribute (inverse, bold, etc) + +0173h End status line display + Move cursor to lower left and reset video attribute + +0194h Printer init. string + room for anything special you need to set up your printer + +0200h Start of the program code + + + I hope you have as much fun with the games as I have had, you can't +beat them at their close-out price. It's unfortunate that they have dropped +their CP/M support, I can't see buying a clone just to play with the +Leather Goddess. + + Gar Nelson + Olympia, Wa. + +GEnie address ==> G.NELSON diff --git a/Source/Images/d_infocom/u15/README.TXT b/Source/Images/d_infocom/u15/README.TXT new file mode 100644 index 00000000..8c2d55aa --- /dev/null +++ b/Source/Images/d_infocom/u15/README.TXT @@ -0,0 +1,8 @@ +VEZZA + +Please see official documentation at the following links + +https://sijnstra.itch.io/vezza + +https://gitlab.com/sijnstra1/vezza + diff --git a/Source/Images/d_infocom/u15/VEZZA-AV.COM b/Source/Images/d_infocom/u15/VEZZA-AV.COM new file mode 100644 index 00000000..e8d5c0ec Binary files /dev/null and b/Source/Images/d_infocom/u15/VEZZA-AV.COM differ diff --git a/Source/Images/d_infocom/u15/VEZZA-AX.COM b/Source/Images/d_infocom/u15/VEZZA-AX.COM new file mode 100644 index 00000000..ba3d7374 Binary files /dev/null and b/Source/Images/d_infocom/u15/VEZZA-AX.COM differ diff --git a/Source/Images/d_infocom/u15/VEZZA-B.COM b/Source/Images/d_infocom/u15/VEZZA-B.COM new file mode 100644 index 00000000..1627afca Binary files /dev/null and b/Source/Images/d_infocom/u15/VEZZA-B.COM differ diff --git a/Source/Images/d_infocom/u15/VEZZA-C2.COM b/Source/Images/d_infocom/u15/VEZZA-C2.COM new file mode 100644 index 00000000..fb5c80cf Binary files /dev/null and b/Source/Images/d_infocom/u15/VEZZA-C2.COM differ diff --git a/Source/Images/d_infocom/u15/VEZZA-CC.COM b/Source/Images/d_infocom/u15/VEZZA-CC.COM new file mode 100644 index 00000000..b5faea13 Binary files /dev/null and b/Source/Images/d_infocom/u15/VEZZA-CC.COM differ diff --git a/Source/Images/d_infocom/u15/VEZZA-FG.COM b/Source/Images/d_infocom/u15/VEZZA-FG.COM new file mode 100644 index 00000000..a3c2787b Binary files /dev/null and b/Source/Images/d_infocom/u15/VEZZA-FG.COM differ diff --git a/Source/Images/d_infocom/u15/VEZZA-RW.COM b/Source/Images/d_infocom/u15/VEZZA-RW.COM new file mode 100644 index 00000000..e8d5c0ec Binary files /dev/null and b/Source/Images/d_infocom/u15/VEZZA-RW.COM differ diff --git a/Source/Images/d_zsdos/u0/LICENSE.TXT b/Source/Images/d_zsdos/u0/LICENSE.TXT index e77696ae..b528e99a 100644 --- a/Source/Images/d_zsdos/u0/LICENSE.TXT +++ b/Source/Images/d_zsdos/u0/LICENSE.TXT @@ -1,339 +1,339 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 675 Mass Ave, Cambridge, MA 02139, USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) 19yy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) 19yy name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Source/Images/fd_aztecc.txt b/Source/Images/fd_aztecc.txt index 7192617c..f7e5d3c0 100644 --- a/Source/Images/fd_aztecc.txt +++ b/Source/Images/fd_aztecc.txt @@ -1,3 +1,4 @@ +@Label="Aztec C" # # Add the ReadMe document # diff --git a/Source/Images/fd_bascomp.txt b/Source/Images/fd_bascomp.txt index 950aa805..8a7f6a97 100644 --- a/Source/Images/fd_bascomp.txt +++ b/Source/Images/fd_bascomp.txt @@ -1,3 +1,4 @@ +@Label="Microsoft BASIC" # # Add the ReadMe document # diff --git a/Source/Images/fd_bp.txt b/Source/Images/fd_bp.txt deleted file mode 100644 index d09f3fdd..00000000 --- a/Source/Images/fd_bp.txt +++ /dev/null @@ -1,55 +0,0 @@ -# -# Add ZSystem images -# -../BPBIOS/*.img 0: -../BPBIOS/*.rel 0: -../BPBIOS/*.zrl 0: -../BPBIOS/*.zex 0: -../BPBIOS/bpbuild.com 0: -# -# Add RomWBW utilities -# -#../../Binary/Apps/*.com 15: -../../Binary/Apps/assign.com 15: -#../../Binary/Apps/bbcbasic.com 15: -#../../Binary/Apps/bbcbasic.txt 15: -../../Binary/Apps/cpuspd.com 15: -../../Binary/Apps/reboot.com 15: -../../Binary/Apps/fat.com 15: -../../Binary/Apps/fdu.com 15: -../../Binary/Apps/fdu.doc 15: -../../Binary/Apps/format.com 15: -../../Binary/Apps/mode.com 15: -../../Binary/Apps/rtc.com 15: -../../Binary/Apps/survey.com 15: -../../Binary/Apps/syscopy.com 15: -../../Binary/Apps/sysgen.com 15: -../../Binary/Apps/talk.com 15: -../../Binary/Apps/htalk.com 15: -../../Binary/Apps/tbasic.com 15: -../../Binary/Apps/timer.com 15: -../../Binary/Apps/tune.com 15: -../../Binary/Apps/xm.com 15: -../../Binary/Apps/zmp.com 15: -../../Binary/Apps/zmp.hlp 15: -../../Binary/Apps/zmp.doc 10: -../../Binary/Apps/zmp.cfg 15: -../../Binary/Apps/zmp.fon 15: -../../Binary/Apps/zmxfer.ovr 15: -../../Binary/Apps/zmterm.ovr 15: -../../Binary/Apps/zminit.ovr 15: -../../Binary/Apps/zmconfig.ovr 15: -../../Binary/Apps/zmd.com 15: -../../Binary/Apps/vgmplay.com 15: -# -# Add Common Applications -# -Common/All/u10/*.* 10: -Common/All/u14/*.* 14: -Common/All/u15/*.* 15: -Common/CPM22/*.* 15: -Common/Z/u14/*.* 14: -Common/Z/u15/*.* 15: -Common/Z3/u10/*.* 10: -Common/Z3/u14/*.* 14: -Common/Z3/u15/*.* 15: diff --git a/Source/Images/fd_cobol.txt b/Source/Images/fd_cobol.txt index 92e2f5f2..4b6f0c8a 100644 --- a/Source/Images/fd_cobol.txt +++ b/Source/Images/fd_cobol.txt @@ -1,3 +1,4 @@ +@Label="Microsoft COBOL" # # Add the ReadMe document # diff --git a/Source/Images/fd_cowgol.txt b/Source/Images/fd_cowgol.txt index d90c4bdd..3100d73b 100644 --- a/Source/Images/fd_cowgol.txt +++ b/Source/Images/fd_cowgol.txt @@ -1,3 +1,4 @@ +@Label="Cowgol" # # Add the ReadMe document # diff --git a/Source/Images/fd_cpm22.txt b/Source/Images/fd_cpm22.txt index 97ea8c61..cd82e472 100644 --- a/Source/Images/fd_cpm22.txt +++ b/Source/Images/fd_cpm22.txt @@ -1,3 +1,5 @@ +@Label="CP/M 2.2" +@SysImage="../CPM22/cpm_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/fd_cpm3.txt b/Source/Images/fd_cpm3.txt index aea0d879..638d38d6 100644 --- a/Source/Images/fd_cpm3.txt +++ b/Source/Images/fd_cpm3.txt @@ -1,3 +1,5 @@ +@Label="CP/M 3" +@SysImage="../CPM3/cpmldr.sys" # # Add the ReadMe document # diff --git a/Source/Images/fd_fortran.txt b/Source/Images/fd_fortran.txt index 2bda53c7..4ced49e4 100644 --- a/Source/Images/fd_fortran.txt +++ b/Source/Images/fd_fortran.txt @@ -1,3 +1,4 @@ +@Label="Microsoft Fortran" # # Add the ReadMe document # diff --git a/Source/Images/fd_games.txt b/Source/Images/fd_games.txt index f4495305..a3e9527f 100644 --- a/Source/Images/fd_games.txt +++ b/Source/Images/fd_games.txt @@ -1,3 +1,4 @@ +@Label="Games" # # Add the ReadMe document # diff --git a/Source/Images/fd_hitechc.txt b/Source/Images/fd_hitechc.txt index b20cdc4a..637d5515 100644 --- a/Source/Images/fd_hitechc.txt +++ b/Source/Images/fd_hitechc.txt @@ -1,3 +1,4 @@ +@Label="HITECH-C" # # Add the ReadMe document # diff --git a/Source/Images/fd_nzcom.txt b/Source/Images/fd_nzcom.txt index f80cc0d5..b52c0905 100644 --- a/Source/Images/fd_nzcom.txt +++ b/Source/Images/fd_nzcom.txt @@ -1,3 +1,5 @@ +@Label="NZ-COM" +@SysImage="../ZSDOS/zsys_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/fd_qpm.txt b/Source/Images/fd_qpm.txt index 53134fe9..268ccf5f 100644 --- a/Source/Images/fd_qpm.txt +++ b/Source/Images/fd_qpm.txt @@ -1,3 +1,5 @@ +@Label="QP/M 2.7" +@SysImage="../QPM/qpm_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/fd_tpascal.txt b/Source/Images/fd_tpascal.txt index 951e7dd4..e73ddc4f 100644 --- a/Source/Images/fd_tpascal.txt +++ b/Source/Images/fd_tpascal.txt @@ -1,3 +1,4 @@ +@Label="Turbo Pascal" # # Add the ReadMe document # diff --git a/Source/Images/fd_ws4.txt b/Source/Images/fd_ws4.txt index d10b7891..a7406958 100644 --- a/Source/Images/fd_ws4.txt +++ b/Source/Images/fd_ws4.txt @@ -1,3 +1,4 @@ +@Label="WordStar 4" # # Add the ZDE binaries # diff --git a/Source/Images/fd_z3plus.txt b/Source/Images/fd_z3plus.txt index f8445693..272d6e37 100644 --- a/Source/Images/fd_z3plus.txt +++ b/Source/Images/fd_z3plus.txt @@ -1,63 +1,65 @@ -# -# Add the ReadMe document -# -d_z3plus/ReadMe.txt 0: -# -# Add files from CPM3 build -# -../CPM3/cpmldr.com 0: -../CPM3/cpmldr.sys 0: -../CPM3/ccp.com 0: -../CPM3/gencpm.com 0: -../CPM3/genres.dat 0: -../CPM3/genbnk.dat 0: -../CPM3/bios3.spr 0: -../CPM3/bnkbios3.spr 0: -../CPM3/bdos3.spr 0: -../CPM3/bnkbdos3.spr 0: -../CPM3/resbdos3.spr 0: -../CPM3/cpm3res.sys 0: -../CPM3/cpm3bnk.sys 0: -../CPM3/gencpm.dat 0: -../CPM3/cpm3.sys 0: -../CPM3/readme.1st 0: -../CPM3/cpm3fix.pat 0: -# -# Include CP/M 3 files -# -d_cpm3/u0/*.COM 15: -d_cpm3/u0/SUBMIT.COM 0: -d_cpm3/u0/HELP.HLP 0: -# -# Add RomWBW utilities -# -../../Binary/Apps/assign.com 15: -../../Binary/Apps/cpuspd.com 15: -../../Binary/Apps/reboot.com 15: -../../Binary/Apps/fat.com 15: -../../Binary/Apps/fdu.com 15: -../../Binary/Apps/mode.com 15: -../../Binary/Apps/rtc.com 15: -../../Binary/Apps/survey.com 15: -../../Binary/Apps/syscopy.com 15: -../../Binary/Apps/sysgen.com 15: -../../Binary/Apps/timer.com 15: -../../Binary/Apps/xm.com 15: -# -# Add Shared NZCOM/Z3PLUS -# -Common/NZ3PLUS/u10/*.* 10: -Common/NZ3PLUS/u14/*.* 14: -Common/NZ3PLUS/u15/*.* 15: -# -# Add Common Applications -# -# Common/All/u10/*.* 10: -# Common/All/u14/*.* 14: -# Common/All/u15/*.* 15: -Common/CPM3/*.* 15: -Common/Z/u14/*.* 14: -Common/Z/u15/*.* 15: -# Common/Z3/u10/*.* 10: -Common/Z3/u14/*.* 14: -Common/Z3/u15/*.* 15: +@Label="Z3PLUS" +@SysImage="../CPM3/cpmldr.sys" +# +# Add the ReadMe document +# +d_z3plus/ReadMe.txt 0: +# +# Add files from CPM3 build +# +../CPM3/cpmldr.com 0: +../CPM3/cpmldr.sys 0: +../CPM3/ccp.com 0: +../CPM3/gencpm.com 0: +../CPM3/genres.dat 0: +../CPM3/genbnk.dat 0: +../CPM3/bios3.spr 0: +../CPM3/bnkbios3.spr 0: +../CPM3/bdos3.spr 0: +../CPM3/bnkbdos3.spr 0: +../CPM3/resbdos3.spr 0: +../CPM3/cpm3res.sys 0: +../CPM3/cpm3bnk.sys 0: +../CPM3/gencpm.dat 0: +../CPM3/cpm3.sys 0: +../CPM3/readme.1st 0: +../CPM3/cpm3fix.pat 0: +# +# Include CP/M 3 files +# +d_cpm3/u0/*.COM 15: +d_cpm3/u0/SUBMIT.COM 0: +d_cpm3/u0/HELP.HLP 0: +# +# Add RomWBW utilities +# +../../Binary/Apps/assign.com 15: +../../Binary/Apps/cpuspd.com 15: +../../Binary/Apps/reboot.com 15: +../../Binary/Apps/fat.com 15: +../../Binary/Apps/fdu.com 15: +../../Binary/Apps/mode.com 15: +../../Binary/Apps/rtc.com 15: +../../Binary/Apps/survey.com 15: +../../Binary/Apps/syscopy.com 15: +../../Binary/Apps/sysgen.com 15: +../../Binary/Apps/timer.com 15: +../../Binary/Apps/xm.com 15: +# +# Add Shared NZCOM/Z3PLUS +# +Common/NZ3PLUS/u10/*.* 10: +Common/NZ3PLUS/u14/*.* 14: +Common/NZ3PLUS/u15/*.* 15: +# +# Add Common Applications +# +# Common/All/u10/*.* 10: +# Common/All/u14/*.* 14: +# Common/All/u15/*.* 15: +Common/CPM3/*.* 15: +Common/Z/u14/*.* 14: +Common/Z/u15/*.* 15: +# Common/Z3/u10/*.* 10: +Common/Z3/u14/*.* 14: +Common/Z3/u15/*.* 15: diff --git a/Source/Images/fd_z80asm.txt b/Source/Images/fd_z80asm.txt index 9a42beca..b7bdcad3 100644 --- a/Source/Images/fd_z80asm.txt +++ b/Source/Images/fd_z80asm.txt @@ -1,3 +1,4 @@ +@Label="SLR Z80ASM" # # Add the ReadMe document # diff --git a/Source/Images/fd_zpm3.txt b/Source/Images/fd_zpm3.txt index f91170d8..999dea15 100644 --- a/Source/Images/fd_zpm3.txt +++ b/Source/Images/fd_zpm3.txt @@ -1,3 +1,5 @@ +@Label="ZPM3" +@SysImage="../ZPM3/zpmldr.sys" # # Add the ReadMe document # diff --git a/Source/Images/fd_zsdos.txt b/Source/Images/fd_zsdos.txt index 00160939..ef1e493f 100644 --- a/Source/Images/fd_zsdos.txt +++ b/Source/Images/fd_zsdos.txt @@ -1,3 +1,5 @@ +@Label="ZSDOS 1.1" +@SysImage="../ZSDOS/zsys_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/hd_aztecc.txt b/Source/Images/hd_aztecc.txt index 7192617c..f7e5d3c0 100644 --- a/Source/Images/hd_aztecc.txt +++ b/Source/Images/hd_aztecc.txt @@ -1,3 +1,4 @@ +@Label="Aztec C" # # Add the ReadMe document # diff --git a/Source/Images/hd_bascomp.txt b/Source/Images/hd_bascomp.txt index 950aa805..8a7f6a97 100644 --- a/Source/Images/hd_bascomp.txt +++ b/Source/Images/hd_bascomp.txt @@ -1,3 +1,4 @@ +@Label="Microsoft BASIC" # # Add the ReadMe document # diff --git a/Source/Images/hd_blank.txt b/Source/Images/hd_blank.txt index 64c9818a..6e002ab6 100644 --- a/Source/Images/hd_blank.txt +++ b/Source/Images/hd_blank.txt @@ -1,3 +1,4 @@ +@Label="Blank" # # Blank disk template # diff --git a/Source/Images/hd_bp.txt b/Source/Images/hd_bp.txt index d293a1ca..4cc81913 100644 --- a/Source/Images/hd_bp.txt +++ b/Source/Images/hd_bp.txt @@ -1,3 +1,5 @@ +@Label="BPBIOS" +@SysImage="../ZSDOS/zsys_wbw.sys" # # Add ZSystem images # diff --git a/Source/Images/hd_cobol.txt b/Source/Images/hd_cobol.txt index 92e2f5f2..4b6f0c8a 100644 --- a/Source/Images/hd_cobol.txt +++ b/Source/Images/hd_cobol.txt @@ -1,3 +1,4 @@ +@Label="Microsoft COBOL" # # Add the ReadMe document # diff --git a/Source/Images/hd_cowgol.txt b/Source/Images/hd_cowgol.txt index d90c4bdd..3100d73b 100644 --- a/Source/Images/hd_cowgol.txt +++ b/Source/Images/hd_cowgol.txt @@ -1,3 +1,4 @@ +@Label="Cowgol" # # Add the ReadMe document # diff --git a/Source/Images/hd_cpm22.txt b/Source/Images/hd_cpm22.txt index 901a05b1..b928c473 100644 --- a/Source/Images/hd_cpm22.txt +++ b/Source/Images/hd_cpm22.txt @@ -1,3 +1,5 @@ +@Label="CP/M 2.2" +@SysImage="../CPM22/cpm_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/hd_cpm3.txt b/Source/Images/hd_cpm3.txt index 28f82aad..bdf7e5a5 100644 --- a/Source/Images/hd_cpm3.txt +++ b/Source/Images/hd_cpm3.txt @@ -1,3 +1,5 @@ +@Label="CP/M 3" +@SysImage="../CPM3/cpmldr.sys" # # Add the ReadMe document # diff --git a/Source/Images/hd_dos65.txt b/Source/Images/hd_dos65.txt index 75ee31d7..3be0ed14 100644 --- a/Source/Images/hd_dos65.txt +++ b/Source/Images/hd_dos65.txt @@ -1,3 +1,5 @@ +@Label="DOS65" +@SysImage="../ZSDOS/zsys_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/hd_fortran.txt b/Source/Images/hd_fortran.txt index 2bda53c7..4ced49e4 100644 --- a/Source/Images/hd_fortran.txt +++ b/Source/Images/hd_fortran.txt @@ -1,3 +1,4 @@ +@Label="Microsoft Fortran" # # Add the ReadMe document # diff --git a/Source/Images/hd_games.txt b/Source/Images/hd_games.txt index f4495305..a3e9527f 100644 --- a/Source/Images/hd_games.txt +++ b/Source/Images/hd_games.txt @@ -1,3 +1,4 @@ +@Label="Games" # # Add the ReadMe document # diff --git a/Source/Images/hd_hitechc.txt b/Source/Images/hd_hitechc.txt index b20cdc4a..637d5515 100644 --- a/Source/Images/hd_hitechc.txt +++ b/Source/Images/hd_hitechc.txt @@ -1,3 +1,4 @@ +@Label="HITECH-C" # # Add the ReadMe document # diff --git a/Source/Images/hd_infocom.txt b/Source/Images/hd_infocom.txt new file mode 100644 index 00000000..cbc58f34 --- /dev/null +++ b/Source/Images/hd_infocom.txt @@ -0,0 +1,5 @@ +@Label="Infocom Games" +# +# Add the ReadMe document +# +d_infocom/Readme.txt 0: diff --git a/Source/Images/hd_msxroms1.txt b/Source/Images/hd_msxroms1.txt index f0966942..b2b07e13 100644 --- a/Source/Images/hd_msxroms1.txt +++ b/Source/Images/hd_msxroms1.txt @@ -1,3 +1,4 @@ +@Label="MSX ROMS 1" # # Add the ReadMe document # diff --git a/Source/Images/hd_msxroms2.txt b/Source/Images/hd_msxroms2.txt index 8bbd751c..868e8652 100644 --- a/Source/Images/hd_msxroms2.txt +++ b/Source/Images/hd_msxroms2.txt @@ -1,3 +1,4 @@ +@Label="MSX ROMS 2" # # Add the ReadMe document # diff --git a/Source/Images/hd_nzcom.txt b/Source/Images/hd_nzcom.txt index b4b7b5df..60f5f686 100644 --- a/Source/Images/hd_nzcom.txt +++ b/Source/Images/hd_nzcom.txt @@ -1,3 +1,5 @@ +@Label="NZ-COM" +@SysImage="../ZSDOS/zsys_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/hd_qpm.txt b/Source/Images/hd_qpm.txt index a1dbf770..0e66f92d 100644 --- a/Source/Images/hd_qpm.txt +++ b/Source/Images/hd_qpm.txt @@ -1,3 +1,5 @@ +@Label="QP/M 2.7" +@SysImage="../QPM/qpm_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Images/hd_tpascal.txt b/Source/Images/hd_tpascal.txt index 951e7dd4..e73ddc4f 100644 --- a/Source/Images/hd_tpascal.txt +++ b/Source/Images/hd_tpascal.txt @@ -1,3 +1,4 @@ +@Label="Turbo Pascal" # # Add the ReadMe document # diff --git a/Source/Images/hd_ws4.txt b/Source/Images/hd_ws4.txt index d10b7891..a7406958 100644 --- a/Source/Images/hd_ws4.txt +++ b/Source/Images/hd_ws4.txt @@ -1,3 +1,4 @@ +@Label="WordStar 4" # # Add the ZDE binaries # diff --git a/Source/Images/hd_z3plus.txt b/Source/Images/hd_z3plus.txt index 05956cd6..3f738c5e 100644 --- a/Source/Images/hd_z3plus.txt +++ b/Source/Images/hd_z3plus.txt @@ -1,102 +1,104 @@ -# -# Add the ReadMe document -# -d_z3plus/ReadMe.txt 0: -# -# Add files from CPM3 build -# -../CPM3/cpmldr.com 0: -../CPM3/cpmldr.sys 0: -../CPM3/ccp.com 0: -../CPM3/gencpm.com 0: -../CPM3/genres.dat 0: -../CPM3/genbnk.dat 0: -../CPM3/bios3.spr 0: -../CPM3/bnkbios3.spr 0: -../CPM3/bdos3.spr 0: -../CPM3/bnkbdos3.spr 0: -../CPM3/resbdos3.spr 0: -../CPM3/cpm3res.sys 0: -../CPM3/cpm3bnk.sys 0: -../CPM3/gencpm.dat 0: -../CPM3/cpm3.sys 0: -../CPM3/readme.1st 0: -../CPM3/cpm3fix.pat 0: -# -# Include CP/M 3 files -# -d_cpm3/u0/*.COM 15: -d_cpm3/u0/SUBMIT.COM 0: -d_cpm3/u0/HELP.HLP 0: -# -# Add RomWBW utilities -# -#../../Binary/Apps/*.com 15: -../../Binary/Apps/assign.com 15: -../../Binary/Apps/bbcbasic.com 15: -../../Binary/Apps/bbcbasic.txt 10: -../../Binary/Apps/cpuspd.com 15: -../../Binary/Apps/reboot.com 15: -../../Binary/Apps/copysl.com 15: -../../Binary/Apps/copysl.doc 10: -../../Binary/Apps/fat.com 15: -../../Binary/Apps/fdu.com 15: -../../Binary/Apps/fdu.doc 10: -../../Binary/Apps/format.com 15: -../../Binary/Apps/mode.com 15: -../../Binary/Apps/rtc.com 15: -../../Binary/Apps/slabel.com 15: -../../Binary/Apps/survey.com 15: -../../Binary/Apps/syscopy.com 15: -../../Binary/Apps/sysgen.com 15: -../../Binary/Apps/talk.com 15: -../../Binary/Apps/htalk.com 15: -../../Binary/Apps/tbasic.com 15: -../../Binary/Apps/timer.com 15: -../../Binary/Apps/tune.com 15: -../../Binary/Apps/xm.com 15: -../../Binary/Apps/zmp.com 15: -../../Binary/Apps/zmp.hlp 15: -../../Binary/Apps/zmp.doc 10: -../../Binary/Apps/zmp.cfg 15: -../../Binary/Apps/zmp.fon 15: -../../Binary/Apps/zmxfer.ovr 15: -../../Binary/Apps/zmterm.ovr 15: -../../Binary/Apps/zminit.ovr 15: -../../Binary/Apps/zmconfig.ovr 15: -../../Binary/Apps/zmd.com 15: -../../Binary/Apps/vgmplay.com 15: -# -../../Binary/Apps/Test/*.com 2: -../../Binary/Apps/Test/*.doc 2: -Common/Test/*.* 2: -# -# Add Tune sample files -# -../../Binary/Apps/Tunes/*.pt? 3: -../../Binary/Apps/Tunes/*.mym 3: -../../Binary/Apps/Tunes/*.vgm 3: -# -# Add CPNET client files -# -../../Binary/CPNET/cpn3*.lbr 4: -../../Binary/CPNET/ReadMe.txt 4: -# -# Add Shared NZCOM/Z3PLUS -# -Common/NZ3PLUS/u10/*.* 10: -Common/NZ3PLUS/u14/*.* 14: -Common/NZ3PLUS/u15/*.* 15: -# -# Add Common Applications -# -Common/All/u10/*.* 10: -Common/All/u14/*.* 14: -Common/All/u15/*.* 15: -Common/CPM3/*.* 15: -Common/Z/u14/*.* 14: -Common/Z/u15/*.* 15: -Common/Z3/u10/*.* 10: -Common/Z3/u14/*.* 14: -Common/Z3/u15/*.* 15: -Common/SIMH/*.* 13: +@Label="Z3PLUS" +@SysImage="../CPM3/cpmldr.sys" +# +# Add the ReadMe document +# +d_z3plus/ReadMe.txt 0: +# +# Add files from CPM3 build +# +../CPM3/cpmldr.com 0: +../CPM3/cpmldr.sys 0: +../CPM3/ccp.com 0: +../CPM3/gencpm.com 0: +../CPM3/genres.dat 0: +../CPM3/genbnk.dat 0: +../CPM3/bios3.spr 0: +../CPM3/bnkbios3.spr 0: +../CPM3/bdos3.spr 0: +../CPM3/bnkbdos3.spr 0: +../CPM3/resbdos3.spr 0: +../CPM3/cpm3res.sys 0: +../CPM3/cpm3bnk.sys 0: +../CPM3/gencpm.dat 0: +../CPM3/cpm3.sys 0: +../CPM3/readme.1st 0: +../CPM3/cpm3fix.pat 0: +# +# Include CP/M 3 files +# +d_cpm3/u0/*.COM 15: +d_cpm3/u0/SUBMIT.COM 0: +d_cpm3/u0/HELP.HLP 0: +# +# Add RomWBW utilities +# +#../../Binary/Apps/*.com 15: +../../Binary/Apps/assign.com 15: +../../Binary/Apps/bbcbasic.com 15: +../../Binary/Apps/bbcbasic.txt 10: +../../Binary/Apps/cpuspd.com 15: +../../Binary/Apps/reboot.com 15: +../../Binary/Apps/copysl.com 15: +../../Binary/Apps/copysl.doc 10: +../../Binary/Apps/fat.com 15: +../../Binary/Apps/fdu.com 15: +../../Binary/Apps/fdu.doc 10: +../../Binary/Apps/format.com 15: +../../Binary/Apps/mode.com 15: +../../Binary/Apps/rtc.com 15: +../../Binary/Apps/slabel.com 15: +../../Binary/Apps/survey.com 15: +../../Binary/Apps/syscopy.com 15: +../../Binary/Apps/sysgen.com 15: +../../Binary/Apps/talk.com 15: +../../Binary/Apps/htalk.com 15: +../../Binary/Apps/tbasic.com 15: +../../Binary/Apps/timer.com 15: +../../Binary/Apps/tune.com 15: +../../Binary/Apps/xm.com 15: +../../Binary/Apps/zmp.com 15: +../../Binary/Apps/zmp.hlp 15: +../../Binary/Apps/zmp.doc 10: +../../Binary/Apps/zmp.cfg 15: +../../Binary/Apps/zmp.fon 15: +../../Binary/Apps/zmxfer.ovr 15: +../../Binary/Apps/zmterm.ovr 15: +../../Binary/Apps/zminit.ovr 15: +../../Binary/Apps/zmconfig.ovr 15: +../../Binary/Apps/zmd.com 15: +../../Binary/Apps/vgmplay.com 15: +# +../../Binary/Apps/Test/*.com 2: +../../Binary/Apps/Test/*.doc 2: +Common/Test/*.* 2: +# +# Add Tune sample files +# +../../Binary/Apps/Tunes/*.pt? 3: +../../Binary/Apps/Tunes/*.mym 3: +../../Binary/Apps/Tunes/*.vgm 3: +# +# Add CPNET client files +# +../../Binary/CPNET/cpn3*.lbr 4: +../../Binary/CPNET/ReadMe.txt 4: +# +# Add Shared NZCOM/Z3PLUS +# +Common/NZ3PLUS/u10/*.* 10: +Common/NZ3PLUS/u14/*.* 14: +Common/NZ3PLUS/u15/*.* 15: +# +# Add Common Applications +# +Common/All/u10/*.* 10: +Common/All/u14/*.* 14: +Common/All/u15/*.* 15: +Common/CPM3/*.* 15: +Common/Z/u14/*.* 14: +Common/Z/u15/*.* 15: +Common/Z3/u10/*.* 10: +Common/Z3/u14/*.* 14: +Common/Z3/u15/*.* 15: +Common/SIMH/*.* 13: diff --git a/Source/Images/hd_z80asm.txt b/Source/Images/hd_z80asm.txt index 9a42beca..b7bdcad3 100644 --- a/Source/Images/hd_z80asm.txt +++ b/Source/Images/hd_z80asm.txt @@ -1,3 +1,4 @@ +@Label="SLR Z80ASM" # # Add the ReadMe document # diff --git a/Source/Images/hd_zpm3.txt b/Source/Images/hd_zpm3.txt index e9391025..96e38390 100644 --- a/Source/Images/hd_zpm3.txt +++ b/Source/Images/hd_zpm3.txt @@ -1,3 +1,5 @@ +@Label="ZPM3" +@SysImage="../ZPM3/zpmldr.sys" # # Add the ReadMe document # diff --git a/Source/Images/hd_zsdos.txt b/Source/Images/hd_zsdos.txt index e35aaa35..7dc8526c 100644 --- a/Source/Images/hd_zsdos.txt +++ b/Source/Images/hd_zsdos.txt @@ -1,3 +1,5 @@ +@Label="ZSDOS 1.1" +@SysImage="../ZSDOS/zsys_wbw.sys" # # Add the ReadMe document # diff --git a/Source/Makefile b/Source/Makefile index c6b219b2..2d4f1e41 100644 --- a/Source/Makefile +++ b/Source/Makefile @@ -23,8 +23,10 @@ shared: $(MAKE) --directory ZCPR $(ACTION) $(MAKE) --directory ZCPR-DJ $(ACTION) $(MAKE) --directory ZSDOS $(ACTION) + $(MAKE) --directory ZSDOS2 $(ACTION) $(MAKE) --directory CPM3 $(ACTION) $(MAKE) --directory ZPM3 $(ACTION) + $(MAKE) --directory BPBIOS $(ACTION) $(MAKE) --directory CPNET $(ACTION) $(MAKE) --directory pSys $(ACTION) $(MAKE) --directory Apps $(ACTION) @@ -33,9 +35,6 @@ shared: $(MAKE) --directory Fonts $(ACTION) $(MAKE) --directory RomDsk $(ACTION) -bp: - $(MAKE) --directory BPBIOS $(ACTION) - images: $(MAKE) --directory Images $(ACTION) diff --git a/Source/ZSDOS2/Build.cmd b/Source/ZSDOS2/Build.cmd new file mode 100644 index 00000000..6be69ba9 --- /dev/null +++ b/Source/ZSDOS2/Build.cmd @@ -0,0 +1,12 @@ +@echo off +setlocal + +set TOOLS=../../Tools + +set PATH=%TOOLS%\tasm32;%TOOLS%\zxcc;%PATH% + +set TASMTABS=%TOOLS%\tasm32 + +set CPMDIR80=%TOOLS%/cpm/ + +zxcc Z80ASM -ZSDOS2/6FS || exit /b diff --git a/Source/ZSDOS2/Clean.cmd b/Source/ZSDOS2/Clean.cmd new file mode 100644 index 00000000..12d1c7de --- /dev/null +++ b/Source/ZSDOS2/Clean.cmd @@ -0,0 +1,6 @@ +@echo off +setlocal + +if exist *.lst del *.lst +if exist *.rel del *.rel +if exist *.sym del *.sym diff --git a/Source/ZSDOS2/Makefile b/Source/ZSDOS2/Makefile new file mode 100644 index 00000000..4fecd9e8 --- /dev/null +++ b/Source/ZSDOS2/Makefile @@ -0,0 +1,5 @@ +TOOLS = ../../Tools + +OBJECTS = zsdos2.rel + +include $(TOOLS)/Makefile.inc diff --git a/Source/ZSDOS2/zsdos2.z80 b/Source/ZSDOS2/zsdos2.z80 new file mode 100644 index 00000000..c40fbd4a --- /dev/null +++ b/Source/ZSDOS2/zsdos2.z80 @@ -0,0 +1,4116 @@ + TITLE "ZSDOS 2" +;************************************************************************ +;* Z S D O S v2 * +;* A banked CP/M 2.2 compatible replacement BDOS * +;* by Harold F. Bower and Cameron W. Cotrill * +;*----------------------------------------------------------------------* +;* Disassembly: jxl May 2025 * +;* public release 1.0 May 2025 * +;* see remarks at the end * +;*----------------------------------------------------------------------* +;* Assemble with SLR Z80ASM * +;* * +;* A>Z80ASM ZSDOS2/6 * +;************************************************************************ + + + NAME ('DOS') + + +VER EQU 20H +REV MACRO + DEFB '27g' + ENDM + +DATE MACRO + DEFB '1993' + ENDM + + +;::::: DEFINITIONS + + +RAMLOW EQU 0000H ; Start address memory + + ; Bios entry points + + COMMON /_BIOS_/ +BIOS EQU $ + + CSEG + +; BOOT EQU BIOS+0000H ; Cold Boot +; WBOOT EQU BIOS+0003H ; Warm Boot +CONST EQU BIOS+0006H ; Console Status +CONIN EQU BIOS+0009H ; Console Input +CONOUT EQU BIOS+000CH ; Console Output +LIST EQU BIOS+000FH ; List Output +PUNCH EQU BIOS+0012H ; Punch Output +READER EQU BIOS+0015H ; Reader Input +HOME EQU BIOS+0018H ; Home Disk +SELDSK EQU BIOS+001BH ; Select Disk +SETTRK EQU BIOS+001EH ; Select Track +SETSEC EQU BIOS+0021H ; Select Sector +SETDMA EQU BIOS+0024H ; Set DMA Address +READ EQU BIOS+0027H ; Read 128 Bytes +WRITE EQU BIOS+002AH ; Write 128 Bytes +; LISTST EQU BIOS+002DH ; List Status +SECTRN EQU BIOS+0030H ; Sector Translation +MOVE EQU BIOS+004BH ; (Interbank) move +SELMEM EQU BIOS+0051H ; Select memory bank +XMOVE EQU BIOS+0057H ; Set memory banks for MOVE +RETMEM EQU BIOS+0075H ; Return current memory bank + +OTPABK EQU BIOS+082H ; offset TPA bank (from B/P Bios base) +OSYSBK EQU BIOS+083H ; offset SYS bank +OZ3ENV EQU BIOS+098H ; offset Z3ENV + + + ; Control chars + +CONTC EQU 03H ; Key to generate warm boot +CONTH EQU 08H ; Backspace +TAB EQU 09H ; Tab +LF EQU 0AH ; Line feed +CR EQU 0DH ; Carriage return +CONTP EQU 10H ; Set/reset print flag +CONTR EQU 12H ; Retype line +CONTS EQU 13H ; Stop console output +CONTX EQU 18H ; Delete line (backspaces) +CONTU EQU 15H ; Same as Control-X +RUBOUT EQU 7FH ; Delete last char + + + ; Disk related + +MAXEXT EQU 1FH ; Maximum extent number +MAXMOD EQU 3FH ; Maximum data module number +TDCKSM EQU 91H ; Checksum of !!!TIME&.DAT + + + ; Attribute bits + +PUBATT EQU 2 ; Public attribute offset +PSFATT EQU 7 ; Public/system file (internal only) +WHLATT EQU 8 ; Wheel protect attribute offset +ROATT EQU 9 ; Read only attribute offset +SYSATT EQU 10 ; System attribute offset +ARCATT EQU 11 ; Archive attribute offset + + + ; FCB positions + +FCBEXT EQU 12 ; Extent number +FCBUSR EQU 13 ; User valid at offset 13 if set (internal) +FCBMOD EQU 14 ; Data module number - D7 used as unmod flag +FCBREC EQU 15 ; Record number +NXTREC EQU 32 ; Next record number + + + ; Internal + +; ZSDOS 1 = 6D / ZSDOS 2 = ED +FLGBITS EQU 11101101B ; PUBlic On, P/P Write Off, R/O On, + ; Fast Relog On, Disk Chg Warning Off, + ; Path On, No System Path On + ; (Reserved) On + + + + ;_______________________// Non-Banked // + + DEFB 'ZSDOS',VER/16+'0' + + ; ZSDOS entry point + JP ENTRY ; jump to start of program code + + +;::::: DATA / CONFIGURATION AREA + + ; CP/M 2.2 compatible error vector table +STBDSC: DEFW ERROR ; Bad sector message +STSEL: DEFW ERROR ; Select error +STRO: DEFW ERROR ; Drive read only +SFILRO: DEFW ERROR ; File read only + + ; External Path +PATH: DEFW PATHAD ; Path address for file open, 0 if no Path + + ; Wheel Byte pointer +WHEEL: DEFW 0 ; Address of Wheel byte, 0 if none + + ; User configuration byte(s) +FLAGS: DEFB FLGBITS ; Flag byte (see above) +STFLAG: DEFB 0110B ; Stamp enable/disable + ; bit2= Modify, bit1= Create, bit0= Access + + ; Dispatch table for time/date stamp routines +GSTIME: DEFW DOTDER ; Address of get/set time/date routine + DEFW DOTDER +UNLOAD: DEFW 0 ; Pointer to remove time stamp routine +IPATH: DEFW PATHAD ; copy to restore Internal Path (see ZSCFG2) + + ;----- + +TABCNT: DEFB 0 ; tab counter +TABCX1: DEFB 0 ; temporary tab counter (used by RDBUF) +FCONTP: DEFB 0 ; list enable flag (Control-P) - used by BGii +LASTCH: DEFB 0 ; last character - used by BGii +USER: DEFB 0 ; user number - used by BGii +DEFDRV: DEFB 0 ; default drive number - used by BGii and DS +DRIVE: DEFB 0 ; drive number + + ;----- + +FCB0: DEFB 0 ; FCB byte 0 +DMA: DEFW 0080H ; DMA address +TRANS: DEFW 0 ; translation vector +TEMP0: DEFW 0 ; number of files on drive +DIRBUF: DEFW 0 ; directory buffer pointer - used by BGii +IXP: DEFW 0 ; disk parameter block +CSV: DEFW 0 ; check sum pointer +ALV: DEFW 0 ; allocation vector pointer + + ;----- + +MAXSEC: DEFW 0 ; number of sectors/track +NBLOCK: DEFB 0 ; block shift +NMASK: DEFB 0 ; mask number of blocks +NEXTND: DEFB 0 ; extent mask + +MAXLEN: DEFW 0 ; maximum block number-1 +NFILES: DEFW 0 ; maximum number of files-1 +NDIR0: DEFB 0 ; first two entries ALV buffer + DEFB 0 ; ..(NDIR1) +NCHECK: DEFW 0 ; number of checksum entries +NFTRK: DEFW 0 ; first track number + + ;----- + +FUNCT: DEFB 0 ; function code +PEXIT: DEFW 0 ; exit code + + ;----- + +FLDRV: DEFB 0 ; drive select used flag +RDWR: DEFB 0 ; read/write flag +SEARQU: DEFB 0 ; search question mark used +SEARPU: DEFB 0 ; search public file + + ;----- + +RECDIR: DEFW 0 ; record directory (checksum) +FILCNT: DEFW 0 ; file counter +SECPNT: DEFB 0 ; sector pointer +SUBFLG: DEFB 0 ; submit flag (reset disk command) +DCOPY: DEFW 0 ; copy address FCB +SEAREX: DEFB 0 ; exit code search +SEARNB: DEFB 0 ; search number of bytes +ERMODE: DEFB 0 ; BDOS error mode +ARWORD: DEFW 0 ; DE argument on entry - used for BGii +DEVAL: DEFW 0 ; return value for DE reg +SPSAVE: DEFW 0 ; Stack pointer location + + ;----- + +FINITD: DEFB 0 ; INITDR flag preventing code re-execution +TPABNK: DEFB 0 ; TPA bank number + + + DEFB 'ZSDOS ',VER/16+'0','.',VER MOD 16 + '0' + DEFB ' Copyright (c) ' + DATE + DEFB ' by C.W.Cotrill & H.F.Bow' +IXSAVE: DEFB 'er' ; User's IX register + +ZSDOSS: DEFW 0 ; ZSDOS Stack + DEFB 0,0,0,0 ; ..also used as buffer to read/set clock + + ;----- + + ; Time/Date +RWCODE: DEFB 0 ; 0= read stamp, 1= write stamp +STOFF: DEFB 0 ; offset in stamp +STATUS: DEFB 0FFH ; status of first routine for exit checs + + ; Other +FCBADR: DEFW 0 ; address of (target) FCB +FCBBUP: DEFB 0 ; number of FCB bytes to copy/update +ZSFCB: DEFS 36 ; buffer for internal FCB (36 bytes) +ZSSTMP: DEFS 15 ; buffer for Time Stamp (15 bytes) + + + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: ZSDOS Entry Point + +ENTRY: CALL RETMEM ; B/P Bios fn #39 (A= current memory bank) + LD (TPABNK),A ; save TPA bank number + XOR A ; clear A + LD B,A ; for later 16-bit addr's + LD L,A + LD H,A ; set HL to zero + LD (PEXIT),HL ; clear exit code + LD (FLDRV),HL ; reset drive select and R/W flags + LD (SPSAVE),SP ; save stack pointer + LD SP,ZSDOSS ; get internal stack pointer + PUSH IX ; save index register on our stack + PUSH DE ; save parameter register + POP IX ; get it back in IX + LD (ARWORD),DE ; save in memory for BGii + LD HL,DOSEXIT ; get exit address ZSDOS + PUSH HL ; save it on stack to return from ZSDOS + LD A,C ; get function code (reg B= 0) + LD (FUNCT),A ; save it for later use + CP 12 ; is it a non-disk function ? + JR C,ENTRY0 ; ..if so, jump + CP MAXCMD ; fcn < maximum command number (49) ? + JR C,ENTRY1 ; ..if so, jump + + ; extended function scanner for added functions + CP 98 ; is it less than cmnd 98 ? + RET C ; ..if so, return (fcn not known/valid) + CP 152 ; is it cmnd 152 ? + JP Z,CMD152 ; ..if so, execute it + CP 103+1 ; is it greater than cmnd 103 ? + RET NC ; ..if so, return (fcn not known/valid) + SUB 98-MAXCMD ; rework 98..103 --> 50..55 + LD C,A ; save reworked function number + ; ..and fall through to ENTRY0 + + ; for Non-disk functions (ie. fcn # less than 12), push address of + ; SAVEA routine on Stack (save A reg as return code). Saves code in + ; Console Routines, as a simple RET can be used in most cases. +ENTRY0: LD HL,SAVEA + PUSH HL ; vector return through A reg save +ENTRY1: LD HL,CTABLE ; load table + ADD HL,BC ; add + ADD HL,BC ; add twice to get word value + LD A,(HL) ; get LSB + INC HL ; pointer to MSB + LD H,(HL) ; get MSB + LD L,A ; save LSB in L + + ; copy byte argument into A and C to simplify Function calls + ; allows direct Bios jumps for several fcn's with code savings + LD C,E ; place arg in C for BIOS + LD A,E ; and in A for others + JP (HL) ; jump to routine + + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: Command Table + +CTABLE: DEFW ERROR5 ; Warm boot (Bios) with ERMODE clear + DEFW CMND01 ; Console input + DEFW WRCON ; Console output + DEFW READER ; Reader input (BIOS) + DEFW PUNCH ; Punch output (BIOS) + DEFW LIST ; List output (BIOS) + DEFW CMND06 ; Direct console I/O + DEFW CMND07 ; Get I/O byte + DEFW CMND08 ; Set I/O byte + DEFW CMND09 ; Print string + DEFW CMND10 ; Read console buffer + DEFW CMND11 ; Get console status + DEFW CMND12 ; Return version number + DEFW CMND13 ; Reset disk system + DEFW CMND14 ; Select disk + DEFW CMND15 ; Open file + DEFW CMND16 ; Close file + DEFW CMND17 ; Search for first + DEFW CMND18 ; Search for next + DEFW CMND19 ; Delete file + DEFW CMND20 ; Read sequential + DEFW CMND21 ; Write sequential + DEFW CMND22 ; Make file + DEFW CMND23 ; Rename file + DEFW CMND24 ; Return login vector + DEFW CMND25 ; Return current disk + DEFW CMND26 ; Set DMA address + DEFW CMND27 ; Get address allocation vector + DEFW CMND28 ; Write protect disk + DEFW CMND29 ; Get R/O vector + DEFW CMND30 ; Set file attributes + DEFW CMND31 ; Get address disk parameter header (DPH) + DEFW CMND32 ; Get/set user code + DEFW CMND33 ; Read random + DEFW CMND34 ; Write random + DEFW CMND35 ; Compute file size + DEFW CMND36 ; Set random record + DEFW CMND37 ; Reset multiple drive + DEFW DUMMY ; Function 38 (unused) + DEFW CMND39 ; Return fixed disk login vector + DEFW CMND40 ; Write random with zero fill + DEFW DUMMY ; Function 41 (unused) + DEFW DUMMY ; Function 42 (unused) + DEFW DUMMY ; Function 43 (unused) + DEFW DUMMY ; Function 44 (unused) + DEFW CMND45 ; Set Error Mode + DEFW CMND46 ; Return Disk Free Space + DEFW CMND47 ; Return DMA + DEFW CMND48 ; Return DOS version + DEFW CMND49 ; Return Environment Descriptor Address +MAXCMD EQU ($-CTABLE)/2 + DEFW CMD98 ; Get Time + DEFW CMD99 ; Set Time + DEFW CMD100 ; Get Flags + DEFW CMD101 ; Set Flags + DEFW CMD102 ; Get Stamp + DEFW CMD103 ; Put Stamp + + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: I/O Routines + + ;-------------------------------------------------- + ; fn #1 CONIN + ; enter: none, exit: A= char + ;-------------------------------------------------- + ; read char fron Console + ; and echo if char = CR, LF, TAB, CONTH or >=Space +CMND01: CALL GETCH ; get character (and test it) + RET C ; ..if less than Space, exit +PUTCH: PUSH HL ; save regs for other calls + CALL WRCON ; echo character + POP HL + RET + + + ;-------------------------------------------------- + ; fn # 6 Direct Console I/O + ; enter: E= 0FFH (In), exit: A= Input Character + ; 0FEH (In) Console Status + ; 0FDH (In) Input Character + ; 00H..0FCH (Out) 00H + ;-------------------------------------------------- + ; enhanced to CP/M 3 spec + ; checks ZSDOS typeahead for reliable Console I/O under all + ; conditions as per a suggestion by Bridger Mitchell +CMND06: INC E ; test if get char is available + JR Z,DCIO1 ; ..if yes, do input + INC E ; test for 0xFE + JR Z,DCIO2 ; ..if so, get status + INC E ; test for 0xFD + JR Z,GETCH ; ..if so, wait for input char + JP CONOUT ; else, print char (Bios Console Output) +DCIO2: LD A,(LASTCH) ; check for buffered char + OR A + LD A,00000001B ; preset ready + CALL Z,CONST ; call Bios Console Status + AND A ; test it + RET ; and return to caller +DCIO1: CALL DCIO2 ; get console status + RET Z ; ..if no character present, exit + ; else, fall through + + ; get char from Console +GETCH: LD HL,LASTCH ; check ZSDOS type ahead for char + LD A,(HL) + LD (HL),0 ; reset last character + OR A ; set flags + CALL Z,CONIN ; call Bios Console Input + ; get char and fall through to test it + + ; test char + ; out: Carry= 0 for CR, LF, TAB, CONTH, or >=Space + ; Carry= 1 for all other characters + CP CR ; is it a Carriage Return ? + RET Z ; ..if so, return + CP LF ; Line Feed ? + RET Z ; ..return + CP TAB ; Tab ? + RET Z ; ..return + CP CONTH ; Backspace ? + RET Z ; ..return + CP ' ' ; test >= Space + RET ; ..and return to caller + + + ;-------------------------------------------------- + ; fn # 8 Set I/O Byte + ; enter: E= I/O Byte, exit: A= 00H + ;-------------------------------------------------- +CMND08: LD (RAMLOW+0003H),A ; save it in RAM and fall through + + + ;-------------------------------------------------- + ; fn # 7 Get I/O Byte + ; enter: None, exit: A= I/O Byte (0003H) + ;-------------------------------------------------- +CMND07: LD A,(RAMLOW+0003H) ; get I/O byte from RAM + RET + + + ;-------------------------------------------------- + ; fn # 10 Read Console Buffer + ; enter: DE= address Buffer, exit: A= 00H + ;-------------------------------------------------- +CMND10: LD A,(TABCNT) + LD (TABCX1),A ; save start Tab position + INC DE + XOR A + LD (DE),A ; set char count to zero + INC DE ; point to actual buffer start +RDBUF1: PUSH DE ; save buffer pointer + CALL GETCH ; get next byte from user + POP DE + LD HL,RDBUF1 + PUSH HL ; return address to stack + LD HL,(ARWORD) + LD C,(HL) ; put buffer length in C + INC HL ; and point to current length + CP CR + JR Z,JZRBX ; ..if CR, then exit + CP LF +JZRBX: JP Z,RDBUFX ; ..or if LF, then exit + + ; delete char from buffer + ; (Rubout, Backspace, CR, LF are _never_ in the buffer) +RDBUF2: CP RUBOUT ; delete char ? + JR Z,DOBACK ; ..if so, jump + CP CONTH ; Control-H also deletes + JR NZ,RDBUF3 ; ..if no delete, skip to next test +DOBACK: LD A,(HL) + AND A ; test if attempting to del from empty line + RET Z ; ..if so, then exit +DOBAK0: DEC DE ; back up to last character + DEC (HL) ; erase from buffer + PUSH DE ; save buffer pointer + LD B,(HL) ; get new char count + INC HL ; point to first char + EX DE,HL + LD HL,TABCNT + LD C,(HL) ; save current Tab count + INC HL + LD A,(HL) ; get starting Tab position + DEC HL + LD (HL),A ; init the counter + INC B ; insure non-zero + JR DOBAK2 ; jump to done test +DOBAK1: LD A,(DE) ; get char from buffer + CALL WRCON2 ; counts chars + INC DE +DOBAK2: DJNZ DOBAK1 ; continue count until done + LD A,C ; get prior Tab count + SUB (HL) ; get diff between new and old + LD B,A ; set up as count + LD (HL),C ; restore prior count + POP DE ; restore pointer + + ; delete B chars from Console + PUSH DE ; save pointer +DOBAK5: LD C,CONTH + PUSH BC ; save counter from destruction + CALL CONOUT ; call Bios Console Output + LD C,' ' + CALL CONOUT ; output Backspace, Space to CON: only + LD A,CONTH + CALL WRCON ; now Backspace CON:, counter, and printer + POP BC ; restore counter + DJNZ DOBAK5 ; loop until all done + POP DE ; restore pointer + RET + + ; erase buffer +RDBUF3: CP CONTU ; test erase line + JR Z,ERALIN ; ..if so, do it + CP CONTX + JR NZ,RDBUF4 ; skip to next test if no erase line +ERALIN: XOR A + OR (HL) ; line empty ? + RET Z ; ..if so, exit + PUSH HL + CALL DOBAK0 ; else, delete another (skip empty check) + POP HL + JR ERALIN ; if Ctrl-R=True, do following code + ; else bypass + +RDBUF4: CP CONTR ; if Ctrl-R type clean buffer version on CON: + JR NZ,RDBUF5 + PUSH HL ; save pointer to buffer length + CALL CROUT ; do CR/LF + LD HL,TABCNT + LD (HL),0 ; init Tab count + INC HL + LD B,(HL) ; and get Tab offset count + LD A,' ' + INC B ; insure nz value + JR RETY1A ; so case of lh side of screen ok +RETYP1: CALL WRCON ; space off start of line +RETY1A: DJNZ RETYP1 + POP HL ; point to buffer length + LD B,(HL) ; get how many chars to print + INC HL ; restore buffer pointer + EX DE,HL ; put buffer pointer in DE + INC B ; comp for first djnz + JR RETYP3 ; skip to done test +RETYP2: LD A,(DE) ; get char from buffer + CALL WRCTL ; output it + INC DE ; bump pointer +RETYP3: DJNZ RETYP2 ; loop until done + RET + + ; toggle line printer echo +RDBUF5: CP CONTP ; toggle printer ? + JR NZ,RDBUF6 ; ..if not, next test + LD HL,FCONTP + LD A,(HL) ; get printer echo flag + CPL ; toggle it + LD (HL),A ; put back + RET + + ; check if Ctrl-C is first char in BUFF, exit if so +RDBUF6: LD (DE),A ; put character in buffer + PUSH HL + CALL WRCTL ; echo the character + POP HL + INC (HL) ; increment the character count + LD A,(HL) ; get current length + CP C ; test against buffer size + JR Z,RDBUFX + DEC A ; set Z flag for first character + LD A,(DE) ; get the character back + INC DE ; and bump the pointer + RET NZ ; ..if not the first character, return + CP CONTC ; possible user abort ? + RET NZ ; ..if not, return + JP ERROR5 ; else, jump to error reset exit + + ; done with Read Console Buffer function +RDBUFX: POP HL ; clear RDBUF1 return address + LD A,CR + JR WRCON ; ..and echo a CR + + ; print Control char as '^X' +WRCTL: CP ' ' ; test if Control char + JR NC,WRCON ; ..if not, send it out + CP TAB ; test if Tab + JR Z,WRCON0 ; ..if it is, then expand with spaces + PUSH AF ; save char + LD A,'^' ; output a caret + CALL WRCON1 ; no need for Tab test here + POP AF + ADD A,40H ; convert to printable + ; ..and fall through to WRCON + + + ;-------------------------------------------------- + ; fn #2 CONOUT + ; enter: E= char, exit: none (A= Bios reg A) + ;-------------------------------------------------- + ; output char with list echo, Tab expansion +WRCON: CP TAB ; is it a Tab ? + JR NZ,WRCON1 ; ..if not, jump +WRCON0: LD A,' ' ; expand Tab with spaces + CALL WRCON1 ; write space + LD A,(TABCNT) ; get Tab count + AND 7 ; test if done + JR NZ,WRCON0 ; ..if not, then repeat + LD A,TAB ; return Tab + RET ; return to caller +WRCON1: PUSH BC ; save pointers + PUSH DE + LD C,A ; save character + PUSH BC + +BGPTCH0 EQU $+1 ; <--- BGii patches this addr + + CALL CMND11 ; test status and CONTS/CONTC + POP BC ; get character back + PUSH BC ; save it again + CALL CONOUT ; call Bios Console Output + POP BC ; get character back + PUSH BC ; save it again + LD A,(FCONTP) ; get printer echo flag + OR A ; test it + CALL NZ,LIST ; ..if non-zero, output char to printer + POP BC ; restore character + LD A,C ; fall through to count routine + POP DE ; restore pointers + POP BC + + ; count characters in line as shown by f10 + LD HL,TABCNT ; get pointer to Tab counter +WRCON2: INC (HL) ; increment Tab counter + CP RUBOUT ; test if character = Rubout + JR Z,WRCON3 ; ..if so, treat like Backspace + CP ' ' + RET NC ; ok if not Control char + CP TAB ; only DOBACK ever gets Tabs through here + JR Z,WRCON4 ; ..if Tab, handle differently + CP CONTH + JR Z,WRCON3 ; ..or Backspace + INC (HL) ; must have been echoed as two chars + CP LF + JR Z,WRCON3 ; unless it's LF + CP CR ; ..or CR + RET NZ + LD (HL),2 ; reset Tab counter +WRCON3: DEC (HL) ; decrement Tab counter + DEC (HL) + RET ; and exit + +WRCON4: LD A,7 ; bumped by one already + ADD A,(HL) ; Tabs are every 8 spaces + AND 0F8H ; ..MOD 8 + LD (HL),A ; save updated Tab count + RET ; ..and continue + + + ;-------------------------------------------------- + ; fn # 11 Get Console Status + ; enter: None, exit: A= 00H No character + ; 01H Char. present + ;-------------------------------------------------- + ; BGii uses this routine +BGCONST: +CMND11: CALL DCIO2 ; get character present status + RET Z ; ..if none, then exit + CALL GETCH ; get next console char + CP CONTS ; is it stop char ? + JR NZ,GCONS2 ; ..if not, jump + CALL CONIN ; call Bios Console Input to get next char + CP CONTC ; does the user want to exit (Ctrl-C) ? + JR NZ,CMND11 ; ..if not, check for another character + JP ERROR5 ; else, jump to warm boot and clear ERMODE +GCONS2: LD (LASTCH),A ; save character + LD A,1 ; character present code + RET ; return to caller + + ; echo CR,LF +CROUT: LD DE,MCRLF ; fall through to output routine + + + ;-------------------------------------------------- + ; fn # 9 Print String + ; enter: DE= address String, exit: None (A= '$') + ;-------------------------------------------------- +CMND09: LD A,(DE) ; get byte from buffer + CP '$' ; test, last byte ? + RET Z ; ..if yes, then return to caller + INC DE ; else, point to next byte + CALL WRCON ; ..and output character + JR CMND09 ; loop, test again + + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: Error Routines + +PRDEC: LD BC,100 + CALL NUM + LD C,10 + CALL NUM + LD BC,0101H + + ; display number +NUM: LD D,-1 ; load number -1 +NUM1: INC D ; increment number + SUB C ; divide by C + JR NC,NUM1 ; ..if not finished, then loop + ADD A,C ; restore last value + PUSH AF ; save it + LD A,D ; test if '0' + OR B ; and if leading zero + JR Z,NUM2 ; ..if yes, then exit + LD B,A ; set no leading zero + LD A,D ; get number + ADD A,'0' ; make ascii + CALL PUTCH ; echo number preserving BC +NUM2: POP AF ; restore number + RET ; and exit + + +;::::: ERROR MESSAGES + +MDSKCH: DEFB 'Changed$' +MBADSC: DEFB 'Bad Sector$' +MSEL: DEFB 'No Drive$' +MFILRO: DEFB 'File ' +MRO: DEFB 'W/P$' +MBERR: DEFB 'ZSDOS Error on $' +MBFUNC: DEFB CR,LF,'Call' +MDRIVE: DEFB ': $' +MFILE: DEFB ' File: $' +MCRLF: DEFB CR,LF,'$' + + + ; new ZDSOS error handler + ; in: B= error code + ; DE= message pointer +ERROR: LD A,(ERMODE) + LD C,A ; save error mode + RRCA ; test suppress print + JR C,ERROR3 ; ..if suppressed, then skip to display + + ; print ZSDOS Error on X: explanation + PUSH BC + PUSH DE ; save params + CALL CROUT ; output CR,LF + LD DE,MBERR + CALL CMND09 ; output 'ZSDOS Error on' + LD A,(DEFDRV) ; get current default drive + ADD A,'A' ; convert to ascii + CALL WRCON ; output to Console + LD DE,MDRIVE ; point to Drive tag + CALL CMND09 ; ouput also + POP DE ; restore error message pointer + CALL CMND09 ; send message + + ; now print CALL: XXX [FILE: XXXXXXXX.XXX] + LD DE,MBFUNC + CALL CMND09 ; display 'Call: ' + LD A,(FUNCT) ; get function number + CALL PRDEC ; output it + LD A,(FLDRV) + AND A ; was FCB used ? + JR Z,ERROR2 ; ..if not, skip file name display + POP BC ; get error type + PUSH BC + PUSH IX ; save FCB pointer + LD A,(FUNCT) ; are we erasing a file ? + CP 19 ; ..if so, get name from DIRBUF + JR NZ,ERROR0 ; ..ambiguous name may have been used + CALL CALDIR ; get Dir buffer pointer + EX (SP),HL ; to show that we are really gagged on +ERROR0: LD DE,MFILE + CALL CMND09 ; output 'File: ' + POP HL ; point to FCB + LD B,11 ; output this many chars +ERROR1: INC HL + LD A,3 + CP B ; time to send '.' ? + LD A,46 ; get ready for it + CALL Z,PUTCH ; ..and send it if time + LD A,(HL) ; get char + AND 7FH ; mask attributes + CALL PUTCH ; output it + DJNZ ERROR1 + +ERROR2: CALL CROUT ; send CR,LF + POP BC ; get error mode back +ERROR3: LD A,4 + SUB B ; test if select error + JR NZ,ERROR4 ; ..if not, skip + LD HL,DRIVE ; point to old default + LD A,(HL) ; get it + DEC HL ; point to bad drive + CP (HL) ; same ? + JR Z,ERROR4 ; ..if so, skip relog + PUSH BC + CALL SELSYB ; switch System bank + CALL SELDK ; get Bios back in step + POP BC +ERROR4: BIT 1,C ; test if return error mode + JR NZ,ERROR7 ; ..if return error, go + LD A,1 + SUB B ; test if fatal error + JR NC,ERROR6 ; ..if not a fatal error, jump + ; else, fall through + + + ;-------------------------------------------------- + ; fn # 0 Boot + ; enter: None, exit: None + ;-------------------------------------------------- +ERROR5: XOR A ; clear A + LD (ERMODE),A ; set DOS error mode to default CP/M + LD A,(OTPABK) ; store TPABNK = 0 (at B/P Bios base +0x82) + CALL SELMEM ; ..and also set it, BIOS fn #27 SELMEM (A= bank #) + RST 0 ; ..and leave + +ERROR6: CALL DCIO1 ; get console char if present + AND A ; test if any + JR NZ,ERROR6 ; keep getting them until typeahead eaten + CALL GETCH ; now get operator's response + CP CONTC ; test if abort + RET NZ ; ..if operator said ignore error + JR ERROR5 ; else, boot + +ERROR7: LD A,B ; get error + LD H,A ; save code in H reg for return + AND A ; test if disk changed warning + RET Z ; ..if so, continue relog + LD L,0FFH ; set extended error code + LD (PEXIT),HL ; save as return code + ; ..and fall through to DOS exit + + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: DOS Exit Routine + +DOSEXIT: LD A,(FLDRV) ; test Drive select used flag + OR A + JR Z,DOSEXT0 ; ..if no, then exit + LD A,(FCB0) ; get FCB byte 0 + LD (IX+0),A ; save it + CALL SELTPB ; select TPA bank + LD HL,ZSFCB ; buffer internal FCB + LD DE,(FCBADR) + LD A,(FCBBUP) ; get number of bytes to copy + OR A ; test if empty + JR Z,DOSEXT1 ; ..if zero, skip + LD C,A ; else, set byte counter (16-bit) + LD B,0 + LDIR ; and copy +DOSEXT1: LD A,(DRIVE) ; get old Drive number + CALL SELSYB ; switch System bank + CALL SELDK ; select disk + + + ; Stack is in an undefined condition at this point, if error handler + ; was invoked. Independent of Stack position, the user's IX register + ; has to be restored. (Thanks to Joe Wright for catching this one!) +DOSEXT0: CALL SELTPB ; select TPA bank + LD SP,(SPSAVE) ; restore user stack + LD IX,(IXSAVE) ; restore IX + LD HL,(PEXIT) ; get exit code + LD DE,(DEVAL) ; and DE reg for DateStamper + LD A,L ; copy function code + LD B,H + RET ; and return to caller + + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: Disk Routines + + ;-------------------------------------------------- + ; fn # 13 Reset Disk System + ; enter: None, exit: A= 00H No $*.* on A + ; FFH $*.* on A + ;-------------------------------------------------- +CMND13: CALL SELSYB ; switch System bank + JP CMD13B ; and continue in Banked code + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Reset Disk System + ; (continue CMND13) + ;-------------------------------------------------- +CMD13B: LD HL,RAMLOW+80H ; set up default DMA address + LD (DMA),HL ; and save it + CALL STDMA ; do Bios call + XOR A ; set default drive = 'A' + LD (DEFDRV),A ; save it + LD DE,0FFFFH ; reset all drives + ; ..and fall through to CMD37B + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 37 Reset Mult Drive + ; enter: DE= Bit Mask, exit: A= 00H + ;-------------------------------------------------- + ; fixed disk login vector is also altered by this call +CMND37: CALL SELSYB ; switch System bank + JP CMD37B ; and continue in Banked code + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Reset Multiple Login Drive + ; (continue CMND37) + ;-------------------------------------------------- + ; fixed disk login vector is also altered by this call +CMD37B: CALL UNLOG ; clear selected Drives in DE from login + LD A,(FLAGS) + BIT 2,A ; test hard R/O enabled + JR NZ,UNWPT1 ; ..if enabled, jump + LD HL,DSKWP ; get Drive W/P vector + CALL ANDDEM ; reset W/P stat only of requested Drives +UNWPT1: LD A,(FUNCT) + CP 13 ; skip hard disk login change ? + LD HL,HDLOG + CALL NZ,ANDDEM ; clear HD login vector if fcn 37 +RELOG1: LD HL,(HDLOG) + CALL HLORDE ; don't clear fixed disks from T/D + EX DE,HL ; place modified logout in DE + LD HL,TDFVCT + CALL ANDDEM ; clear T/D vector as needed + LD A,(DEFDRV) ; get default drive + CALL SELDK + + + ; check for possible existance of submit file + + ; ZSDOS watches for any $*.* file in any User on any Drive during + ; re-log, make, and delete. In this manner, SUBFLG will always be + ; valid - even under Fast Relog and NZCOM. (Thanks to Joe Wright + ; for suggesting the need for this, and suggesting ways to do it.) +SUBEXT: LD A,(SUBFLG) ; get submit flag + JP SAVEA ; exit + + + ; check first byte of Dir entry or FCB for '$' + ; in: HL= pointer to Dir or FCB +CKSUB: INC HL ; point to file name + LD A,(HL) ; get first char file name + DEC HL + SUB '$' ; test if '$' + RET NZ ; ..if not, then exit + DEC A ; load with 0xFF + LD (SUBFLG),A ; save it in subflg + RET + + ; unlog Drive mask in DE +UNLOG: LD A,E ; get LSB + CPL ; complement it + LD E,A + LD A,D ; get MSB + CPL ; complement it + LD D,A ; DE = not reset + LD HL,LOGIN ; get address of login vector +ANDDEM: LD A,E ; clear login bits of reset drives + AND (HL) ; ..a byte at a time + LD (HL),A ; put to memory + INC HL + LD A,D + AND (HL) + LD (HL),A + RET + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 17 Search for First Entry of File + ; enter: DE= Address of FCB, exit: A= Directory Code + ;-------------------------------------------------- +CMND17: CALL SELDRV ; select drive from FCB + LD A,(IX+0) + SUB '?' ; test if '?' + JR Z,CMD17B ; ..if so, all entries match + LD A,(IX+FCBMOD) ; get system byte + CP '?' ; test if '?' + JR Z,CMD17A ; ..if yes, jump + LD (IX+FCBMOD),0 ; load system byte with zero +CMD17A: LD A,15 ; test first 15 items in FCB +CMD17B: CALL SEARCH ; do search +CMD17C: CALL SELTPB ; select TPA bank + LD HL,(DIRBUF) ; copy Directory buffer + LD BC,128 ; Directory = 128 bytes + LD DE,(DMA) ; to DMA address + LDIR + RET ; exit + + + ;-------------------------------------------------- + ; fn # 18 Search for Next Occurrence of File + ; enter: DE= Address of FCB, exit: A= Directory Code + ;-------------------------------------------------- +CMND18: LD IX,(DCOPY) ; get last FCB used by search + LD (ARWORD),IX ; save FCB pointer for BGii + CALL SELDRV ; select drive from FCB + CALL SEARCN ; search next file match + XOR A ; clear A (zero) + LD (FCBBUP),A ; ..save as num of bytes to update in FCB + JR CMD17C ; and copy Directory to DMA address + + + ;-------------------------------------------------- + ; fn # 19 Delete File + ; enter: DE= Address of FCB, exit: A= Error Code + ;-------------------------------------------------- +CMND19: CALL SELDRV ; select drive from FCB + ; (also switches System bank) + CALL DELETE ; ..and continue in Banked code + +CMND19A: LD A,(SEAREX) ; get exit byte 00= file found, 0FFH= not + JR SAVEA ; and exit + + + ;-------------------------------------------------- + ; fn # 23 Rename File + ; enter: DE= Address of FCB, exit: A= Error Code + ;-------------------------------------------------- +CMND23: CALL SELDRV ; select drive from FCB + CALL RENAM ; rename file + JR CMND19A ; and exit + + + ;-------------------------------------------------- + ; fn # 25 Get Current Disk + ; enter: None, exit: A= Current Disk + ;-------------------------------------------------- +CMND25: LD A,(DEFDRV) ; get current drive +SAVEA: LD (PEXIT),A ; return character +DUMMY: RET ; ..and exit ZSDOS + + + ;-------------------------------------------------- + ; fn # 101 Set Flags + ; enter: DE=Flags, exit: None + ;-------------------------------------------------- +CMD101: LD (FLAGS),A ; set ZSDOS flags + ; ..and fall through + + + ;-------------------------------------------------- + ; fn # 100 Get flags + ; enter: None, exit: HL= Flags + ;-------------------------------------------------- +CMD100: LD A,(FLAGS) ; get ZSDOS flags + JR SAVEA ; ..and exit + + + ;-------------------------------------------------- + ; fn # 30 Set File Attributes + ; enter: DE= Address of FCB, exit: A= Error Code + ;-------------------------------------------------- +CMND30: CALL SELDRV ; select drive from FCB + CALL CSTAT ; change status bits of file + JR CMND19A ; and exit + + + ;-------------------------------------------------- + ; fn # 12 Get Version Number + ; enter: None, exit: A= Version Number (22H, CP/M compatible) + ;-------------------------------------------------- +ZDPCH1: +CMND12: LD HL,22H ; set CP/M compatible version number + LD A,E + CP 'D' ; is caller testing for DateStamper ? + JR NZ,CMD12A ; ..if not, jump exit + LD H,E ; otherwise return DS Active flag + LD DE,CMD98A ; have a clock, so get clock address +CMD12A: LD (DEVAL),DE ; in case DS gave us a clock address + JR SAVHL ; for speed + + + ; The following code section may seem a bit obscure. When the Z80 jumps + ; in at a label, it executes the LD HL instruction. The DEFB 0DDH turns + ; the LD HL instructions that follow into LD IX. In effect, this turns + ; the DEFB 0DDH into a one byte relative jump to SAVHL. As IX is never + ; used by these calls, its loss is of no consequence. + ; A similar trick is used in SEAR15. + + + ;-------------------------------------------------- + ; fn # 48 Get DOS and Version + ; enter: None, exit: H= DOS type: 'S'=ZSDOS, 'D'=ZDDOS + ; L= BCD Version Number + ;-------------------------------------------------- +CMND48: LD HL,'S' SHL 8 + VER ; 'S' indicates ZSDOS, ZRDOS returns 0 + DEFB 0DDH ; trash IX and fall through + + + ;-------------------------------------------------- + ; fn # 29 Get R/O Vector + ; enter: None, exit: HL= R/O Vector + ;-------------------------------------------------- +CMND29: LD HL,(DSKWP) ; get disk W/P vector + DEFB 0DDH ; trash IX and fall through + + + ;-------------------------------------------------- + ; fn # 39 Get Fixed Disk Vector + ; enter: None, exit: HL= Fixed Disk Vector + ;-------------------------------------------------- +CMND39: LD HL,(HDLOG) ; return fixed disk login vector + DEFB 0DDH ; trash IX and fall through + + + ;-------------------------------------------------- + ; fn # 27 Get Alloc. Address (ALV) + ; enter: None, exit: HL= Address of Allocation Vector + ;-------------------------------------------------- +CMND27: LD HL,(ALV) ; get allocation vector + DEFB 0DDH ; trash IX and fall through + + + ;-------------------------------------------------- + ; fn # 49 Return ENV Address + ; enter: None, exit: HL= Address Env. Descriptor + ;-------------------------------------------------- +CMND49: LD HL,(OZ3ENV) ; get Z3ENV address (Bios base +0x98) + DEFB 0DDH ; trash IX and fall through + + + ;-------------------------------------------------- + ; fn # 24 Get Login Vector + ; enter: None, exit: HL= Login Vector + ;-------------------------------------------------- +CMND24: LD HL,(LOGIN) ; get login vector + DEFB 0DDH ; trash IX and fall through + + + ;-------------------------------------------------- + ; fn # 31 Get DPB Address + ; enter: None, exit: HL= Address of DPB + ;-------------------------------------------------- +CMND31: LD HL,(IXP) ; get drive table + DEFB 0DDH ; trash IX and fall through + + + ;-------------------------------------------------- + ; fn # 47 Get DMA address + ; enter: None, exit : HL= Current DMA Address + ;-------------------------------------------------- +CMND47: LD HL,(DMA) ; get current DMA address + LD A,H ; test if valid (<> zero) + OR L +SAVHL: LD (PEXIT),HL ; save it + RET ; and exit + + + ;-------------------------------------------------- + ; fn # 45 Set error mode + ; enter: E= FFH (Get), exit: A=0 0H + ; FEH (Get Err/Disp) + ; 01H (Set ZSDOS) + ; 00H (Set CP/M) + ;-------------------------------------------------- + ; ##### implementation does not comply with documentation +CMND45: LD (ERMODE),A + RET + + + ;-------------------------------------------------- + ; fn # 32 Set/Get User Code + ; enter: E= FFH (Get), exit: A= User Number + ; User Number (Set) 00H + ;-------------------------------------------------- +CMND32: LD HL,USER ; point to User byte location + INC A ; test if 0xFF + LD A,(HL) ; get old user code + JR Z,SAVEA ; ..if 0xFF, then exit + LD A,E ; get new User code + AND 1FH ; mask it + LD (HL),A ; save it + RET ; and exit + + + ;-------------------------------------------------- + ; fn # 35 Compute File Size + ; enter: DE= Address of FCB, exit: A= Error Code + ;-------------------------------------------------- +CMND35: CALL SELDR1 ; select drive from FCB + LD A,36 ; 36 bytes + LD (FCBBUP),A ; ..to update in FCB + CALL FILSZ ; compute file size + JR CMND19A ; and exit + + + ;-------------------------------------------------- + ; fn # 36 Set Random Record + ; enter: DE= Address of FCB, exit: A= 00H + ;-------------------------------------------------- +CMND36: LD HL,32 ; set pointer to next record + CALL CALRRC ; calculate random record count +LDRRC: LD (IX+33),D ; and save it + LD (IX+34),C + LD (IX+35),B + RET ; ..exit + + + ; ##### CHECK: unreferenced code + PUSH IX + CALL SELDRV + JP NOTUSE2 + ; ##### + + + ;----- + ; Select Disk From FCB +BGSELDRV: +SELDRV: LD A,(ERMODE) ; are we in modified User mode ? + AND A + JR NZ,SELDR1 ; ..if so, jump + LD HL,(ARWORD) + LD BC,FCBUSR ; else, point to User number + ADD HL,BC + LD (HL),A ; clear User flag +SELDR1: LD A,0FFH ; set disk select done flag + LD (FLDRV),A + LD HL,(ARWORD) ; get argument of fcn call (DE= FCB address) + LD (FCBADR),HL ; ..and save it + LD DE,ZSFCB ; set to internal FCB + PUSH DE + POP IX ; ..copy to IX + LD (ARWORD),DE ; ..and save + LD BC,36 ; byte count + LDIR ; ..and copy + LD A,16 ; 16 bytes + LD (FCBBUP),A ; save # bytes to update in FCB + LD A,(DEFDRV) ; get current drive + LD E,A ; save it in register E + LD HL,(ARWORD) + LD A,(HL) ; get drive from FCB + LD (FCB0),A ; save it + CP '?' ; test if '?' + JR Z,CMND14 ; ..if yes, then select drive from reg E + PUSH IX ; save BGii's IX register + + ; IX won't be altered on cmnd14 + LD IX,(ARWORD) ; get FCB pointer + AND 1FH ; mask drive + PUSH HL + JR Z,SELDR0 ; select drive from register E + LD E,(HL) ; get drive from FCB + DEC E ; decrement drive number, so A= 0 +SELDR0: CALL CMND14 ; do select of drive + POP HL ; restore FCB pointer + + ; resolve User for FCB + ; in: IX= FCB ptr + ; out: A= User + LD A,(IX+FCBUSR) ; ..get potential User in case + BIT 7,A ; is this a valid User ? + JR NZ,RESUS1 ; ..if there is, then skip + LD A,(USER) ; get User number + JR RESUS1 ; ..and bypass push IX + + ; set User in FCB to value passed in A +RESUSR: PUSH IX +RESUS1: LD IX,(ARWORD) + AND 1FH ; user number in A + LD (IX+0),A ; save in FCB 0 byte + OR 80H ; set valid DOS user flag + LD (IX+FCBUSR),A ; ..and in FCB 13 byte + POP IX ; restore caller's IX + RET + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ; select disk error exit + ; Stack is off by one level here, but there is a one way trip around +SELDK3: LD HL,(STSEL) ; load error message address + LD B,4 ; select error + LD DE,MSEL ; load select error message + JP JUMPHL ; Select Disk from E register + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 14 Select Disk + ; enter: E= Disk Number, exit: A= 00H No $*.* File + ; FFH $*.* File + ;-------------------------------------------------- +CMND14: LD A,(DEFDRV) ; get current drive + LD (DRIVE),A ; save it in memory + CALL SELSYB ; switch System bank + JP CMD14B ; ..and continue in Banked code + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Select Disk + ; (continue CMND14) + ;-------------------------------------------------- +CMD14B: LD A,E ; copy Drive number + + ; call w/ A= drive no. (0..15 = A..P) +SELDK: LD HL,(LOGIN) ; get login vector + AND 0FH ; mask Drive number + LD B,A ; save counter + CALL NZ,SHRHLB +SELDK0: EX DE,HL ; put Drive bit mask in DE + LD HL,DEFDRV ; get pointer last drive + BIT 0,E ; test if Drive logged in + JR Z,SELDK2 ; ..if not, log it in + CP (HL) ; test same Drive ? + RET Z ; ..if yes, then exit + + ; NOTE: + ; A long standing DOS bug concerns the SELECT function. If fcn 14 is + ; called and the drive doesn't exist, the default will still point + ; to the bad drive unless we fix it in the error routine. + ; It is for this reason that drive is saved above. We must allow + ; default to assume the illegal drive value long enough for the + ; error handler to print ot, then re-select the old default. +SELDK2: LD (HL),A ; save new current Drive + PUSH DE ; save Drive logged in flag + LD C,A ; copy Drive number + LD B,A + CALL DRVOK ; test if Drive is valid (Z3ENV Drive vector) + JR NC,SELDK3 ; ..if not, exit + CALL SELDSK ; do Bios call Select Disk + LD A,H ; test if error + OR L + JR Z,SELDK3 ; ..if yes, illegal Drive number + LD DE,TRANS ; point to local translation storage + LD BC,2 ; ..and move 2-byte ptr in + LDIR + LD (TEMP0),HL ; save address in temp0 + LD C,6 ; advance to Dirbuf part of DPH + ADD HL,BC ; as TEMP1 and TEMP2 unused in P?DOS + LD DE,DIRBUF ; load Dirbuf pointer + LD C,8 ; copy 8 bytes + LDIR + LD HL,(IXP) ; get Drive parameter address + LD C,15 ; copy 15 bytes + LDIR + POP DE ; get Drive logged in flag + BIT 0,E ; test it + RET NZ ; Drive logged in, so return + CALL GETCDM + EX DE,HL ; Drive mask in DE + LD HL,(LOGIN) ; get login vector + CALL HLORDE ; set Drive bit in login vector + LD (LOGIN),HL ; save login vector + LD A,(FLAGS) ; get flags + BIT 3,A ; fast relog enabled ? + JR Z,INITDR ; if disabled, skip + + + ; The following code checks the WACD size to determine if the drive + ; being selected is a fixed disk. If WACD is 0, the disk is non- + ; removable. However, BIOS may support remapping of logical drives. + ; Therefore BDOS must catch the swap and clear the Hard Disk ALV and + ; allow the allocation bitmaps to be rebuilt. Hence, every disk + ; that is being selected for the first time traverses this code. + ; If a disk was logged as a fixed disk and all of the sudden has a + ; WACD buffer, the Fixed Disk Login Vector is cleared. + ; For bug-free operation of Fast Fixed Disk Logging, if drives are + ; swapped, NEVER SWAP TWO FIXED DRIVES! + + LD HL,(NCHECK) ; is this a fixed Drive ? + LD A,H + OR L + LD C,A ; save fixed disk flag (Z= true) + LD HL,(HDLOG) + LD A,E ; see if logged as fixed disk + AND L + LD L,A + LD A,D + AND H ; MSB + OR L ; Z flag set if HL and DE = 0 + LD A,0FFH ; don't alter flags + JR Z,SELDK4 ; ..if not logged as fixed disk, skip over + INC A ; else, flag as logged +SELDK4: LD B,A ; save logged as fixed disk flag (Z= true) + OR C ; test if still fixed disk + RET Z ; skip re-map if logged and not swapped + XOR A + LD H,A + LD L,A ; null vector + OR B ; was it logged as fixed disk ? + JR Z,SELDK5 ; invalidate HDLOG vector + ; (drive no longer considered fixed disk) + LD A,C + OR A ; wasn't fixed disk before - is it now ? + JR NZ,INITDR ; ..if it isn't, skip vector update + LD HL,(HDLOG) + CALL HLORDE ; else, add this drive to fixed disk vector +SELDK5: LD (HDLOG),HL ; update fixed disk vector + ; ..and fall through to INITDR + + + ; init drive + ; clear ALV bit buffer after Drive reset +INITDR: LD HL,(MAXLEN) ; get length ALV buffer-1 (bits) + CALL SHRHL3 ; divide by 8 to get bytes + LD B,H + LD C,L ; counter to BC (will be count+1 cleared) + LD HL,(ALV) ; get pointer ALV buffer + PUSH HL + LD D,H + LD E,L + INC DE ; ALV buffer +1 in DE + XOR A + LD (HL),A ; clear first 8 bits + LDIR ; and remainder of buffer + POP HL ; get ALV pointer + LD DE,(NDIR0) ; get first two bytes ALV buffer + LD (HL),E ; save LSB + INC HL ; increment pointer + LD (HL),D ; save MSB + LD HL,(TEMP0) ; clear number of files on this Drive + LD (HL),A ; clear LSB (A still has 0) + INC HL ; increment pointer + LD (HL),A ; clear MSB + LD A,0FFH ; set initial value for flag + LD (FINITD),A + +ZDPCH2 EQU $ ; <--- Intercept first scan (ZDS Patch) + + CALL SETFCT ; set file count +INITD2: LD A,0FFH ; update Directory checksum + CALL RDDIR ; read FCB's from Directory + CALL TSTFCT ; test last FCB + JP Z,SUBEXT ; return subflg for strict CP/M compat + CALL CALDIR ; calculate entry point FCB + LD A,(HL) ; get first byte FCB + CP 0E5H ; test empty Directory entry + JR Z,INITD2 ; ..if yes, then get next FCB + AND 7FH ; mask + CP 21H ; test time stamp + JR Z,INITD2 ; ..if yes, then get next FCB + + + ; check if FCB belongs to !!!TIME&.DAT file + LD A,(FINITD) ; get first loop flag + OR A ; test if zero + JR Z,INITD5 ; ..if yes, then jump + ; to prevent re-execution of following code + INC A ; ..else, increment + LD (FINITD),A ; and save flag again + LD BC,00C00H ; set counter B=12, and clear C + PUSH HL +INITD3: LD A,(HL) ; get byte from FCB + AND 7FH ; mask high bit + ADD A,C ; add in previous result + LD C,A ; ..and save it in C + INC HL ; move ptr forward + DJNZ INITD3 ; loop till done + CP TDCKSM ; test if matches checksum of !!!TIME&.DAT + JR NZ,INITD4 ; ..if not, skip over + LD HL,(TDFVCT) ; else, get T/D vector + CALL SDRVB ; set drive bit in HL + LD (TDFVCT),HL ; and save T/D vector again +INITD4: POP HL + +ZDPCH3 EQU $ ; <--- Test for T&D if first time (ZDS Patch) + +INITD5: CALL CKSUB ; test for submit file + LD C,1 ; set bit in ALV buffer + CALL FILLBB ; set bits from FCB in ALV buffer + CALL TSTLF ; test for last file + CALL NC,SETLF0 ; ..and update the last file count if so + JR INITD2 ; get next FCB + + + + ;_______________________// Non-Banked // + CSEG + + ;----- + ; return mask for current Drive in HL +GETCDM: LD HL,0 ; no drives to Or + + ; set Drive bit in HL +SDRVB: EX DE,HL ; copy HL=>DE + LD HL,1 ; get mask drive 'A' + LD A,(DEFDRV) ; get current drive + OR A ; test if drive 'A' + JR Z,HLORDE ; ..if yes, then done +SDRVB0: ADD HL,HL ; get next mask + DEC A ; decrement drive number + JR NZ,SDRVB0 ; ..and test if done +HLORDE: LD A,D ; HL= HL or DE + OR H + LD H,A + LD A,E + OR L + LD L,A + RET ; exit + + +SHRHL3: LD B,3 ; ZSDOS v1 comment: "used in a few places" + ; ##### used exactly once - make INITDR inline + + ;----- + ; shift HL right logical B bits +SHRHLB: SRL H + RR L ; Shift HL right one bit (divide by 2) + DJNZ SHRHLB + RET + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;----- + ; calculate Sector/Track directory +STDIR: LD HL,(FILCNT) ; get FCB counter Directory + SRL H ; divide by 4 + RR L + SRL H + RR L + LD (RECDIR),HL ; save value (used by checksum) +STDIR2: EX DE,HL ; move to DE +STDIR1: LD HL,0 ; clear HL + + + ; calculate Sector/Track + ; Track= HL,DE / MAXSEC, Sector= HL,DE MOD MAXSEC + ; in: HL, DE= sector number (128 byte sector) +CALST: LD BC,(MAXSEC) ; get sectors/track + LD A,17 ; set up loop counter +CALST0: OR A + SBC HL,BC ; HL > BC ? + CCF + JR C,CALST1 ; ..if yes, then jump + ADD HL,BC ; else, restore HL + OR A ; clear Carry +CALST1: RL E ; shift result in DE + RL D + DEC A ; test last bit done + JR Z,CALST2 ; ..if yes, then exit + ADC HL,HL ; else, shift next bit in HL + JR CALST0 ; continue + +CALST2: PUSH HL ; save sector number + LD HL,(NFTRK) ; get first track + ADD HL,DE ; add track number + LD B,H ; copy it to BC + LD C,L + CALL SETTRK ; Bios call Set Track + POP BC ; restore sector number + LD DE,(TRANS) ; get translation table address + CALL SECTRN ; Bios call Sector Translation + LD B,H ; copy result in BC + LD C,L + JP SETSEC ; Bios call Set Sector + + + ; get Disk map block number from FCB + ; out: HL= FCB address + ; DE= DM + ; BC= offset in DM + ; Zero Flag set (Z) if DM= 0, else reset (NZ) + ; (squeezed by Joe Wright) +GETDM: LD L,(IX+NXTREC) ; get record number in L + RL L ; shift it left once + LD A,(NEXTND) ; get EXM + AND (IX+FCBEXT) ; And the extent number + LD H,A ; to H + LD A,(NBLOCK) ; get BSH + LD B,A ; to B + INC B ; +1 + CALL SHRHLB ; shift HL right B times + LD D,B ; zero to D + LD A,L ; result in A + +GETDM4: LD HL,(ARWORD) + LD C,16 ; add offset 16 to point to DM + ADD HL,BC + LD C,A ; add entry FCB + ADD HL,BC + LD A,(MAXLEN+1) ; test 8 bits/16 bits FCB entry + OR A + LD E,(HL) ; get 8 bit value + JR Z,GETDMX ; ..if 8-bit entries, exit + + ADD HL,BC ; add twice (16-bit values) + LD E,(HL) ; get LSB + INC HL ; increment pointer + LD D,(HL) ; get MSB + DEC HL ; decrement pointer +GETDMX: LD A,D ; check for zero DM value + OR E + RET ; and exit + + + ; calculate Sector number + ; in: DE= block number from FCB +CALSEC: LD HL,0 ; clear MSB sector number + LD A,(NBLOCK) ; get loop counter + LD B,A ; save it in B + EX DE,HL +CALSC0: ADD HL,HL ; shift L,D,E + RL E + DJNZ CALSC0 ; B times + EX DE,HL + LD A,(NMASK) ; get sector mask + AND (IX+NXTREC) ; And with next record + OR E ; set up LSB sector number + LD E,A + RET ; and exit + + + + ;_______________________// Non-Banked // + CSEG + + ;----- + ; check file Read-Only status, then fall through to CALDIR +CKRODI: CALL CHKFRO ; abort if the file is R/O + ; ..fall through + + + ;----- + ; calculate DIRBUF entry point +CALDIR: LD A,(SECPNT) ; get sector pointer +CALDIR1: LD HL,(DIRBUF) ; get start address dirbuf +CALDI0: ADD A,L ; add L=L+A + LD L,A + RET NC ; ..if no Carry, then exit + INC H ; increment H + RET ; and exit + + + ;----- + ; init file count +SETFCT: LD HL,-1 ; set up file count + LD (FILCNT),HL ; save it + RET ; and exit + + + ;-------------------------------------------------- + ; fn # 28 Write Protect Disk + ; enter: None, exit: A= 00H + ;-------------------------------------------------- +CMND28: LD HL,(DSKWP) ; get disk W/P vector + CALL SDRVB ; include drive bit + LD (DSKWP),HL ; save disk W/P vector + LD DE,(NFILES) ; get max number of files-1 (bumped below) + LD HL,(TEMP0) ; get pointer to disk parameter block + INC HL ; correct pointer + + ; setlf0 relocated inline here +SETLF0: INC DE ; increment last file + LD (HL),D ; save it in TEMP0 + DEC HL + LD (HL),E + RET ; and exit + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;----- + ; search using first 15 bytes of FCB, test if found +SRCT15: CALL SEAR15 ; search on 15-bytes.. + ; ..fall through to test presence + + + ;----- + ; test file count +TSTFCT: LD HL,(FILCNT) ; test file count= 0xFFFF + LD A,H ; get MSB + AND L ; And LSB + INC A ; test if result= 0xFF + RET ; and exit + + + ;----- + ; test last file +TSTLF: LD HL,(TEMP0) ; get pointer to last file + LD DE,(FILCNT) ; get file counter + LD A,E ; subtract DE-(HL) + SUB (HL) + INC HL + LD A,D + SBC A,(HL) + RET ; and exit + + + ;----- + ; get next FCB from Drive + ; in: A= 0 check checksum, A= 0FFH update checksum +RDDIR: LD C,A ; save checksum flag + LD HL,(FILCNT) ; get file counter + INC HL ; increment it + LD (FILCNT),HL ; and save it + LD DE,(NFILES) ; get maximum number of files + LD A,E ; is this the last file ? + SUB L + LD A,D + SBC A,H + JP C,SETFCT ; ..if so, set file count to 0xFFFF + LD A,L ; get file count LSB + RRCA ; *32 + RRCA + RRCA + AND 60H ; mask it + LD (SECPNT),A ; save it for later use + RET NZ ; ..if not first FCB sector, return + PUSH BC ; save checksum flag + CALL STDIR ; calculate sector/track Directory +RDDIR2: CALL DMADIR ; set up DMA Directory + CALL READR ; read a record + CALL STDMA ; ..and set up user's DMA + POP BC ; check/update checksum Directory + + ; C= 0 check checksum, C= 0FFH update checksum +CHKDIR: LD HL,(NCHECK) ; get number of checked records + LD DE,(RECDIR) ; get current record + XOR A ; clear Carry + SBC HL,DE ; test current record + RET Z ; ..if zero, exit + RET C ; ..if greater than NCHECK, exit + CALL CKS127 ; checksum first 127 bytes + ADD A,(HL) ; ..then 128th byte + LD HL,(CSV) ; get pointer checksum directory + ADD HL,DE ; add current record + INC C ; test checksum flag + JR NZ,CHKDR1 ; 0xFF -> update checksum + LD (HL),A ; update checksum + RET ; and exit + +CHKDR1: CP (HL) ; test checksum + RET Z ; ..if ok, exit + + ; checksum differs, so Disk has changed - relog and continue + LD A,(FLAGS) + BIT 4,A ; inform user ? + LD B,0 ; disk change error code + LD DE,MDSKCH ; disk changed message + CALL NZ,ERROR ; inform user + + ; relog current Drive after media change detected + CALL GETCDM ; get current Drive mask in HL + EX DE,HL ; transfer mask to DE + CALL UNLOG ; reset login vector for logged Drive + CALL RELOG1 ; do the meat of relogging + + ; Caveat emptor: this call is recursive.. + CALL SETFCT ; re-initialize search file count + XOR A ; we only get here by checking + JR RDDIR ; ..and all checking is done in RDDIR + + + ;----- + ; read sector from Drive +READR: CALL READ ; Bios call Read Sector + JR WRITE0 + + + ;----- + ; write sector on Drive +WRITER: CALL WRITE ; Bios call Write Sector +WRITE0: OR A ; test exit code + RET Z ; ..if ok, exit + LD B,1 ; disk I/O error code + LD DE,MBADSC ; load bad sector message + LD HL,(STBDSC) ; load bad sector vector + JP JUMPHL ; output error + + + + ;_______________________// Non-Banked // + CSEG + + ; ##### CHECK: unreferenced code + PUSH IX + CALL CMND16 + ; ##### + + + ; JP target of unreferenced code between CMND36 and SELDRV +NOTUSE2: LD HL,(FCBADR) + LD (ARWORD),HL + ; JP target of unreferenced code between CMND34 and CMND21 +NOTUSE3: POP IX + JP SELTPB ; select TPA bank + + + ;-------------------------------------------------- + ; fn # 16 Close File + ; enter: DE= Address of FCB, exit: A= Directory Code + ;-------------------------------------------------- + +BGPTCH2 EQU $+1 ; <--- BGii patch point + +CMND16: CALL SELDR1 ; select Drive from FCB + ; (also switches System bank) + JP CLOSE ; ..and continue in Banked code + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Close File + ; (continue CMND16) + ;-------------------------------------------------- +CLOSE: BIT 7,(IX+FCBMOD) ; test FCB/file modified + RET NZ ; ..if not, no close required + CALL CHKRO ; test disk W/P + CALL SRCT15 ; search file and test present + RET Z ; ..if not, then exit with error + CALL CKRODI ; check file W/P, get Directory entry + LD BC,16 ; offset to DM block + ADD HL,BC ; add offset + EX DE,HL ; save DIR ptr in DE + LD HL,(ARWORD) ; get FCB ptr + ADD HL,BC ; add offset + EX DE,HL + LD B,C ; transfer counter + + ; copy FCB (DE) to DIR (HL), if and only if DIR= 0 or DIR= FCB +CLOSE0: INC (HL) + DEC (HL) ; test DIR for 0 + LD A,(DE) ; get byte from FCB + JR Z,CLOSE1 ; ..if 0, ok to copy + CP (HL) ; test if same as DIR + JP NZ,RETCFF ; ..if not, abort close and return error +CLOSE1: LD (HL),A ; else save in DIR + INC DE + INC HL + DJNZ CLOSE0 ; bump pointers and loop until done + + LD DE,-20 ; add -20 to get extent number from DIR + ADD HL,DE ; HL= pointer to extent number + LD A,(IX+FCBEXT) ; get extent number FCB + CP (HL) ; compare with extent number Directory + JR C,CLOSE3 ; ..if FCB < Directory, then jump + LD (HL),A ; save extent number in Directory + INC HL ; get pointer to next record + INC HL + INC HL + LD A,(IX+FCBREC) ; get next record FCB + LD (HL),A ; save next record in Directory +CLOSE3: CALL CLOSE6 ; clear Archive bit and write FCB + CALL GETDME ; get data module and extent + JR Z,CLOSE4 + PUSH BC ; save prior module and extent + LD BC,0 + CALL SETDME ; set FCB data module and extent to 0 + CALL SRCT15 ; find proper DIR entry + POP BC + JR Z,JSETDME ; ..if extent 0 not found, exit +CLOSE4: PUSH BC + CALL CLOSE6 ; clear Archive bit and write FCB + LD B,4 ; mask for STFLAG (bit2 = Modify stamp) + LD HL,STUP ; address of stamp update routine + CALL STPMSK ; mask stamp type and update if enabled + POP BC ; get original module and extent bak +JSETDME: JP SETDME ; restore to FCB and exit + +CLOSE6: CALL CALDIR ; get directory entry + LD BC,11 ; point to Archive byte + ADD HL,BC + RES 7,(HL) ; reset Archive bit + RES 7,(IX+ARCATT) ; reset bit in FCB + + ; write FCB to disk +WRFCB: CALL CALDIR ; point to Dir entry to write + LD A,FCBUSR ; offset to User byte in FCB + CALL CALDI0 ; ..do the add here + LD (HL),0 ; prevent writing it to disk + CALL STDIR ; calculate setor/track Directory + LD C,0FFH ; update checksum Directory + CALL CHKDIR +WRITD1: CALL DMADIR ; set up DMA Directory (label for DS) + LD C,1 ; write Directory flag + CALL WRITER ; write record + JP STDMA ; set up DMA user + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 26 Set DMA Address + ; enter: DE= DMA Address, exit: A= 00H + ;-------------------------------------------------- +CMND26: LD (DMA),DE ; save DMA address + + ; set DMA address +STDMA: LD BC,(DMA) ; get DMA address + JR DMADR0 ; ..and do Bios call + + ; set DMA address Directory +DMADIR: LD BC,(DIRBUF) ; get DMA address Directory +DMADR0: JP SETDMA ; Bios call Set DMA + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;----- + ; get bit from ALV buffer + ; in: DE= block number + ; out: A= bit in LSB + ; B= bit number in A + ; HL= pointer in ALV buffer +GETBIT: LD A,E ; get bit number + AND 7 ; mask it + INC A ; +1 + LD C,A ; save it + SRL D ; get byte number + RR E ; divide DE by 8 + SRL D + RR E + SRL D + RR E + LD HL,(ALV) ; get start address ALV buffer + LD B,A ; save bit number for next shift + ADD HL,DE ; add byte number + LD A,(HL) ; get 8 bits +GETBT0: RLCA ; get correct bit + DJNZ GETBT0 + LD B,C ; restore bit number + RET ; and return to caller + + + ;-------------------------------------------------- + ; Delete File + ; (continue CMND19) + ;-------------------------------------------------- +DELETE: CALL COMCOD ; call common code w/ VDEL on stack + + ; delete core routine +VDEL: CALL CKRODI ; check file W/P, get Directory entry + LD (HL),0E5H ; remove file + INC HL + LD A,(HL) ; get first char + SUB '$' ; see if submit file + JR NZ,VDEL1 ; ..if not, skip over + LD (SUBFLG),A ; clear subflag if $*.* erased +VDEL1: INC HL + RES 7,(HL) ; ensure erased files are not public + LD C,0 ; remove bits ALV buffer + ; ..fall through and return to caller + + + ; fill bit buffer from FCB in DIRBUF + ; in: C= 0 reset bit, C= 1 set bit +FILLBB: CALL CALDIR ; get directory entry + LD DE,16 ; get offset DM block + ADD HL,DE ; add offset + LD B,E ; get block counter +FILLB0: LD E,(HL) ; get LSB block number + INC HL ; increment pointer + LD D,0 ; reset MSB block counter + LD A,(MAXLEN+1) ; test >256 blocks present + OR A + JR Z,FILLB1 ; ..if not, jump + DEC B ; decrement block counter + LD D,(HL) ; get correct MSB + INC HL ; increment block counter +FILLB1: LD A,D ; test block number + OR E + JR Z,FILLB2 ; ..if zero, then get next block + PUSH HL ; save pointer + PUSH BC ; save counter and set/reset bit + LD HL,(MAXLEN) ; get maximum length ALV buffer + OR A ; reset Carry + SBC HL,DE ; test DE <= maxlen ALV buffer + JR C,FILLB3 ; ..if yes, skip insert bit + + ; set/reset bit in ALV buffer +SETBIT: PUSH BC ; save set/reset bit + CALL GETBIT ; get bit + AND 0FEH ; mask it + POP DE ; get set/reset bit + OR E ; set/reset bit +SETBT0: RRCA ; rotate bit in correct position + DJNZ SETBT0 + LD (HL),A ; save 8 bits +FILLB3: POP BC ; get counter and set/reset bit + POP HL ; get pointer +FILLB2: DJNZ FILLB0 ; repeat for all DM entries + RET ; and return to caller + + + + ;_______________________// Non-Banked // + CSEG + + ;----- + ; check file W/P bit - SEARCH called first +CHKFRO: CALL CALDIR ; get Directory entry + LD DE,WHLATT ; offset to R/O bit + ADD HL,DE ; add offset + LD DE,(WHEEL) ; get Wheel byte address + LD A,(DE) ; retrieve the actual byte + AND A ; ..and check it + JR NZ,CHKFR4 ; we have Wheel, so allow writes + BIT 7,(HL) ; else, check Wheel attribute + JR NZ,CHKFR2 ; ..if yes, then jump error +CHKFR4: INC HL ; check W/P bit + BIT 7,(HL) ; test file W/P + JR NZ,CHKFR2 ; ..if W/P, then jump +CHKFR3: BIT 7,(IX+PSFATT) ; was file accessed as Pubic or Path ? + RET Z ; ..if normal access, return + LD A,(FLAGS) ; else, test for writes allowed + AND 0010B + RET NZ ; ..if writes allowed, go ahead +CHKFR2: LD HL,(SFILRO) ; ptr file W/P message (CP/M 2.2 vector table) + LD B,3 ; file W/P error code + LD DE,MFILRO ; load file W/P message + JP JUMPHL ; display message + + + ;----- + ; check Drive Write Protect +BGCKDRO: +CHKRO: CALL CHKRO1 ; is the disk W/P ? + RET NZ ; ..if disk is R/W, then return + LD B,2 ; else, set disk W/P error code + LD DE,MRO ; load drive W/P message + LD HL,(STRO) ; ptr Drive W/P message (CP/M 2.2 vector table) + JP JUMPHL ; display message + +CHKRO1: LD HL,(DSKWP) ; get W/P drive vector + CALL SDRVB ; set the bit for this drive + SBC HL,DE ; see if extra bit added (Carry is clear) + RET + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;----- + ; search using first 12 bytes of FCB +SEAR12: LD A,12 + DEFB 21H ; trash HL and fall through + + ; search using first 15 bytes of FCB +SEAR15: LD A,15 + + ; search for File Name + ; in: A= number of bytes for which to search +SEARCH: LD (SEARNB),A ; save number of bytes + LD A,0FFH ; set exit code to 0xFF (not found) + LD (SEAREX),A + LD (DCOPY),IX ; copy FCB pointer to RAM (search next) + CALL SETFCT ; initiate file counter + + ; force directory read with call home (Floppy only) + LD HL,(NCHECK) ; is this a fixed media ? + LD A,H + OR L + CALL NZ,HOME ; if removable, invoke Bios call Home routine + + ; search next File Name +SEARCN: XOR A ; checksum Directory + LD H,A + LD L,A + LD (SEARQU),HL ; clear flags, question mark and PUBlic found + RES 7,(IX+PSFATT) ; reset PUBlic/SYStem file flag + CALL RDDIR ; get FCB from Directory + CALL TSTFCT ; test if past last entry + JR Z,JSEAR8 ; ..if yes, jump (note Carry always clear) + LD DE,(DCOPY) ; get FCB pointer + LD A,(DE) ; get first byte + CP 0E5H ; test if searching empty Directory + JR Z,SEARC1 ; ..if yes, then jump + PUSH DE ; save FCB pointer + CALL TSTLF ; test last file on this Drive + POP DE ; restore FCB pointer +JSEAR8: JR NC,SEARC8 ; ..if yes, then jump + +SEARC1: CALL CALDIR ; get entry in Directory + LD A,(HL) ; get first byte Directory entry + AND 7FH ; mask high bit + CP 21H ; test time stamp + JR Z,SEARCN ; ..if yes, then get next Directory entry + LD C,0 ; clear counter + LD A,(SEARNB) ; get number of bytes to search for + LD B,A ; save it in counter +SEARC2: LD A,B ; test if character is zero + OR A + JR Z,SEARC9 ; ..if yes, then jump + LD A,(DE) ; get byte from FCB + XOR '?' ; test if question mark + AND 7FH ; mask it + JR Z,SEARC6 ; ..if yes, then jump + LD A,C ; get FCB counter + OR A ; test first byte + JR NZ,SEARC3 ; ..if not, then jump + LD A,(FLAGS) ; get flag byte + RRA ; test PUBlic file enable + JR NC,SEARC3 ; ..if not, jump + INC HL ; get pointer to PUBlic bit + INC HL + BIT 7,(HL) ; test PUBlic bit Directory + DEC HL ; restore pointer + DEC HL + JR Z,SEARC3 ; ..if no PUBlic file, then jump + LD A,(DE) ; get first byte FCB + CP 0E5H ; test if searching empty Directory + JR Z,SEARC3 ; ..if yes, then jump + + + ; The following 3 lines of code represent a deviation from description + ; of PUBlic files as given in DDJ article by Bridger Mitchell and Derek + ; McKay of Plu*Perfect Systems. The specification states that PUBlic + ; files will _NOT_ be found by any wildcard reference, except when a + ; '?' is in the FCB+0 byte. The code here relaxes that as follows: + ; If we are in the same User area as the PUBlic file, then don't report + ; file as PUBlic, but find it. This has a nasty side effect - PUBlic + ; files can be erased if we are in the same area. However, these files + ; also show up on the directory (they wouldn't otherwise), so at least + ; we should know we're blasting them. + + XOR (HL) ; test FCB = Directory entry + AND 7FH ; mask it (setting Zero flag) + JR Z,SEARC5 ; ..if user is same, jump + + LD A,0FFH + LD (SEARPU),A ; set PUBlic file found + SET 7,(IX+PSFATT) ; set PUBlic/SYStem file flag + JR SEARC5 ; jump found + +SEARC3: LD A,C ; get FCB counter + CP 13 ; is it User code ? + JR Z,SEARC5 ; ..if so, jump (don't test) + CP 12 ; is it an extent number ? + LD A,(DE) ; get byte from FCB + JR Z,SEARC7 ; ..if extent number, then jump + XOR (HL) ; is FCB byte = Directory Entry byte ? + AND 7FH ; mask it +SEARC4: JR NZ,SEARCN ; ..if not the same, jump and get next entry +SEARC5: INC DE ; increment FCB pointer + INC HL ; increment Directory Entry pointer + INC C ; increment counter + DEC B ; decrement counter + JR SEARC2 ; test next byte + +SEARC6: DEC A ; set question mark found flag + LD (SEARQU),A + JR SEARC5 ; jump found + +SEARC7: XOR (HL) ; test extent + CALL SEARC7A ; mask extent + JR SEARC4 ; ..and test result + +SEARC7A: PUSH BC + LD B,A ; save extent + LD A,(NEXTND) ; get extent mask + CPL ; complement it + AND MAXEXT ; mask it + AND B ; mask extent + POP BC ; restore counters + RET + +SEARC8: CALL SETFCT ; error set file counter + JP RETCFF ; set return code to 0xFF and exit + +SEARC9: LD HL,(SEARQU) ; get question mark and PUBlic found flags + LD A,H + AND L + JR NZ,SEARC4 ; ..if yes, then search for next entry + CALL TSTLF ; test for last file + CALL NC,SETLF0 ; and update if so + LD HL,(RECDIR) ; set DE return to Directory record + LD (DEVAL),HL ; ..for DateStamper simulation + LD A,(FILCNT) ; get file counter + AND 3 ; mask it + LD (PEXIT),A ; and set exit code + XOR A ; clear exit code search + LD (SEAREX),A + RET ; and return to caller + + + ;----- + ; common code of DELETE, RENAME, and CSTAT + ; (coded in a manner that is compatible with Z280 in protected mode) +COMCOD: CALL CHKRO ; check disk W/P + CALL SEAR12 ; search file +COMCO1: CALL TSTFCT ; test if file found + POP HL ; routine addr to HL (in case not found) + RET Z ; ..if not, then exit + PUSH HL ; else, found so routine back to stack + PUSH HL ; ..twice as RET pops first push + LD HL,COMCO2 + EX (SP),HL ; COMCO2 to stack, routine addr to HL + JP (HL) ; ..branch to routine + +COMCO2: CALL WRFCB ; write Directory buffer on disk + CALL SEARCN ; search next entry + JR COMCO1 ; and test it + + + ;----- + ; Rename File + ; note wildcard support +RENAM: CALL COMCOD ; go to common code w/ VRENAM on stack + + ; rename core routine +VRENAM: CALL CHKFRO ; check file W/P + LD HL,(ARWORD) ; get FCB address + LD DE,16 ; offset to new name + ADD HL,DE ; add offset + EX DE,HL ; swap regs + CALL CALDIR ; get Directory entry + INC HL + INC HL + RES 7,(HL) ; make any renamed file private + DEC HL + DEC HL + LD B,11 ; set up loop counter + +RENAM1: INC HL ; increment Directory pointer + INC DE ; increment FCB pointer + LD A,(DE) ; get character from FCB + AND 7FH ; mask it + CP '?' ; test if question mark + JR NZ,RENAM2 ; ..if not, then change character on disk + LD A,(HL) ; else, no change, so get what's there +RENAM2: RLA ; clear MSB + RL (HL) ; get MSB from directory + RRA ; and move to FCB + LD (HL),A ; save in directory + DJNZ RENAM1 ; loop until done + RET + + + ;----- + ; Change Status Bits for File +CSTAT: CALL COMCOD ; got to common code w/ VCSTAT on stack + + ; change core routine +VCSTAT: PUSH IX + POP DE ; FCB pointer in DE + CALL CALDIR ; get Directory entry + LD B,11 ; set up loop counter + +CSTAT1: INC HL ; increment Directory pointer + INC DE ; increment FCB pointer + LD A,4 ; are we pointing to Wheel Attribute ? + CP B + JR NZ,CSTAT2 ; ..if not, jump + PUSH HL + LD HL,(WHEEL) ; else, do we have Wheel privileges ? + LD A,(HL) + POP HL + AND A ; set flags to show + JR NZ,CSTAT2 ; ..if we have Wheel, jump + BIT 7,(HL) ; is file Wheel protected ? + JP NZ,CHKFR2 ; ..if so, jump +CSTAT2: LD A,(DE) ; get status bit from FCB + RL (HL) ; remove MSB of Directory + RLA ; get MSB from FCB + RR (HL) ; and move into Directory char + DJNZ CSTAT1 ; loop till done + RET + + + ;----- + ; Compute File Size +FILSZ: LD BC,0 ; reset file size length + LD D,C + CALL LDRRC ; save it in FCB+33,34,35 + CALL SEAR12 ; search file +FILSZ0: CALL TSTFCT ; test if file found + RET Z ; ..if not, exit + + CALL CALDIR ; get Directory entry + EX DE,HL ; copy to DE + LD HL,15 ; offset to next record + CALL CALRRC ; calculate random record count + LD A,D ; test LSB < (IX+33) + SUB (IX+33) + LD A,C ; test ISB < (IX+34) + SBC A,(IX+34) + LD A,B ; test MSB < (IX+35) + SBC A,(IX+35) + CALL NC,LDRRC ; write new maximum + CALL SEARCN ; search next file + JR FILSZ0 ; and test it + + + ;-------------------------------------------------- + ; Find File + ; (called by CMND15) + ;-------------------------------------------------- +FINDF: CALL SRCT15 ; search file + RET NZ ; ..if found, then exit + LD A,(FLAGS) + BIT 5,A ; test if Path enabled + RET Z ; ..if not, exit + LD HL,(PATH) ; get Path address + LD A,H ; test if zero (no Path) + OR L + RET Z ; ..if so, exit + +FINDF0: CALL DUPATH ; test if current DU: is in Path + JP Z,SEARC8 ; ..if not, then jump + LD A,B ; Drive in A + PUSH BC ; save DU + PUSH HL + CALL SELDK + ; ##### PUSH HL first, then BC + ; saves POP HL + next PUSH HL (2 bytes) + POP HL + POP BC + LD A,C ; User in A + PUSH HL ; save Path pointer + CALL RESUSR ; add new User number in FCB+0 and FCB+13 + CALL SRCT15 ; search file and test if present + POP HL ; restore Path pointer + JR Z,FINDF0 ; ..if not present, then test next Path entry + PUSH HL ; save Path pointer + CALL CALDIR ; get Directory entry + LD DE,10 ; add offset SYStem bit + ADD HL,DE + BIT 7,(HL) ; test SYStem file + LD A,(FLAGS) ; test for relaxed Path definition + RLA ; ..by rotating bit + RLA ; ..into Carry flag + POP HL ; restore Path pointer + JR C,FINDF3 ; ..if Carry, SYStem attribute not required + JR Z,FINDF0 ; else, SYStem file, so test next Path entry +FINDF3: LD A,(DEFDRV) ; get current Drive + INC A ; increment Drive number + LD (FCB0),A ; save it in exit FCB0 + SET 7,(IX+PSFATT) ; set PUBlic/SYStem file flag + RET ; and return to caller + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 15 Open File + ; enter: DE= address of FCB, exit: A= Directory Code + ;-------------------------------------------------- +CMND15: CALL SELDRV ; select Drive from FCB + ; (also switches System bank) + LD A,32 ; 32 bytes + LD (FCBBUP),A ; ..to update in FCB + LD (IX+FCBMOD),0 ; clear data module number + CALL FINDF ; find file using Path (..in Banked code) + CALL TSTFCT ; test file found (..in Banked code) + RET Z ; ..if not, then exit + +OPENF0: LD A,(IX+PSFATT) ; get PUBlic/SYStem file bit + PUSH AF ; save it + LD A,(IX+FCBEXT) ; get extent number from FCB + PUSH AF ; save it + CALL CALDIR ; get Directory entry + LD A,(HL) ; find real User number file is in + OR 80H ; set User valid flag + PUSH IX ; save FCB entry + POP DE ; get in DE + LD BC,32 ; number of bytes to move + LDIR ; move Directory to FCB + LD (IX+FCBUSR),A ; and put User byte back + SET 7,(IX+FCBMOD) ; set FCB/File not modified + LD B,(IX+FCBEXT) ; get extent number + LD C,(IX+FCBREC) ; get next record number + POP AF ; get old extent number + LD (IX+FCBEXT),A ; save it + CP B ; compare old and new extent number + JR Z,OPENF1 ; ..if same, then jump + LD C,0 ; set next record count to 0 + RR C ; record count to max (0x80) if need new extent +OPENF1: LD (IX+FCBREC),C ; save next record count + POP AF ; get PUBlic/SYStem file bit + RL (IX+PSFATT) ; remove MSB from IX+7 + RLA ; set new MSB in Carry + RR (IX+PSFATT) ; save Carry in IX+7 + LD B,1 ; mask for STFLAG (bit0 = Access stamp) + LD HL,STLA ; address of last accessed routine + JP STPMSK ; ..and continue in Banked code + + + ;-------------------------------------------------- + ; fn # 22 Make File + ; enter: DE= Address of FCB, exit: A= Directory Code + ;-------------------------------------------------- +CMND22: CALL SELDRV ; select Drive from FCB + LD (IX+FCBMOD),0 ; clear data module number + LD A,32 ; 32 bytes + LD (FCBBUP),A ; save # bytes to update in FCB +MAKES: CALL CHKRO ; check drive W/P + CALL SELSYB ; switch System bank + JP MAKESB ; ..and continue in Banked code + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Make File + ; (continue CMND22 / MAKES) + ;-------------------------------------------------- +MAKESB: LD HL,(ARWORD) + LD A,(HL) ; get first byte of FCB + PUSH AF ; save it + LD (HL),0E5H ; set first byte to empty file + LD A,1 ; search for 1 byte + CALL SEARCH ; search empty file + POP AF ; get first byte of FCB + LD (IX+0),A ; restore it + CALL TSTFCT ; test empty file found + RET Z ; ..if not, return error + LD HL,(ARWORD) ; get FCB pointer + CALL CKSUB ; check if this is a submit file + LD DE,15 ; prepare offset + ADD HL,DE ; add it + LD B,17 ; set counter + CALL CLRMEM ; clear FCB+15 up to FCB+31 + RES 7,(IX+PSFATT) ; reset PUBlic/SYStem file bit + RES 7,(IX+ARCATT) ; reset Archive bit if present + CALL CALDIR ; get Directory entry + PUSH IX ; save FCB entry + POP DE ; get it in DE + EX DE,HL ; exchange FCB and Directory entry + LD BC,32 ; number of bytes to copy + LDIR + CALL WRFCB ; write FCB on disk + SET 7,(IX+FCBMOD) ; set FCB/File not modified + LD B,2 ; mask for STFLAG (bit1 = Create stamp) + LD HL,STCR ; address stamp create routine + JP STPMSK ; mask type and stamp file if enabled + + + ;----- + ; open next extent +OPENEX: BIT 7,(IX+FCBMOD) ; test if FCB/File modified (write) + JR NZ,OPENX2 ; ..if not, jump + CALL CLOSE ; close current FCB + LD A,(PEXIT) ; get exit code + INC A ; test if error + RET Z ; ..if so, exit +OPENX2: CALL CALNEX ; calculate next extent + JR C,OPENX3 ; ..if error, jump + +OPENX0: CALL SRCT15 ; search for 15-char match and test presence + JR NZ,OPENX5 ; ..if yes, jump + LD A,(RDWR) ; test Read/Write flag + OR A ; test if read + JR Z,OPENX3 ; ..if yes, then error + CALL MAKES ; make new extent if write + CALL TSTFCT ; test if successful + JR NZ,OPENX6 ; ..if yes, then exit +OPENX3: SET 7,(IX+FCBMOD) ; set FCB/File not modified +RETCFF: LD A,0FFH ; set exit code +OPENX4: JP SAVEA ; and return to caller + +OPENX5: CALL OPENF0 ; open file +OPENX6: XOR A ; clear exit code + JR OPENX4 ; use same code to exit routine + + + ;----- + ; calculate next extent + ; out: Carry set (C) if overflow detected +CALNEX: CALL GETDME ; get extent number, data module number + BIT 6,B ; test error bit random record + SCF ; set error flag + RET NZ ; ..if non-zero, error exit + INC C ; increment extent number + LD A,C ; get extent number + AND MAXEXT ; mask it for max extent + LD C,A ; save it in C + JR NZ,CALNE1 ; ..if new data module not required, jump + INC B ; set next data module + LD A,B ; get it in A + AND MAXMOD ; mask it for max module + LD B,A ; save it in B + SCF ; set error flag + RET Z ; ..if file overflow, return +CALNE1: LD (IX+NXTREC),0 ; zero next record count +SETDME: LD (IX+FCBEXT),C ; save extent number + LD (IX+FCBMOD),B ; save data module number + AND A ; clear flag + RET + +GETDME: LD C,(IX+FCBEXT) ; get extent number + LD B,(IX+FCBMOD) ; get data module number + LD A,C + CALL SEARC7A ; mask extent + RES 7,B ; clear unmodified flag + OR B ; test for module and extent = 0 + RET ; ..and return to caller + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 33 Read Random Record + ; enter: DE= Address of FCB, exit: A= Read/Write Code + ;-------------------------------------------------- +CMND33: CALL SELDR1 ; select Drive from FCB + LD A,36 + LD (FCBBUP),A ; save # bytes to update in FCB + + ; read random sector + XOR A ; set Read/Write flag + CALL LDFCB ; load FCB random record (..in Banked code) + JR Z,READS ; ..if no error, then read sector + RET + + + ;-------------------------------------------------- + ; fn # 20 Read Sequential + ; enter: DE= Address of FCB, exit: A= Read/Write Code + ;-------------------------------------------------- +CMND20: CALL SELDR1 ; select Drive from FCB + ; (also switches System bank) + LD A,33 ; 33 bytes + LD (FCBBUP),A ; save # bytes to update in FCB + + ; read sector +READS: JP READSB ; ..continue in Banked code + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Read Sector + ; (continue CMND20 / READS) + ;-------------------------------------------------- +READSB: XOR A ; set Read/Write flag + LD (RDWR),A ; save it + LD A,(IX+NXTREC) ; get record counter + CP 80H ; test if last record in this extent + JR Z,READSB1 ; ..if yes, then open next extent + CP (IX+FCBREC) ; test if greater than current record + JR C,READSB2 ; ..if not, then get record +READSB0: LD A,1 ; set end of file flag + JP SAVEA ; and exit + +READSB1: CALL OPNXCK ; open next extent +READSB2: CALL GETDM ; get block number from DM in FCB + JR Z,READSB0 ; ..if block number= 0, jump to end of file + CALL CALSEC ; calculate sector number (128 bytes) + CALL CALST ; calculate sector/track number + CALL READR ; read data + JP WRITS7 ; increment elsewhere if necessary + + + ;----- + ; consolidated routine to open extent and check status +OPNXCK: CALL OPENEX ; open next extent + LD A,(PEXIT) ; get exit code + OR A + RET Z ; return if open OK + POP HL ; else, pop return address to abort R/W + JR READSB0 ; ..and set error code to EOF + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 34 Write Random + ; fn # 40 Write random with zero fill + ; enter: DE= Address of FCB, exit: A= Read/Write Code + ;-------------------------------------------------- +CMND34: +CMND40: CALL SELDR1 ; select Drive from FCB + LD A,36 ; 36 bytes + LD (FCBBUP),A ; save # bytes to update in FCB + + ; write random sector and write random with zero fill + LD A,0FFH ; set Read/Write flag + CALL LDFCB ; load FCB random record (..in Banked code) + JR Z,WRITES ; ..if no error, then write record + RET ; else, return error + + + ; ##### CHECK: unreferenced code + CALL CHKRO ; check drive W/P status + PUSH IX + LD IX,ZSFCB ; buffer internal FCB + CALL NOTUSE1 ; write sector + JP NOTUSE3 + RET + ; ##### + + + ;-------------------------------------------------- + ; fn # 21 Write Sequential + ; enter: DE= Address of FCB, exit: A= Read/Write Code + ;-------------------------------------------------- +CMND21: CALL SELDR1 ; select Drive from FCB + LD A,33 ; 33 bytes + LD (FCBBUP),A ; save # bytes to update in FCB + + ; write sector - permitted to PUBlic file and those found along Path +WRITES: LD A,0FFH ; set Read/Write flag + LD (RDWR),A ; save it + +BGPTCH1 EQU $+1 ; <--- patched location for BGii + + CALL CHKRO ; check disk W/P +NOTUSE1: CALL SELSYB ; switch System bank + JP WRITESB ; ..and continue in Banked code + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Write Sector + ; (continue CMND21 / WRITES) + ;-------------------------------------------------- +WRITESB: BIT 7,(IX+ROATT) ; test if file W/P + JR NZ,WRITSA ; ..if yes, then file W/P message + CALL CHKFR3 ; test W/P if Path or Public used + LD HL,(WHEEL) ; get address of Wheel byte + LD A,(HL) ; do we have Wheel privileges ? + AND A + JR NZ,WRITSB ; ..if yes, allow write + BIT 7,(IX+WHLATT) ; else, test if file is Wheel protected +WRITSA: JP NZ,CHKFR2 ; ..if so, then file W/P message +WRITSB: BIT 7,(IX+NXTREC) ; end of this extent ? + CALL NZ,OPNXCK ; open next extent and check status + CALL GETDM ; get block number from FCB + JP NZ,WRITS5 ; ..if not zero, then jump to write sector + PUSH HL ; save pointer to block number + LD A,C ; test first block number in extent + OR A + JR Z,WRITS1 ; ..if yes, then jump + DEC A ; decrement pointer to block number + CALL GETDM4 ; get previous block number + + + ; get free block from ALV buffer + ; in: DE= old block number + ; out: DE= new block number, 0 if no free block + ; (HL counts up, DE counts down) +WRITS1: LD H,D ; copy old block to HL + LD L,E +GETFR0: LD A,D ; test down counter is zero + OR E + JR Z,GETFR1 ; ..if so, jump + DEC DE ; decrement down counter + PUSH HL ; save up/down counter + PUSH DE + CALL GETBIT ; get bit from ALV buffer + RRA ; test if zero + JR NC,GETFR3 ; ..if yes, then found empty block + POP DE ; get up/down counter + POP HL +GETFR1: LD BC,(MAXLEN) ; get maximum ALV length-1 in BC + LD A,L ; is HL >= length ALV-1 ? + SUB C ; ..do while preserving HL + LD A,H + SBC A,B + JR NC,GETFR2 ; ..if end of buffer, then jump + INC HL ; increment up counter + PUSH DE ; save down/up counter + PUSH HL + EX DE,HL ; up counter in DE + CALL GETBIT ; get bit from ALV buffer + RRA ; test if zero + JR NC,GETFR3 ; ..if yes, then found empty block + POP HL ; get down/up counter + POP DE + JR GETFR0 ; and test next block + +GETFR2: LD A,D ; test if last block testet + OR E + JR NZ,GETFR0 ; ..if not, then test next block + JR WRITSG ; continue with DE= 0 + +GETFR3: SCF ; set block number used + RLA ; save bit + + ; SETBT0 code now inline +GETFR4: RRCA ; rotate bit in correct position + DJNZ GETFR4 + LD (HL),A ; save 8 bits + POP DE ; get correct counter + POP HL ; restore stack pointer + ; ..continue with (DE= block number) + +WRITSG: POP HL ; get pointer to block number + LD A,D ; test if block number = 0 + + ; WRITS8 code now inline + OR E + LD A,2 ; set disk full error + JP Z,SAVEA ; and return to caller + RES 7,(IX+FCBMOD) ; reset FCB/File modified + LD (HL),E ; save block number + LD A,(MAXLEN+1) ; get number of blocks + OR A ; is it < 256 ? + JR Z,WRITS2 ; ..if so, jump + INC HL ; increment to MSB block number + LD (HL),D ; ..and save MSB block number +WRITS2: LD C,2 ; set write new block flag + LD A,(NMASK) ; get sector mask + AND (IX+NXTREC) ; mask with record number + JR Z,WRITSX ; ..if zero, then Ok (at start new record) + LD C,0 ; else, clear new block flag +WRITSX: LD A,(FUNCT) ; get function number + SUB 40 ; test if Write Random Record with zero fill + JR NZ,WRITS6 ; ..if not, then jump + PUSH DE ; save block number + LD HL,(DIRBUF) ; use Directory buffer for zero fill + LD B,128 ; 128 bytes to clear + CALL CLRMEM ; do clear + CALL CALSEC ; calculate sector number (128 bytes) + LD A,(NMASK) ; get sector mask + LD B,A ; copy it + INC B ; increment it to get number of writes + CPL ; complement sector mask + AND E ; mask sector number + LD E,A ; and save it + LD C,2 ; set write new block flag +WRITS4: PUSH HL ; save registers + PUSH DE + PUSH BC + CALL CALST ; calculate sectors/track + CALL DMADIR ; set DMA Directory buffer + POP BC ; get write new block flag + PUSH BC ; save it again + CALL WRITER ; write record on disk + POP BC ; restore registers + POP DE + POP HL + LD C,0 ; clear write new block flag + INC E ; increment sector number + DJNZ WRITS4 ; write all blocks + CALL STDMA ; set user DMA address + POP DE ; get block number +WRITS5: LD C,0 ; clear write new block flag +WRITS6: RES 7,(IX+FCBMOD) ; reset FCB/File modified flag + PUSH BC ; save it + CALL CALSEC ; calculate sector number (128 bytes) + CALL CALST ; calculate sectors/track + POP BC ; get write new block flag + CALL WRITER ; write record on disk + LD A,(IX+NXTREC) ; get record counter + CP (IX+FCBREC) ; compare with next record + JR C,WRITS7 ; ..if less, then jump + INC A ; increment record count + LD (IX+FCBREC),A ; save it on next record position + RES 7,(IX+FCBMOD) ; reset FCB/File modified flag +WRITS7: LD A,(FUNCT) ; get function number + CP 20 + RET C ; return if < 20 + CP 21+1 + RET NC ; return if > 21 + INC (IX+NXTREC) ; increment record count + RET ; and return to caller + + + ;-------------------------------------------------- + ; Load FCB for random read/write + ; (called by CMND33 / CMND34 / CMND40) + ;-------------------------------------------------- + ; out: Zero Flag set (Z) = no error, reset (NZ) if error +LDFCB: LD (RDWR),A ; save Read/Write flag + LD A,(IX+33) ; get first byte random record + LD D,A ; save it in D + RES 7,D ; reset MSB to get next record + RLA ; shift MSB in Carry + LD A,(IX+34) ; load next byte random record + RLA ; shift Carry + PUSH AF ; save it + AND MAXEXT ; mask next extent + LD C,A ; save it in C + POP AF ; get byte + RLA ; shift 4 times + RLA + RLA + RLA + AND 00FH ; mask it + LD B,A ; save data module number + LD A,(IX+35) + LD E,6 ; set random record too large flag + CP 4 ; test random record too large + JR NC,LDFCB8 ; ..if yes, then error + RLCA ; shift 4 times + RLCA + RLCA + RLCA + ADD A,B ; add byte + LD B,A ; save data module number in B + LD (IX+NXTREC),D ; set next record count + LD D,(IX+FCBMOD) ; get data module number + BIT 6,D ; test error random record + JR NZ,LDFCB0 ; ..if yes, then jump + LD A,C ; get new extent number + CP (IX+FCBEXT) ; compare with FCB + JR NZ,LDFCB0 ; ..if not equal, then open next extent + LD A,B ; get new data module number + XOR (IX+FCBMOD) ; compare with data module number + AND MAXMOD ; mask it + JR Z,LDFCB6 ; ..if equal, then return +LDFCB0: BIT 7,D ; test FCB modified (write) + JR NZ,LDFCB1 ; ..if no, then jump + PUSH DE ; save registers + PUSH BC + CALL CLOSE ; close extent + POP BC ; restore registers + POP DE + LD E,3 ; set close error + LD A,(PEXIT) ; get exit code + INC A + JR Z,LDFCB7 ; ..if error, then exit +LDFCB1: CALL SETDME ; save data module and extent + CALL SEAR15 ; search next FCB + LD A,(PEXIT) ; get error code + INC A + JR NZ,LDFCB5 ; if no error, then exit + LD A,(RDWR) ; get Read/Write flag + LD E,4 ; set read empty record + INC A + JR NZ,LDFCB7 ; ..if read error, then jump + CALL MAKES ; make new FCB + LD E,5 ; set make error + LD A,(PEXIT) ; get error code + INC A + JR Z,LDFCB7 ; ..if error, then exit + JR LDFCB6 ; else, exit w/ zero set (no error) +LDFCB5: CALL OPENF0 ; open file +LDFCB6: JP OPENX6 ; set zero flag and clear error code +LDFCB7: LD (IX+FCBMOD),0C0H ; set random record error +LDFCB8: LD A,E ; get error code + LD (PEXIT),A ; and save it + OR A ; clear Zero flag +SETB14: SET 7,(IX+FCBMOD) ; set FCB/File not modified + RET ; and return to caller + + + + ;_______________________// Non-Banked // + CSEG + + ;----- + ; calculate random record + ; in: HL= offset in FCB + ; DE= FCB pointer + ; out: D= LSB random record + ; C= ISB + ; B= MSB +CALRRC: ADD HL,DE ; pointer to FCB+15 or FCB+32 + LD A,(HL) ; get record number + LD HL,12 ; offset to extent number + ADD HL,DE ; get pointer to extent byte + LD D,A ; save record number + LD A,(HL) ; get extent byte + AND MAXEXT ; mask it (000eeeee) + RL D ; shift MSB in Carry (Cy= R, D= rrrrrrr0) + ADC A,0 ; add Carry (00xeeeeex) + RRA ; shift 1 time (16 bits, 000xeeee) + RR D ; D= xrrrrrrr + LD C,A ; save ISB + INC HL ; increment to data module number + INC HL + LD A,(HL) ; get data module number 00mmmmmmm + RRCA ; divide module by 16 + RRCA + RRCA + RRCA + PUSH AF ; save it mmmm00mm + AND 03H ; mask for maximum module + LD B,A ; save it 000000mm + POP AF ; get LSB + AND 0F0H ; mask it mmmm0000 + ADD A,C ; add with ISB mmmxeeee + LD C,A ; save ISB + RET NC ; no Carry then return + INC B ; increment MSB 000000mm + RET ; and return to caller + ; 000000mm mmmxeeee xrrrrrrr + + + ;----- + ; clear/fill memory +CLRM4: LD B,4 ; clear memory area (used by MAKES and WRITSX) + +CLRMEM: XOR A ; clear A + + ; fill memory with byte in A + ; in: A= byte + ; B= counter (# bytes) + ; HL= destination +FILLM: LD (HL),A ; store byte + INC HL ; increment pointer + DJNZ FILLM ; and clear all bytes + RET + + + ;----- + ; check/update !!!TIME&.DAT checksum + ; calc checksum of 127 bytes, return with HL pointing to 128th byte + ; in: DIRBUF= pointer to T&D record + ; out: A= checksum + ; HL= points to checksum byte in record +CKS127: LD HL,(DIRBUF) ; directory buffer pointer + XOR A ; clear A + LD B,127 ; test first 127 bytes +CKSLP: ADD A,(HL) ; sum all bytes to A + INC HL + DJNZ CKSLP + RET + + + ;----- + ; get word (16-bit value) indirectly + ; in: HL= base addr + ; A= offset + ; out: HL= 16-bit value at offset addr + ; Z-Flag set if HL= 0 +GWHLA: CALL CALDI0 ; add A to HL + LD A,(HL) ; get low byte at memory location + INC HL + LD H,(HL) ; get high byte + LD L,A + OR H ; test if zero (set return status) + RET + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;----- + ; test if Drive is valid + ; in: B= drive number + ; out: Carry flag set (C) = ok, NC= not ok +DRVOK: LD HL,(OZ3ENV) ; B/P Bios base +0x98 (addr Z3 ENV decriptor) + LD A,H ; test if valid (<> zero) + OR L + JR Z,DRVOK1 ; ..if not, jump exit (assume drive is valid) + LD A,8 ; else, offset to Env type (ENV base +8) + CALL CALDI0 ; move ptr fwd + BIT 7,(HL) ; is it extended (=> 0x80) ? + JR Z,DRVOK1 ; ..if not, jump + LD A,44 ; move ptr fwd to DRVEC + CALL GWHLA ; ..and get vector of valid drives in HL + LD A,16 ; set up loop counter + SUB B ; adjust to drive in scope +DRVOK0: DEC A ; counter -1 + ADD HL,HL ; "shift" MSB into Carry + JR NZ,DRVOK0 ; loop + RET ; ..and return with status in Carry +DRVOK1: SCF ; set return status (Carry set = Ok) + RET + + + + ;_______________________// Non-Banked // + CSEG + + ;----- + ; test if current DU: is in Path + ; in: HL= path address + ; out: B= current drive, C= current user + ; A= 0xFF, Z-Flag clear (NZ) if match or '$$' + ; Z-Flag set if no match +DUPATH: LD BC,(USER) ; get default drive (B) and user number (C) + LD A,(HL) ; get byte of path entry + OR A ; test for end + RET Z ; ..if yes, then return with Z-Flag set + CP '$' ; test if current drive + JR Z,DUPAT0 ; ..if so, then jump + DEC A ; decrement drive number of path entry + LD B,A ; ..and save in B +DUPAT0: INC HL ; advance pointer + LD A,(HL) ; get user number + CP '$' ; test if current user + JR Z,DUPAT1 ; ..if so, then jump + LD C,A ; else, save in C +DUPAT1: INC HL ; advance pointer + OR 0FFH ; set exit code to 0xFF (match) + RET ; and return to caller + + + ;-------------------------------------------------- + ; fn # 46 Return Free Space + ; enter: E= Disk Number, exit: A= Error Code + ; Space in DMA+0..DMA+3 + ;-------------------------------------------------- +CMND46: CALL CMND14 ; select disk from E register + CALL SELSYB ; switch System bank + CALL CMD46B ; ..and continue in Banked code + JP DOSEXT1 + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ;-------------------------------------------------- + ; Return Free Space + ; (continue CMND46) + ;-------------------------------------------------- +CMD46B: LD HL,DFCALC + CALL CLRM4 ; clear 4 bytes + LD DE,(MAXLEN) ; get maximum blocks-1 + INC DE ; +1 + LD HL,(ALV) ; get ptr to allocation vector + + ; process one byte of ALV - outer loop +DFREE1: LD C,(HL) ; get bit pattern of allocation byte + PUSH HL ; save pointer + LD B,8 ; process 8 bits +DFREE2: RL C ; shift MSB to Carry + CCF ; invert + JR NC,DFREE4 ; ..if MSB was 1, then jump + + ; count zeros - inner loop + PUSH BC + LD B,4 + LD HL,DFCALC +DFREE3: LD A,(HL) + ADC A,0 ; add Carry + LD (HL),A ; ..and save back + INC HL ; move ptr + DJNZ DFREE3 ; loop till done + + POP BC +DFREE4: DEC DE ; decrease number of blocks + LD A,E ; test if zero + OR D + JR Z,DFREE5 ; ..if zero, exit inner loop + DJNZ DFREE2 + POP HL ; restore ALV ptr + INC HL ; move to next byte + JR DFREE1 ; ..and loop (outer) + + ; allocation is measured in blocks, convert to kB +DFREE5: POP HL ; clear stack + LD A,(NBLOCK) ; get block shift factor + SUB 3 ; (BSH= 3 -> 1k, 4 -> 2k, ...8 -> 32k) + JR Z,DFREEX ; if BSH-3 = 0, then we're done + + ; multiply 32-bit (4 bytes) +DFREE6: LD HL,DFCALC ; set ptr to data storage + LD B,4 ; bytes to work +DFREE7: RL (HL) ; shift MSB into Carry + INC HL ; move ptr + DJNZ DFREE7 ; ..and loop + DEC A + JR NZ,DFREE6 ; if not zero, loop for next block size + ; ..else, fall through and transfer data + + + ; transfer to DMA using interbank move + ; (destination could be in a disabled memory bank) +DFREEX: LD A,(TPABNK) ; get TPA bank # + LD B,A ; ..in B + LD A,(OSYSBK) ; get SYS bank # (Bios base +0x83 SYSBNK) + LD C,A ; ..in C + CALL XMOVE ; call Bios fn #29 XMOVE, set banks for MOVE + LD HL,DFCALC ; source address + LD DE,(DMA) ; destination address + LD BC,4 ; bytes to move + JP MOVE ; ..and do it (Bios fn #25) + + + + ;_______________________// Banked Data Segment // + COMMON /B2RAM/ + + ; Disk free calculation data area (4 bytes) +DFCALC: DEFS 4 +; DEFB 0,0,0,0 + + + + ;_______________________// Non-Banked // + CSEG + + ;-------------------------------------------------- + ; fn # 152 Parse FileSpec + ; enter: DE= FCB Address, exit: A= Number of '?'s in Fn.Ft + ; String in DMA Buffer DE= Address of delimiter char + ; FCB+15= 0 if Parse Ok, 0FFH if Error(s) + ;-------------------------------------------------- +CMD152: PUSH DE ; save ptr to FCB + XOR A + LD (DE),A ; clear FCB Drive field + INC DE ; move ptr fwd + LD A,' ' ; prepare to init FCB name and type fields + LD B,8+3 +CM152A: LD (DE),A + INC DE + DJNZ CM152A + + ; destination FCB initialized + POP DE ; restore ptr to FCB + LD HL,(DMA) ; get DMA address + LD BC,(USER) ; get User number + LD A,C ; ..in A + LD (STATUS),A ; and save as status + CALL SCANF8 ; place first token (8-bytes) in name field + CP ':' ; is the delimiter a Colon ? + LD A,0 ; prepare status flag for ok DU/DIR + JP NZ,SCAN1 ; ..if only a file name, then jump + + INC HL ; point to char after Colon + PUSH HL + PUSH DE + CALL CMND49 ; get address of Z3 Environment + ; ##### CHECK: should jump further down ? (repeats CALL CMND49) + JR Z,DUSCAN ; ..if none found, jump + LD A,21 ; offset to Z3NDIR (addr Named Dir Buffer) + CALL GWHLA ; get vector at offset memory location + JR Z,DUSCAN ; ..if address not valid, jump to DU scan + INC DE + + ; scan Named Dir entries +DIRS1: CALL DUPATH ; test if current DU: in Path + JR Z,DUSCAN ; ..if not, then jump + PUSH BC ; save DU + PUSH HL ; save ptr to file name + PUSH DE ; save ptr to NDR entry + LD B,8 ; max 8 chars +DIRS2: LD A,(DE) ; get char + CP (HL) ; compare to NDR entry + JR NZ,DIRS3 ; ..if no match, exit loop + INC HL ; else, point to next char + INC DE + DJNZ DIRS2 ; loop + +DIRS3: POP DE ; restore regs + POP HL + POP BC + JR Z,CHKVVC ; ..if ok, then jump + LD BC,16 ; 8 bytes name + 8 bytes password + ADD HL,BC ; advance ptr + JR DIRS1 + + ; scan Drive/User +DUSCAN: CALL CMND49 ; get address of Z3 Environment + JR Z,DUS0 ; ..if none found, jump + + LD A,46 ; offset to DU Flag + CALL CALDI0 ; move ptr fwd + LD A,(HL) ; get byte at memory location + OR A + JR Z,DUSERR ; ..if zero, then jump + ; (1= ok to accept DU:, 0= not ok) + + ; no Z3 Envorionment, assume DU: form and scan/extract Drive/User +DUS0: LD L,C + EX DE,HL + CALL DELIM + EX DE,HL + CP ' '+1 ; legal char ? + JR C,DUSOK ; ..if only delimiter, jump w/ current DU + SUB 41H ; convert possible drive spec to number + JR C,DUS1 ; ..if less than 'A', must be digit + + ; set Drive number (0= A) + LD B,A ; save drive in B + INC DE ; point to next input char + LD A,(DE) ; get char + CP ' '+1 ; end of string ? + JR C,DUCHEK ; ..if so, jump to check limits + + ; set User number +DUS1: LD HL,2*256 ; get up to 2 digits +DUS1A: LD A,(DE) + CP ' '+1 ; is it a delimiter ? + JR C,DUS2 ; ..if so, jump to end + SUB '0' ; digit ? + JR C,DUSERR ; ..if not, jump + CP 10 ; number in range (0..9) ? + JR NC,DUSERR ; ..if not, jump + LD C,A ; save + LD A,L ; ..and multiply old digit + ADD A,A ; *2 + ADD A,A ; *4 + ADD A,L ; *5 + ADD A,A ; *10 + ADD A,C + LD L,A + INC DE ; advance to next byte + DEC H ; count down + JR NZ,DUS1A ; ..loop if more to go + LD A,(DE) +DUS2: CP ' ' ; is it the proper delimiter ? + JR NZ,DUSERR ; ..if not, jump error exit + LD C,L ; save good User in C + + + ; BC now has parsed DU:, check legality +DUCHEK: LD HL,(USER) ; get currently logged DU + OR A + SBC HL,BC ; same as that parsed ? + JR Z,DUSOK ; ..if so, take good exit + +CHKVVC: CALL SELSYB ; switch System bank + CALL DRVOK ; check if drive is valid + CALL SELTPB ; switch back to TPA bank + JR C,DUSOK + +DUSERR: LD BC,(USER) ; get current DU + DEFB 0F6H ; fall through with OR A,0AFH + +DUSOK: XOR A ; set return status OK + POP DE + POP HL + PUSH AF + LD A,B ; get drive # + INC A ; change to A= 1 base + LD (DE),A ; store in FCB+0 + LD A,C ; get User # + LD (STATUS),A ; store in mem + CALL SCANF8 ; scan token (8-byte) + POP AF ; restore A cleared + ; ..and fall through + + + ; skip to file type field + ; in: HL= ptr to next char + ; DE= ptr to DN field of FCB +SCAN1: PUSH AF ; save error flag for exit + EX DE,HL + LD BC,8 ; point to before file type field of FCB + ADD HL,BC + EX DE,HL ; Extract file type field + LD B,3 + LD A,(HL) ; get the delimiter char + CP '.' ; is it '.' ? + JR NZ,SCAN2 ; ..if no type, then jump + INC HL ; else, point to char after '.' + CALL SCANF ; ..and get file type +SCAN2: LD (DEVAL),HL + INC DE ; move ptr from last char of name to T1 + INC DE ; ..to T2 + INC DE ; ..to T3 + INC DE ; ..to EXM + XOR A ; zero + LD (DE),A ; store here at FCB+12 (EXM) + INC DE ; move to S1 + LD A,(STATUS) ; get User number + LD (DE),A ; ..and store it here at FCB+13 (S1) + INC DE ; move ptr to S2 + XOR A ; zero + LD (DE),A ; store here at FCB+14 (S2) + INC DE ; move ptr to FCB+15 + POP AF ; restore error flag + LD (DE),A ; ..and save it in FCB+15 + RET + + + ;----- + ; scan up to 8 chars +SCANF8: XOR A ; get a 0 + LD (PEXIT),A ; ..and clear question mark counter + LD B,8 ; scan for up to 8 chars + ; ..fall through to main scan routine + + ; scan token with interpreting/expanding '*' and '?' wild cards + ; in: B= max number of bytes + ; HL= ptr to token + ; DE= destination addr (FCB file name field) + ; out: HL= ptr to terminating delimiter +SCANF: PUSH DE ; preserve FCB address +SCANF0: INC DE ; ptr to next byte in FCB + CALL DELIM ; is it a delimiter ? + JR Z,SCANF2 ; ..if so, jump + INC HL ; else, point to next char + CP '*' ; is (DE) a wild card ? + JR NZ,SCANF1 ; ..if not, continue + DEC HL ; else, back up to same char + LD A,'?' ; ..and expand with '?' + +SCANF1: LD (DE),A + CP '?' ; is it wild ? + JR NZ,SCNOQ ; ..if not, jump + PUSH HL ; else, save HL + LD HL,PEXIT ; point to count storage + INC (HL) ; ..and increment + POP HL ; restore HL +SCNOQ: DJNZ SCANF0 ; ..loop till done + INC DE ; then advance to next FCB char + + ; flush to next delimiter +SCANF3: CALL DELIM + JR Z,SCANFX ; ..if delimiter found, then jump + INC HL ; point to next char + JR SCANF3 ; and loop + + ; preserve present char, and fill remaining chars in field w/ spaces +SCANF2: PUSH AF ; save char +SCANFA: LD A,' ' ; store this char + LD (DE),A ; ..in FCB field + INC DE ; point to next + DJNZ SCANFA ; loop till done + POP AF ; restore char +SCANFX: POP DE ; restore FCB address + RET ; ..and exit + + + ; capitalize char, then fall through to check for delimiter +DELIM: LD A,(HL) ; get char + CP 'a' ; less than small letter A ? + JR C,SDELM + CP 'z'+1 ; between small A and small Z ? + JR NC,SDELM + AND 5FH ; remove bit 5 to capitalize + + ; check for delimiter + ; in: HL= ptr to char + ; out: A= addressed char + ; Zero Flag set (Z) if delimiter, end-of-line or cmd separator + ; Zero Flag cleard (NZ) if char is not a delimiter +SDELM: CP '_' ; is it an Underscore ? + RET Z + CP '.' ; a Period ? + RET Z + CP ',' ; a Comma ? + RET Z + CP '>' ; greater than a Greater Sign ? + RET NC ; ..if so, return + CP ':' ; is it any of : ; < = > ? + JR NC,SDEL0 ; ..if so, jump to set status + CP ' ' ; is it less than a Space ? + RET NC ; ..if so, return (Space has zero set) + XOR A ; else, must be less than Space, + RET ; so return with zero in A +SDEL0: CP A ; set Z-Flag retaining char + RET + + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: Time and Date Routines + + + ;-------------------------------------------------- + ; fn # 98 Get time + ; enter: DE= Address to Put Time, exit: A= Time/Date Code + ;-------------------------------------------------- +CMD98A: EX DE,HL ; entry point for cmnd12 + +CMD98: LD C,0 ; set parameter to get time/date + DEFB 21H ; ..and fall through to GSTD (trashing HL) + + + ;-------------------------------------------------- + ; fn # 99 Set time + ; enter: DE= Address of Time, exit: A= Time/Date Code + ;-------------------------------------------------- +CMD99: LD C,1 ; set parameter to set time/date +GSTD: LD HL,(GSTIME) ; get time/date get/set routine address + PUSH HL ; ..to stack for pseudo 'Jump' +DOTDER: OR 0FFH ; save 1 T state while setting flags + RET ; vector to service routine + + + ;-------------------------------------------------- + ; fn # 103 Set file stamp + ; enter: DE= Address of FCB, exit: A= Time/Date Code + ; Stamp in DMA Buffer + ;-------------------------------------------------- + ; wildcards allowed in FCB + ; ##### ZSDOS-GP.Z80 (v1) refers to "10 byte stamp from DMA" ?? +CMD103: LD HL,(DMA) ; address DMA buffer + LD DE,ZSSTMP ; time stamp buffer + CALL STPCP0 ; ..and copy + + + ;-------------------------------------------------- + ; fn # 102 Get file stamp + ; enter: DE= Address of FCB, exit: A= Time/Date Code + ; Stamp in DMA Buffer + ;-------------------------------------------------- + ; wildcards allowed in FCB +CMD102: CALL SELDRV ; select Drive in FCB + ; (also switches System bank) + JP CMD103B ; copy stamp (..in Banked code) + + + + ;_______________________// Banked // + COMMON /BANK2/ + + ; ZSDOS2 supports DateStamper and P2DOS (CP/M+) file stamping. + ; Internally, the Universal T&D format is used, and converted + ; as needed when reading from / writing to disk. Similarly, + ; all stamps are converted to/from the Universal stamp format + ; (15 bytes packed BCD), and stuffed into ZSSTMP buffer. + + ;----- + ; Universal Stamp format + ; Bytes 0..4 Create 5..9 Access 10..14 Modify + ; | YY MM DD HH MM | YY MM DD HH MM | YY MM DD HH MM | + ; + ; YY MM DD HH MM SS - Universal T&D format + ; (all BCD, prefix 19 assumed for years 79-99, else 20) + + ;----- + ; P2DOS (CP/M+) Stamp format + ; Bytes 0..3 Create 4..7 Modify + ; | nn nn HH MM | nn nn HH MM | + ; + ; nnnn HH MM SS - P2DOS (CP/M+) format + ; (nnnn = binary number of das since 1 Jan 1978) + ; (HH MM SS = time in BCD) + + + ;-------------------------------------------------- + ; Get/Set file stamp + ; (continue from CMD102/CMD103) + ;-------------------------------------------------- +CMD102B: +CMD103B: CALL SRCT15 ; find the FCB + JP Z,DOTDER ; ..if not found, exit w/ error + LD HL,GETSTR ; address of get time stamp routine + LD A,(FUNCT) ; check function + CP 102 ; get stamp ? + JR Z,DOTDR3 ; ..if yes, jump + LD HL,PUTSTR ; address of put (set) time stamp routine + JR STAMPT ; mask for enabled stamp type(s) in B +STPMSK: LD A,(STFLAG) ; get time stamp flags + AND B ; mask + RET Z ; ..if not selected, then return + + ; enter here for stamp Create/Access/Modify +STAMPT: PUSH HL + CALL CHKRO1 ; test for disk W/P but avoid error trap + POP HL + JP Z,DOTDER ; no stamp if disk is W/P +DOTDR3: CALL GETDME ; get data module and extent number + JP NZ,DOTDER ; ..if not extent 0 of module 0, then quit + JP (HL) ; else, continue in GETSTR/PUTSTR routine + + + ;----- + ; Stamp Create +STCR: CALL P2CR ; call P2D Create routine + LD B,0 ; offset into stamp in B + JR STT ; Stamp Update + + ;----- + ; Stamp Modify +STUP: CALL P2UP ; call P2D Update routine + LD B,10 ; offset into stamp in B + JR STT ; Stamp Access + + ;----- + ; Stamp Access +STLA: LD B,5 ; offset into stamp in B + LD A,0FFH ; set correct value to validate status + + ; update stamp +STT: LD (STATUS),A ; save first routine status + LD C,2 ; show as stamp + LD A,(SECPNT) ; get sector pointer + ADD A,3 ; point to no date attribute + LD L,A + LD H,0 + LD DE,(DIRBUF) ; get Directory buffer pointer + ADD HL,DE ; point to Dir entry + BIT 7,(HL) + LD A,(STATUS) ; get prev routine status for possible ret + RET NZ ; ..if no date attribute, return (don't update) + JR STPSV0 ; else, jump to service routine + + + ;----- + ; get/put Stamp routines +GETSTR: CALL GSTAMP ; get file stamp in Universal format + CP 1 ; test if OK + JR Z,GETST0 ; ##### not needed if following code is removed + + ; ##### CHECK unreferenced code + LD BC,0 ; flag as read + CALL STPSVC + ; ##### + +GETST0: JP STPCPY + + + + ;_______________________// Non-Banked // + CSEG + +STPCPY: CALL SELTPB ; select TPA bank + LD HL,ZSSTMP ; time stamp buffer + LD DE,(DMA) ; address DMA buffer +STPCP0: LD BC,15 ; copy 15 bytes + LDIR + RET + + + + ;_______________________// Banked // + COMMON /BANK2/ + + RET ; ##### unreferenced, will not be executed + + ; get/put Stamp routines contd. +PUTSTR: CALL PSTAMP ; put file stamp in Universal format + LD BC,1 ; flag as write + ; ..and fall through + + + ;----- + ; Stamp service routine, combined get/put + ; in: A= index to Dir entry (00H, 20H, 40H, 60H) + ; B= offset in stamp (0, 5, 10) + ; C= function (0= read, 1= write, 2= update) +STPSVC: LD (STATUS),A ; save first routine status +STPSV0: LD (RWCODE),BC ; save function code and sector offset + LD BC,(TDFVCT) ; get T/D vector + CALL GETCDM ; get mask for current Drive in HL + LD A,H + AND B + LD H,A + LD A,L + AND C + OR H ; test if Drive has T/D vector + JR Z,STPSVE ; ..if it doesn't, jump error + + CALL DMADIR ; set DMA address to Directory buffer + LD BC,(RECDIR) ; get current Directory record + XOR A + SRL B ; calculate buffer offset + RR C ; divide record by two, lsb to carry + RRA ; place in msb of A + LD HL,SECPNT ; get sector pointer + ADD A,(HL) ; get offset to stamp in buffer + RRA ; divide by 2 (8 stamps/rec) + PUSH AF ; save index for later + PUSH BC ; ..and save relative record number + + ; now calculate record number needed + LD HL,(NDIR0) ; first entry ALV buffer + LD DE,(NMASK) ; mask number of blocks + INC E ; now is number of records per block + XOR A ; clear A (cheap zero) + LD D,A ; ..to D for 16-bit math + LD B,16 ; check all bits +STPSV1: ADD HL,HL ; shift MSB into Carry + JR NC,STPSV2 ; ..if bit was zero, then jump + EX (SP),HL ; else, get relative record + ADD HL,DE ; add records for this directory block + EX (SP),HL ; back to top-of-stack +STPSV2: DJNZ STPSV1 ; loop until done + POP DE ; has actual record number now + + CALL STDIR1 ; set track/sector and read + CALL READ + POP DE ; get index (was in A before) + AND A ; test if read ok + JR NZ,STPSVE ; ..if error, jump + CALL CKS127 ; checksum first 127 bytes + CP (HL) ; test against DS's checksum + JR NZ,STPSVE ; ..if error, jump exit + LD BC,15 ; size of Universal Stamp + LD E,D ; index in E + LD D,B ; D= 0 + LD HL,(DIRBUF) + ADD HL,DE ; now pointing to correct stamp + LD DE,ZSSTMP ; time stamp buffer + LD A,(RWCODE) ; get Read/Write code + AND A ; is it Get stamp ? + JR NZ,PUTSTP ; ..if not, we're supposed to write + LDIR ; copy bytes + JR STPSVX ; ..and exit + + + ;----- + ; copy Stamp from User DMA to local buffer +PUTSTP: SUB 2 ; is this a simple put + JR Z,UPSTMP ; ..if not, read the clock + EX DE,HL ; swap pointers +PUTS1: LDIR ; move new stamp into place + CALL CKS127 ; checksum first 127 bytes of local buffer + LD (HL),A ; ..and save checksum in last byte of record + INC C ; flag as non-deferred (0 from ldir -> 01) + CALL WRITE ; write sector to disk + AND A ; test if error + JR NZ,STPSVE +STPSVX: LD A,1 ; indicate all is well (OL status) + DEFB 01H ; ..fall through the LD A,FF with LD BC,FF3E + + ; return error status +STPSVE: LD A,0FFH ; set status + PUSH AF ; save return code + CALL STDMA ; set DMA + POP AF ; restore return code + CP 1 ; is it OK ? + RET Z ; ..if so, return + LD A,(STATUS) ; else, get first routine status + RET ; ..and return + + + ;----- + ; read Clock, place in proper Stamp field +UPSTMP: LD D,A ; reg A= 0 + LD A,(STOFF) ; get offset in stamp + LD E,A ; make word length in DE + ADD HL,DE ; pointer to target address + PUSH HL ; save it + OR A ; is it Create time ? + LD B,15 ; prepare to clear 15 bytes + CALL Z,CLRMEM ; ..if Create, then zero entire stamp entry + LD DE,ZSDOSS ; point to Time and Date buffer + PUSH DE + CALL CMD98 ; call fn 98 to read clock + POP HL ; get buffer start + POP DE ; get stamp target address + DEC A ; was the clock read OK ? + JR NZ,STPSVE ; ..if not, jump error exit + LD BC,5 ; else, move 5 bytes + JR PUTS1 ; ..and finish up + + + ;----- + ; update Create/Modify field in T&D buffer +P2CR: LD E,0 ; set to Create field in stamp + DEFB 21H ; trash HL and fall through + +P2UP: LD E,4 ; set to Modify field in stamp + CALL SETREC ; calculate offset in stamp + LD C,E ; move offset to C (B= 0) + ADD HL,BC ; destination now in HL + LD DE,ZSDOSS ; set address to read time + PUSH HL ; save destination address + PUSH DE ; ..and source address + CALL CMD98 ; call fn 98 to get time + POP DE ; restore addresses + POP HL + DEC A ; was the clock read OK ? + JR NZ,NOTIM0 ; ..if not, jump error exit + + ; ##### move label/target PSTMP1 up by one instruction + ; this CALL U2PTIM could be saved (3 bytes) + CALL U2PTIM ; else, convert DE= U-time -> HL= P-time + JR PSTMP1 ; jump to write FCB + + + ;----- + ; Put File Stamp in Universal format + ; convert Create and Modify time fields from Universal T&D format + ; to P2DOS (CP/M+) form and insert in Directory buffer, call WRFCB + ; routine to write on exit + ; in: A= index to Dir entry (00H, 20H, 40H) + ; out: A= time/date code +PSTAMP: CALL SETREC ; calculate the Stamp area address for file + LD DE,ZSSTMP ; time stamp buffer + CALL U2PTIM ; convert Create (DE= U-time -> HL= P-time) + JR NZ,NOTIM0 ; ..if invalid date, jump error exit + INC DE ; bypass Last Access field of input + INC DE + INC DE + INC DE + INC DE + CALL U2PTIM ; convert Modify field +PSTMP1: JR NZ,NOTIM0 ; ..if invalid date, jump error exit + CALL WRFCB ; write stamp +OKRET: LD A,1 ; set status ok and return + RET + +NOSTD: POP AF ; remove return address from Stack +NOTIM0: OR 0FFH ; set error flags + RET ; back to caller + + + ;----- + ; Get File Stamp in Universal format + ; read Create and Modify stamps and convert to Universal T&D format, + ; null the Access time field + ; in: A= index to Dir entry (00H, 20H, 40H) + ; out: A= time/date code +GSTAMP: CALL SETREC ; calculate source Stamp address in HL + LD DE,ZSSTMP ; time stamp buffer + CALL P2UTIM ; convert Create (HL= P-time -> DE= U-time) + LD B,5 ; zero Last Access field for this type + XOR A ; clear A +GSLOOP: LD (DE),A ; ..and poke a zero + INC DE + DJNZ GSLOOP ; ..in each location + CALL P2UTIM ; convert Modify field + JR OKRET ; ..jump to return OK status + + + ;----- + ; convert Universal T&D to P2DOS (CP/M+) form + ; in: DE= ptr to Universal T&D string + ; HL= ptr to destination buffer for P2DOS (CP/M+) T&D + ; out: A= 0, Zero Flag set (Z), if conversion OK + ; A= 0FFH, Zero Flag clear (NZ), error (dest nulled) + ; DE= ptr to Seconds byte in Universal T&D (not moved) + ; HL= ptr to Seconds byte in P2DOS (CP/M+) T&D (not filled) +U2PTIM: PUSH HL ; save destination address + LD A,(DE) ; get BCD year + LD B,A ; ..to B + INC DE ; advance to month + LD A,(DE) ; get BCD month + OR B ; is it invalid (YY = MM = 0) ? + JR Z,NODATE ; ..if invalid stamp, jump to error exit + LD A,B ; get BCD year again from B + CALL BCDBIN ; convert year to binary + CP 78 ; is it 20th century ? + JR NC,YR19 ; ..if so, jump + ADD A,100 ; else, make it 21st century +YR19: LD BC,1900 ; set base century + ADD A,C ; add current year to base + LD C,A + LD A,0 + ADC A,B + LD B,A + LD A,(DE) ; get BCD month + INC DE + CALL BCDBIN ; ..convert to binary + LD H,A + LD A,(DE) ; get day + INC DE ; point to U-hours + PUSH DE ; ..and save address on stack + CALL BCDBIN ; convert day to Binary + LD L,A ; day to L (Binary) + + ; check validity of day, month year (CHKDAT from DATE.ASM) + ; L= binary day, H= binary month, BC= binary year (1978..2077) + LD A,H ; month + DEC A ; convert to 0-11 range + CP 12 ; is it a valid month ? + JR NC,BADDAT ; ..if invalid, then jump error + PUSH HL ; save day/month + LD E,A ; month-1 in E + LD D,0 + LD HL,DMTABLE ; set lookup table for months + ADD HL,DE + LD D,(HL) ; get days in this month + POP HL ; restore day/month + CP 2-1 ; is this February ? + CALL Z,LEAPYR ; ..if so, check for leap year + JR NZ,CHKDT0 ; else, jump + INC D ; make 29 days +CHKDT0: LD A,L ; check for day within range + DEC A ; have day > 0, check for <= max. days + CP D + JR NC,BADDAT ; ..anything else is error + + ; calculate 16-bit binary date since 1978 in days, works til 2157 + PUSH HL ; save month (H) and day (L) + LD H,0 ; null out month, leaving just days + EX DE,HL ; ..move to DE + LD L,C ; year in HL + LD H,B + LD BC,1978 ; start with base year in BC +DAYS0: OR A + SBC HL,BC ; is this the starting year ? + ADD HL,BC + JR Z,DAYS1 ; ..if so, jump + PUSH HL + LD HL,365 ; add days in non-leap year + ADD HL,DE ; ..to total days count in DE + EX DE,HL ; ..and put new days total in DE + POP HL + CALL LEAPYR ; is this a leap year ? + INC BC ; advance to next year + JR NZ,DAYS0 ; ..if not leap year, then loop + INC DE ; else, add a day + JR DAYS0 ; ..then loop + + + ; error routines, destination P2DOS field nulled +NODATE: INC DE ; advance source ptr for same routine + INC DE + DEFB 3EH ; ..fall through to 2nd POP with LD A,0D1H +BADDAT: POP DE ; restore Universal T&D string (-> hours) + POP HL ; restore destination addr for P2DOS date +BADDA1: CALL CLRM4 ; fill with 4 nulls + INC DE ; ..advance ptr to exit position + INC DE + DEC A ; set error flags (A= 0FFH, Zero clear (NZ)) + RET + + + ; DE= total days (year + day), BC= binary year, (Stack)= month and day + ; first day 0001H : Su 01 Jan 1978 + ; last day 8EADH : Fr 31 Dec 2077 + ; real last day FFFFH : Su 05 Jun 2157 +DAYS1: POP HL ; restore month and day + EX DE,HL ; date to HL, month/day to DE + PUSH HL ; ..and save binary date + LD HL,DMTABLE ; address days-of-month table + LD E,1 +DAYS2: LD A,D ; check for matching month + CP E + JR Z,DAYS4 ; ..exit when match + LD A,(HL) ; get days in this month + EX (SP),HL ; put table on stack, binary date to HL + ADD A,L ; add month's days to cum binary date + LD L,A + LD A,0 + ADC A,H + LD H,A + LD A,E ; check this month + CP 2 ; is it February ? + CALL Z,LEAPYR ; ..if so, check if leap year + JR NZ,DAYS3A ; jump if not Feb and/or leap year + INC HL ; else, bump cum binary date by 29 Feb +DAYS3A: EX (SP),HL ; put cum binary date to stack + ; ..and days-of-month table to HL + INC HL ; point to next month + INC E ; bump index counter + JR DAYS2 ; ..and loop + +DAYS4: POP BC ; exit here, put cum binary date to BC + POP DE ; restore Universal T&D string (-> Hrs) + POP HL ; ..and destination address + LD (HL),C ; put binary date in string + INC HL + LD (HL),B +MOVHM: INC HL + EX DE,HL ; swap src/dest pointers + LDI ; move BCD hours + LDI ; ..and BCD minutes + EX DE,HL ; restore pointers into correct regs for exit + XOR A ; set OK flags + RET ; and return + + + ;----- + ; calculate leap year correction + ; in: BC= year (binary, leap years = xxxxxx00B) + ; out: Zero Flag set (Z) = correction necessary, reset (NZ) = no corr +LEAPYR: BIT 0,C ; get lower part of date + RET NZ ; ..if not leap year, return + BIT 1,C ; test other bit + RET ; ..and return + + + ;----- + ; convert BCD to Binary + ; in: A= BCD digit + ; out: A= binary number +BCDBIN: OR A ; test if zero + RET Z ; ..if so, return (it's the same) + PUSH BC ; save register + LD B,0 ; set counter +BCDBI0: INC B ; bump counter + SUB 1 ; count down BCD + DAA + JR NZ,BCDBI0 ; ..till all gone + LD A,B + POP BC + RET + + + ;---- + ; convert Binary to BCD + ; in: A= byte to be converted + ; out: A= two packed BCD digits + ; Convert byte in A register to two packed BCD digits +BINBCD: PUSH BC ; save register + LD B,0FFH ; preset counter +BINBCL: INC B ; bump counter output + SUB 10 + JR NC,BINBCL ; loop bumping counter till no more 10's + ADD A,10 ; ..correct for underflow + LD C,A ; save low nybble here for a while + LD A,B ; ..and bring high nybble in A + ADD A,A ; move it into position + ADD A,A + ADD A,A + ADD A,A + ADD A,C ; add in low nybble + POP BC ; restore regs + RET + + + ;----- + ; convert P2DOS (CP/M+) form to Universal T&D string + ; in: HL= ptr to P2DOS (CP/M+) T&D + ; DE= ptr to destination buffer for Universal T&D + ; out: A= 0, Zero Flag set (Z), if conversion OK + ; A= 0FFH, Zero Flag clear (NZ), error (dest nulled) + ; HL= ptr to Seconds byte in P2DOS (CP/M+) T&D (not moved) + ; DE= ptr to Seconds byte in Universal T&D (not filled) +P2UTIM: PUSH DE ; save destination addr + LD E,(HL) ; get binary date to DE + INC HL + LD D,(HL) + INC HL + EX DE,HL ; put binary day/date in HL, P2D ptr in DE + LD A,H ; check for valid entry + OR L ; is date present ? + JR NZ,P2UTI0 ; ..if not null, then jump + POP HL ; get destination addr back + LD B,5 + CALL BADDA1 ; ..and null the U-time field + EX DE,HL ; put pointers in correct regs + RET ; ..and return to caller + +P2UTI0: PUSH DE ; save P2D pointer (-> Min) + LD BC,1978 ; beginning year +DMJ0: LD DE,365 ; set days in normal year + CALL LEAPYR ; check for leap year + JR NZ,DMJ1 ; ..if not leap year, then jump + INC DE ; else, add one day +DMJ1: OR A ; when # of days left.. + SBC HL,DE ; ..is less than days in year.. + JR C,DMJ2 ; ..year is in HL, so exit + JR Z,DMJ2 ; ..or if last day of year + INC BC ; bump starting year + JR DMJ0 ; ..and back for another try + + ; BC= binary year, HL= remaining days +DMJ2: ADD HL,DE ; compensate for underflow + LD A,1 ; start with month 1 (Jan) + LD D,0 ; prepare for 16-bit math + PUSH HL ; save days remaining + LD HL,DMTABLE ; address days-of-month table +DMJ3: LD E,(HL) ; get days in current month to E + CP 2 ; is it February ? + CALL Z,LEAPYR ; ..if so, check for leap year + JR NZ,DMJ4 ; ..if not leap year, then jump + INC E ; else, make 29 days +DMJ4: EX (SP),HL ; swap ptr (HL) with days remaining (Stack) + OR A + SBC HL,DE ; subtract days in month from remaining days + JR C,DMJ5 ; ..if we've gone too far, then exit + JR Z,DMJ5 ; ..or just far enough (last day of month) + EX (SP),HL ; swap back + INC HL ; point to next month in table + INC A ; bump month counter + JR DMJ3 ; ..and try again + + ; arrive here with binary year on Stack, relative month in A (Jan = 1), + ; days in that month in E, and binary year in BC +DMJ5: ADD HL,DE ; compensate for underflow + EX (SP),HL ; ..and put back on Stack + POP HL ; restore day in L + CALL BINBCD ; convert month (in A) to BCD + LD H,B ; ..moving year to HL + LD B,A + LD A,L ; convert day + LD L,C + CALL BINBCD ; ..to BCD + LD C,A + LD DE,100 ; subtract centuries, one by one.. +DMJ7A: OR A + SBC HL,DE + JR NC,DMJ7A ; ..until we go too far + ADD HL,DE ; then correct for underflow + LD A,L ; get year (tens and ones) + CALL BINBCD ; ..to BCD + POP DE ; restore P2D pointer (-> Min) + POP HL ; get Universal T&D string address + LD (HL),A ; store years + INC HL + LD (HL),B ; ..months + INC HL + LD (HL),C ; ..days + CALL MOVHM ; store hours and minutes, and set flags + EX DE,HL ; put U-time exit address in DE + RET ; ..and finish up elsewhere + + + ;------ + ; calculate offset within T&D entry, if one exists + ; out: HL= ptr to first byte of Create field +SETREC: LD HL,(DIRBUF) + LD BC,60H ; offset to Time and Date fields + ADD HL,BC + LD A,(HL) ; get byte + SUB 21H ; is TimeStamping present + JP NZ,NOSTD ; ..if not, quit here + + LD A,(SECPNT) ; get sector pointer + RRCA ; shift 2 times + RRCA + LD C,A ; save temporarily + RRCA ; shift 2 more times + RRCA + ADD A,C ; ..and add in again + LD C,A ; set for offset (C= 0, 10, 20) + ADD HL,BC ; add offset + INC HL ; ..and bump to Create Time start + XOR A ; set return status OK + RET + + ; day-of-month table +DMTABLE: DEFB 31,28,31,30,31,30,31,31,30,31,30,31 + + + + ;_______________________// Non-Banked // + CSEG + + ;----- + ; JP (HL) with bank context switching +JUMPHL: CALL RETMEM ; get current mem bank (BIOS fn #39 RETMEM) + LD (CURBNK),A ; save it + CALL SELTPB ; select TPA bank + CALL JPHL ; do the actual JP (HL) + LD A,(CURBNK) ; get bank # back + JP SELMEM ; select mem bank again (BIOS fn #27 SELMEM) + ; ..and let return from there +JPHL: JP (HL) + +CURBNK: DEFS 1 + + + + ;_______________________// Non-Banked // + CSEG ; technically not needed + ; but necessary to assemble identical REL file + + ;:::::::::::::::::::::::::::::::::::::::: + ;::::: Memory Bank Switching Routines + + ; bring SYSBNK into context (Banked mode) +SELSYB: PUSH AF + LD A,(OSYSBK) ; B/P Bios base +0x83 (offset SYSBNK) + JR SELBNK ; switch bank + + ; bring TPABNK into context (Non-banked mode) +SELTPB: PUSH AF + LD A,(TPABNK) ; get TPA bank number + ; ..and fall through + + ; select memory bank +SELBNK: CALL SELMEM ; BIOS fn #27 SELMEM (A= bank #) + POP AF + RET + + +;::::: DATA AREA (in CSEG) + +PATHAD: DEFB 1,0 ; Internal path - Drive A, User 0 + DEFB 0,0 ; blank entry + DEFB 0,0 ; blank entry + DEFB 0 ; ..and ending null + + ;----- + +TDFVCT: DEFW 0 ; time and date vector + + ;----- + +LOGIN: DEFW 0 ; Login vector +DSKWP: DEFW 0 ; Disk write protect vector +HDLOG: DEFW 0 ; Fixed disk login vector + + + END + + +;************************************************************************ +; Remarks jxl: +; When assembled as M-REL, this source file produces an _exact_ copy +; of ZS227G.ZRL included in available B/P Bios package(s). +; Compared to v1 (ZSDOS-GP.Z80) many code portions are unaltered, or +; show only slight modifications. Major changes result from banking and +; addition of universal T&D stamp routines, supporting DateStamper +; as well as P2DOS (CP/M+) stamps. +; Besides basic functionality (e.g. error handling), all I/O routines +; are located in non-banked memory. Many Disk routines begin in non-banked +; memory with just a small footprint, and are continued in banked memory. +; This is also the case for T&D stamp routines. With the exception of +; 4 bytes stored in /B2RAM/, all data bytes are located in non-banked +; CSEG code segment. +; +; A comment on function 152 Parse FileSpec: ZCPR 4.1 (Z41.ZRL) relies +; on that function. Thus, it cannot be removed. Even though most probably +; no other application might use it. Currently, the entire function is +; located in non-banked memory. A considerable amount of space could be +; reclaimed by moving this function (or parts of it) to banked memory. +; +; Possible optimisations noticed during disassembly are marked with +; "#####" in the comment. Speaking of which - non-banked and banked parts +; need to be sector-aligned, ie. BPBUILD fills the remainder of the last +; 128-byte block with zeros. In its current state, the non-banked part +; leaves 71 bytes unused. Or, in other words, a block could be saved +; if 57 bytes could be eliminated and/or moved to banked code section. +;************************************************************************ diff --git a/Source/ver.inc b/Source/ver.inc index b03e2f39..4508e6f8 100644 --- a/Source/ver.inc +++ b/Source/ver.inc @@ -2,7 +2,7 @@ #DEFINE RMN 6 #DEFINE RUP 0 #DEFINE RTP 0 -#DEFINE BIOSVER "3.6.0-dev.0" +#DEFINE BIOSVER "3.6.0-dev.14" #define rmj RMJ #define rmn RMN #define rup RUP diff --git a/Source/ver.lib b/Source/ver.lib index 8ea05b52..c0841e56 100644 --- a/Source/ver.lib +++ b/Source/ver.lib @@ -3,5 +3,5 @@ rmn equ 6 rup equ 0 rtp equ 0 biosver macro - db "3.6.0-dev.0" + db "3.6.0-dev.14" endm diff --git a/Tools/cpm/bin80/LOAD.COM b/Tools/cpm/bin80/LOAD.COM new file mode 100644 index 00000000..b9601e00 Binary files /dev/null and b/Tools/cpm/bin80/LOAD.COM differ diff --git a/Tools/cpm/lib80/DSLIB.REL b/Tools/cpm/lib80/DSLIB.REL new file mode 100644 index 00000000..9fc51506 Binary files /dev/null and b/Tools/cpm/lib80/DSLIB.REL differ diff --git a/Tools/cpm/lib80/DSLIBS.REL b/Tools/cpm/lib80/DSLIBS.REL new file mode 100644 index 00000000..c1ad9618 Binary files /dev/null and b/Tools/cpm/lib80/DSLIBS.REL differ diff --git a/Tools/cpm/lib80/LIBS45.NOT b/Tools/cpm/lib80/LIBS45.NOT new file mode 100644 index 00000000..55ea363f --- /dev/null +++ b/Tools/cpm/lib80/LIBS45.NOT @@ -0,0 +1,7 @@ + 11 October 1993 +This library contains the REL versions of SYSLIB, Z3LIB, VLIB, and DSLIB +in both Microsoft REL and SLR REL form. The names have an "S" appended +to signify the libraries in SLR form. All libraries are of the 4.5 +release level. + Harold F. Bower + \ No newline at end of file diff --git a/Tools/cpm/lib80/SLINK0.REL b/Tools/cpm/lib80/SLINK0.REL new file mode 100644 index 00000000..acbc8358 Binary files /dev/null and b/Tools/cpm/lib80/SLINK0.REL differ diff --git a/Tools/cpm/lib80/SYSLIB.REL b/Tools/cpm/lib80/SYSLIB.REL new file mode 100644 index 00000000..23a57a4a Binary files /dev/null and b/Tools/cpm/lib80/SYSLIB.REL differ diff --git a/Tools/cpm/lib80/SYSLIBS.REL b/Tools/cpm/lib80/SYSLIBS.REL new file mode 100644 index 00000000..6659ff64 Binary files /dev/null and b/Tools/cpm/lib80/SYSLIBS.REL differ diff --git a/Tools/cpm/lib80/VLIB.REL b/Tools/cpm/lib80/VLIB.REL new file mode 100644 index 00000000..8b9c5c91 Binary files /dev/null and b/Tools/cpm/lib80/VLIB.REL differ diff --git a/Tools/cpm/lib80/VLIBS.REL b/Tools/cpm/lib80/VLIBS.REL new file mode 100644 index 00000000..a2af0edd Binary files /dev/null and b/Tools/cpm/lib80/VLIBS.REL differ diff --git a/Tools/cpm/lib80/Z3LIB.REL b/Tools/cpm/lib80/Z3LIB.REL new file mode 100644 index 00000000..cb7e0b35 Binary files /dev/null and b/Tools/cpm/lib80/Z3LIB.REL differ diff --git a/Tools/cpm/lib80/Z3LIBS.REL b/Tools/cpm/lib80/Z3LIBS.REL new file mode 100644 index 00000000..a5394582 Binary files /dev/null and b/Tools/cpm/lib80/Z3LIBS.REL differ