OVERVIEW of the ROM V3.0 by Andy Wright
Total Page:16
File Type:pdf, Size:1020Kb
OVERVIEW OF THE ROM v3.0 by Andy Wright NOTES ON THE ROM SOURCE LISTING This disk contains the complete ROM 3.0 source code. Source code is the text that an assembler program reads and converts into machine code, ready to go into a ROM hip. The files on the disk are in a slightly different form than normal source files. They were made by re-directing the output that the assembler would have sent to a printer during assembly to a disk file instead. This gives addresses in the left-hand column, followed by the values at those addresses (both in hexadecimal) followed by the actual source file text. So, for example, near the start of the lower ROM you will see: 0016 C5 BCJUMP: PUSH BC ;16 The first number gives the address in the ROM, and the second number is the value there, so that PRINT HEX$(PEEK &0016) gives C5. BCJUMP is a Label that is used to referto this bit ofthe ROM in other parts ofthe source listing. PUSH BC is the Assembly Language text that caused the Assembler to generate the C5 machine code equivalent. A semi-colon precedes any REMs by the author - here I just put a 16 to remind myselfas I wrote the source (without the benefit ofthe left-handtwo columns) where things would be in memory. This doesn't usually matter very much, but the first part ofa ROM used by a Z80 proces- sor is a special case - see the section on RESTARTS below. You will find the Technical Manual (available via FORMAT) useful for a full understanding ofinteractions with the hardware. The text ofthe ROM source has been leftjust as I wrote it. Some parts are not terribly well documented, since I was writing to explain things to myselfrather than an audience. The symbols used may not correspond exactly to the Technical Manual's usage - for example, I started using URPORT and LRPORT (for Upper RAM Port and Lower RAM Port) before Bruce Gordon told me he was using HMPR and LMPR for the same things! Also, to the hardware, the screen MODEs are 0-3, not 1-4, and I think I may have used MODE inconsistently. Some sections have been "commented out" by inserting semicolons; for example, a table of EQUs that allowed me to write e.g. CP BORDERTOK instead ofCP 9EH had to be cut when the assembler ran out ofsymbol space! At one point I changed assemblers, and the new one didn't allow e.g. LD A,'K'. I did a search and change ofall single quotes to double quotes; this accounts for the occasional appearance in the text of CAN"T and A" rather than CAN'T and A'. You may think the code is oddly arranged, or contains odd things like DB 0DDH used to jump three bytes. This is because space was very tight, and any trick that saved a byte was needed. This included moving routines into "illogical" positions ifthis allowed a Label to be reached by a 2-byte JR instead of a 3-byte JP instruction. A NOTE ON HEXADECIMAL NUMBERS I know some people don't like hex, but it does make life much easier if you can get used to it. For example, in the first part of the lower ROM is the line: 000A C3CE37 JP ERROR2 In any 3-byte Z80 instruction, the first byte is the code for the operation, or "op code". In this case it is C3, for JP. The next 2 bytes are a value, or address, in reverse order, so they should be read 37 and then CE. In other words, JP to 37CE hex, which you can eas- ily find in the later part ofthe lower ROM. (The Label ERROR2 is at 37CE.) A decimal version would not be as easy to use: 0010 195 206 55JP ERROR2 Besides, it takes more room and it isn't as neat. PAGING There is only one actual ROM chip in the SAM, but it is handled in two sections. The lower ROM, also called ROM0 (machine code programmers often start counting at zero!) is usually paged in at 0000 to 3FFF (0 to 16383) whereas the upper ROM, or ROM1, is paged in at C000 to FFFF (49152 to 65535) when required. The lower ROM is ALWAYS paged in unless user-loaded software initiates complex pag- ing operations. The lower ROM pages in the upper ROM as required, for example, to handle floating-point calculations, BEEP or tape operations. RAM page 0 is usually paged in at 4000-7FFF (16384-32767) and holds important sys- tem variables and the start ofthe current Basic program. The upper halfofmemory, 8000-FFFF, is used to hold the section ofRAM that is currently being worked on. The early part ofa Basic program would involve RAM page 0 being paged in at 8000 (which automatically means that page 1 follows at C000). It doesn't matter that RAM page 0 is also simultaneously paged in at 4000. As later parts ofthe Basic program are inter- preted, the start ofthe current line will occur higher and higher in memory, passing from, say, BF85 to C023. While any structure in memory, like a Basic line, starts below C000, it can be 16K long before it will "fall off" the end of the memory map. This simplifies the job ofthe ROM, since it doesn't need to keep checking, forevery byte it reads, whether the end ofthe memory map has been reached. It is sufficientifit checks, say, every line, if the start ofthe line is above C000; ifit is, the paging can be altered so that the same byte ofRAM is re-mapped 16K lower (which will be somewhere in the region 8000 to BFFF) and again we have ample room before we fall off the end of the memory map. This sys- tem can be extended with up to 32 pages ofRAM (the maximum that the ports that page internal RAM can control) allowing for very big programs indeed. The screen is paged in, starting at 8000, when it must be read from or written to. The fly in the ointment, in a way, is the upper ROM. When paged in, it covers RAM at C000-FFFF and could obscure the later part ofa Basic line or variable, or the later part of the screen. This makes it unsuitable for many kinds of routines. Floating-point calculation routines are fine, because they work on numbers in the "system page" - RAM page 0, paged in at 4000-7FFF. However, graphic routines should not be in the upper ROM because the entire screen could not be paged in at the same time. (Well, it could be paged in at 4000-BFFF, but that would mean paging out the system page, which holds important variables like the PEN colour, screen MODE, the machine stack, information for interrupts, etc.) All this means that too much code cannot be run in the upper ROM. To get round this, I had to do nasty things like copying routines from this ROM to a RAM buffer in the system page forexecution. The first part ofthe upper ROM consists ofsuch routines, and the addresses given in the left-hand column correspond to the addresses in the RAM buffer where the code is RUN, not to the actual addresses in the upper ROM where the code is STORED. The routines involved were chosen because their speed is not critical - the copying process obviously imposes a slight delay. Other routines are quite convoluted because ofthe problem with the upper ROM. The PRINT routines, forexample, start in the lower ROM, use the upper ROM where this is feasible for the interpretation of charac- ters, and then use the lower ROM again for actually putting data on the screen. SAMDOS, MasterDOS and MasterBasic all page into 4000-7FFF for execution. They page out the normal machine stack and replace it with one oftheir own. Special routines are used to read or write the (paged out) system page variables, or to Call ROM routines with the system page temporarily paged in. HOW THE BASIC INTERPRETER WORKS I do not have the time to explain this in detail, but the following rough outline may help. When the SAM is turned on, the start ofthe ROM, at 0000, is executed. This jumps to an initialisation routine in the upper ROM, which clears RAM, sets up the system variables, screen mode, rainbow start-up screen, copyright message etc. and then waits for you to press any key. It then indirectly enters the interpreter's "main loop", as it would after an error report. The main loop is at 0E84 in the lower ROM. The first action is a CALL AUTOLIST which would list the current part ofthe Basic program, ifthere was one. Afterclearing various scratch-pad areas (such as the edit line) with CALL SETMIN, the lower screen is selected for input and output with CALL STRM0. Then theEDITOR is called to get input from the user. When the user presses RETURN, the Editor hands back control, and the main loop tokenises any keywords in the input using CALL TOKMAIN. (E.g. print is turned into a single-byte internal form that is shorter and easier to handle.) The modified line is then checked for correct syntax using CALL LINESCAN. This process also inserts invisible forms of numbers in the line. The invisible form is used to speed things up during program execution. Ifthere is an error, the invisible forms are stripped out again at 0EB0, a warning BEEP is produced, and the loop is gone round again, giving the user a chance to modify the line.