Column for TCJ Issue #39 Jay Sage For this issue I will discuss some unique new capabilities made possible¨ by NZCOM that have already proved their value and that I hope will be¨ exploited to a much greater extent in the future. I originally had several¨ other issues on my agenda, but Lee A. Hart sent me such an interesting¨ article that I wanted to leave plenty of room for it. System Enhancements Using NZCOM I'm afraid that many people think of NZCOM as just a way for unskilled¨ users to get Z-System running on their computers. It's true that NZCOM¨ accomplishes that, but, as I have asserted often before, NZCOM does much¨ more than that. It offers possibilities that a manually installed Z-System¨ cannot achieve. I would like to describe one of them here and will do so¨ first in the context of a problem that arose with the new ZSDOS and ZDDOS¨ disk operating systems on some computers. Because CP/M was created originally for the 8080 microprocessor, a number¨ of BIOS implementors (the BIOS, or Basic Input/Output System, is the¨ hardware-dependent part of CP/M) felt that they could make free use of the¨ additional registers introduced with the Z80 chip. These registers included¨ two index registers, called IX and IY, and a duplicate set of the standard¨ registers denoted with primes on the names (e.g., B' or HL'). This was perhaps excusable at the time, but it is poor programming¨ practice for an operating system to change anything other than what is¨ explicitly indicated in the specifications. Most BIOS writers who have used¨ the Zilog registers have been careful to restore the original values before¨ exit from the BIOS routines. Unfortunately, a few BIOSes fail to do that. ¨ Among them are the following: Epson QX10, Zorba, Televideo 803 and TPC-1,¨ Oneac On, and the Osborne Executive. The Bondwell is on the suspect list,¨ and there are probably others we don't know about yet. The (mis)use of these registers poses no problem for programs written to¨ run on the 8080, but today we are rapidly moving beyond the limitations of¨ the 8080 and making extensive use of the Z80 registers to pack more power¨ into operating system components and application programs. Today, the Z­ System, true to its name, is intended to run only on the Z80 or upwardly¨ compatible processors like the HD64180, Z180, or Z280. Several users who purchased ZDOS (that is ZSDOS and ZDDOS) found that it¨ would not work properly on their computers. An investigation turned up the¨ fact that the BIOSes in those computers were modifying the index registers. ¨ This also explained why those same users had been experiencing strange¨ problems with JetLDR, Bridger Mitchell's superb Z-System module loader. It¨ also explained some mysterious problems I was having with a number of¨ programs (for example, EDITNDR) on my Televideo 803! The question was what¨ to do about the problem. In the ancient days, when computers always came with the source to their¨ BIOS and their owners were always intimately familiar with the procedures¨ for rebuilding their operating systems, the solution would have been to¨ rewrite the BIOS with the proper PUSH IX and POP IX instructions to preserve¨ the index register values. But what could we do today for nonprogrammers¨ and those without BIOS source code? NZCOM provided the answer quite nicely! As I explained in a column long ago, NZCOM works by creating what I call¨ a virtual BIOS (I'll call it VBIOS) lower in memory in order to open up¨ space for the Z-System modules between it and the real BIOS (often called¨ the custom BIOS or CBIOS). The source for this virtual BIOS is available. ¨ Except for the warmboot code and some minor complications for IOP¨ (input/output processor) support, the standard NZCOM VBIOS module just¨ vectors calls that come to it up to the real BIOS. But no one says this is all it is allowed to do. ZDOS authors Cam¨ Cotrill and Hal Bower found it quite easy to surround the vectors with code¨ to save and restore registers. First they released ZSNZBI11.LBR, which¨ contained the source and ZRL file (loadable by NZCOM) for a VBIOS that¨ preserved the IX and IY registers for all disk function calls. Later they¨ discovered that some of the machines changed the index registers even for¨ console I/O function calls, and others changed the alternate registers. ¨ They then wrote ZSNZBI12.LBR, whose VBIOS preserves all the registers for¨ all BIOS functions. Instead of having the virtual BIOS routines jump directly to the real¨ BIOS, they jump to an intermediate entry point. For example, the list­ status vector in the jump table has a JP ILSTST (intermediate list status),¨ and the code at ILSTST is ILSTST: LD A,45 JR DOBIOS The offset for the BIOS function is placed in the A register and then¨ control is transferred to a general BIOS-calling routine shown in Table 1¨ that implements the register protection. The routine JPHL referenced there¨ contains only the code line JP (HL), which vectors the CPU off to the BIOS¨ with a return to the DOBIOS code. ----------------------------------------------------------------------------- DOBIOS: LD HL,CBIOS ; Start with address of real BIOS ADD A,L ; Add offset in A (never a LD L,A ; ..carry since on page boundary) EXX ; Swap to alternate registers LD (HLP),HL ; Save them all in memory LD (DEP),DE LD (BCP),BC LD (IXREG),IX ; Save index registers, too LD (IYREG),IY EXX ; Back to regular registers EX AF,AF' ; Swap to alternate PSW PUSH AF ; Save it on stack EX AF,AF' ; Back to original PSW CALL JPHL ; Actually call the BIOS! EXX ; Restore alternate and index LD HL,(HLP) ; ..registers LD DE,(DEP) LD BC,(BCP) LD IX,(IXREG) EX AF,AF' ; Alternate PSW, too POP AF EX AF,AF' RET ; Register save area BCP: DEFS 2 ; BC' DEP: DEFS 2 ; DE' HLP: DEFS 2 ; HL' IXREG: DEFS 2 ; IX IYREG: DEFS 2 ; IY END Table 1. Code from ZSNZBI12.Z80 that preserves all index and alternate¨ registers across BIOS calls in NZCOM. ----------------------------------------------------------------------------- To use this replacement VBIOS, you have to run MKZCM and create an NZCOM¨ system with 4 records allocated for the BIOS instead of the standard 2. ¨ Because the BIOS must start on a page rather than just a record boundary,¨ MKZCM will sometimes make automatic adjustments to the BIOS size. ¨ Therefore, you should specify changes in MKZCM starting with the higher­ numbered modules; the adjustment in the BIOS allocation should be made last. ¨ If an attempt to enter a value of 4 results in MKZCM using 5, then you could¨ go back (if you don't like wasting memory) and make one of the other modules¨ (such as the NDR) one record larger and then respecify a 4-record BIOS. There are many other ways that NZCOM can be used to introduce system¨ enhancements without having to make changes in the real BIOS. As an¨ example, we will show how to add support for the drive vector in environment¨ descriptors of type 80H and above (implemented with NZCOM and Z3PLUS). The¨ drive vector is a 16-bit value stored as a word beginning at offset 34H in¨ the environment descriptor. It specifies which disk drives are actually¨ implemented on a system. The lowest order bit in the word is for drive A¨ and the highest for drive P. A zero in a bit position indicates that the¨ corresponding drive is not available. For example, on my SB180 the bytes at¨ addresses ENV+34H and ENV+35H were 7FH and 00H, respectively. Thus the word¨ value is 007FH or 0000,0000,0111,1111 binary, indicating that I had drives¨ A, B, C, D, E, F, and G. When the hard disk E partition developed a problem¨ that made it unusable, I changed the 7FH value to 6FH, thereby disabling¨ drive E. You can display the drive vector using menu selection 3 in the¨ SHOW program (ZSHOW for Z3PLUS). The ZCPR34 command processor knows about the drive vector and will not¨ allow command references to unsupported drives. But what about programs¨ that you run? Unfortunately, the BIOS generally knows only which drives are¨ potentially implemented, and it may try to access a nonexistent drive. When¨ 'smart' BIOSes encounter this problem, they often prompt the user as to what¨ to do next. This is fine if you are sitting at the console and can take¨ appropriate action to recover, but if the system is being run remotely,¨ there is generally no way for the remote user to recover. In fact, because¨ the 'smart' BIOS uses direct hardware calls to display the "Abort, Retry,¨ Ignore?" message rather than calls through the BIOS vector table, the remote¨ user does not even see the message and just thinks the system has crashed. ¨ My Z-Node got hung once that way when I forgot to put a diskette back into a¨ floppy drive. A caller attempted to access it, and when I got home, the¨ BIOS was dutifully beeping at me and waiting for me to tell it what to do. My first stab at writing a VBIOS that observes the drive vector¨ restrictions is shown in Table 2. Now that I have read Lee Hart's column, I¨ am sure that this code can be made shorter, faster, or both! But I will¨ leave that as an exercise for the reader. (I already see one place where I¨ could save a byte.) The listing assumes you are starting with the ZSNZBIO described earlier. ¨ Just add the extra equate for DRVEC under the /_ENV_/ common block and¨ replace the simple ISELDK (intermediate select disk) code with the slightly¨ more complex version shown in the Table. I put this on my Televideo, and¨ the results were most pleasant. Now when I attempt to access a nonexistent¨ drive, the system does not force a direct-CBIOS warmboot that drops me out¨ of NZCOM. ----------------------------------------------------------------------------- ; Add DRVEC definition in the ENV common COMMON /_ENV_/ Z3ENV: DRVEC EQU Z3ENV+34H ; Drive vector CCP EQU Z3ENV+3FH DOS EQU Z3ENV+42H ; Modify ISELDK as follows and place it after the DOBIOS code and before ; the data area for register storage. ISELDK: LD HL,(DRVEC) ; Get drive vector LD A,16 ; Subtract requested drive SUB C ; .. from 16 LD B,A ; .. and put into B ISELDK1: ADD HL,HL ; Move bits left into carry DJNZ ISELDK1 ; Loop 16- times LD HL,0 ; BIOS return code for invalid drive RET NC ; Return if drive vector bit not set LD A,27 ; Otherwise, use CBIOS function JR DOBIOS ; .. at offset 27 Table 2. Code added to virtual BIOS to support the environment drive vector¨ at the BIOS level. ----------------------------------------------------------------------------- These two examples of system enhancements by no means exhaust the¨ possibilities. One can implement all kinds of additional features and¨ drivers right in the NZCOM VBIOS. Joe Wright suggested early during NZCOM¨ development that one should create an absolutely stripped down CBIOS, one¨ that contains only the functions that are absolutely necessary to get the¨ system running and then implement all the bells and whistles in the VBIOS. ¨ These extra features would include things like RAM-disk drivers, keyboard¨ type-ahead buffers, logical drive swapping facilities, and disk error¨ recovery management routines. With this strategy, one can actually achieve¨ a larger TPA with an NZCOM system than one had under the standard CP/M¨ system, since the CBIOS can be made smaller and the fancy features dropped¨ when a larger TPA is more important. For example, the "Abort, Retry, Ignore" message should be implemented in¨ the VBIOS, with the CBIOS returning from disk errors with standard error¨ codes. With the normal VBIOS, the error will simply be passed back to the¨ DOS, which will report the error in its usual way ("BDOS ERROR on..." in the¨ case of the Digital Research BDOS). A more elaborate VBIOS can detect the¨ error, report it to the user, and allow the operation to be retried. When¨ the system is running in remote mode, either the simpler VBIOS can be used¨ or the prompt can be vectored properly through the jump table so that the¨ remote user will be able to deal with the problem. Similarly, one should be able to handle the swapping of logical drive¨ names in the VBIOS. There are a couple of pitfalls to watch out for,¨ however. If you change logical names, you better make sure that the disk¨ system is reset, probably both before and after the swap. You also better¨ make sure that NZCOM can still find its CCP file, which is normally kept in¨ directory A15:. If you swap the A drive without providing a copy of this¨ CCP in the new A drive, you'll be in serious trouble. Of course, the¨ swapping would be handled by a utility program, and it would worry about¨ these requirements. The VBIOS would simply have the code for translating¨ references to a logical drive value in register C into a possibly different¨ physical drive value. I hope that this short discussion has given some of you ideas for¨ imaginative applications of the new capability offered by the NZCOM virtual¨ BIOS. If so, I would love to hear about them and to see sample code.