The ZX81 High Res Core Routine - As used by Rock Crush and Dans Revenge ----------------------------------------------------------------------- Introduction ------------ As a lot of people have been asking me recently, as to how the high res routines actually work, in response, I have decided to detail and release the following Z80 code: (Revision 3.0R - Steven McDonald - July, 1997) Technical Notes: ---------------- A call to HI-RES will start generating a high res display. The HRESGEN routine address is loaded into the IX register and will take over the display output - 50 times a second (UK). A further call to LO-RES will start to generate the normal lo res display again. The Z80 "I" register normally holds the start of the ZX81 character table / 256 (i.e. 30 * 256 = 7680). As nearly all of the ROM characters have a blank line at the top, the high res routine changes this to 12 which is at ROM address 3072 which I found contains much more interesting bit-patterns than other values which can be used. Due to hardware limitations, the "I" register can ONLY point into the ROM - and not RAM (hence the reason for only pseudo high res - sigh!). The high res routine works by fooling the ULA into thinking it is only on the top line of a character - every time! It cleverly does this by resetting and restarting the ULA ROW counter at every VSYNC pulse with the "IN A,(C)" and "OUT (FF),A" code sequence. This allows the same row of patterns to be used for every one of the 192 tv lines. As this procedure is carried out for every tv line, true high res is achieved vertically - but not horizontally, as this depends on the limited bit patterns stored at the location pointed to by: (the "I" register * 256 + 8 * the value of the "character" stored in the display buffer) Phew! This high res display buffer is stored at (E71E+0021) - 8000 i.e. at address 673F - in this example routine. It consists of 32 decimal display characters or "patterns", followed by a 201 decimal byte which just happens to be the Z80 "RET" opcode. These "patterns" can only be in the range (0 - 63) i.e. BIT 6 must be zero. BIT 7 is used to invert the video signal before it is ouput to the screen via the ULA shift register. This is repeated 192 decimal times for the complete high res display buffer! In lo res, each line ends with a 118 decimal byte - which is the Z80 opcode, "HALT" - which conveniently waits for the next interrupt! Basically, any byte with BIT 6 set stored in the display buffer, tells the ULA to stop outputting tv data and execute that instruction. As it happens "RET" also has BIT 6 set so is executed, thus cleverly returning control to the high res display routine! These routines work on a real 16K ZX81 and provide pseudo high res displays. The ZX81 emulator, "XTENDER" also follows what is going on, by trapping an immediate change of value to the IX register pair and kicking in its own high res screen handler to generate the correct picture. Therefore, under the emulator, this high res routine is not actually executed as such - just cleverly emulated! "XTENDER" first tries to emulate the pseudo high res by looking for the characteristically shaped 6k display buffer in the bottom 16k of RAM and outputting it to the PC screen appropriately. If it cannot locate this display buffer, normal resolution will be switched back in again. The Routines ------------ HI-RES: HALT ; Wait for an interrupt - used to sync the changeover! LD A,(FRAMES) ; Wait LD C,A ; for the SYNC1: LD A,(FRAMES) ; next CP C ; new JR Z SYNC1 ; tv frame - used to sync the changeover! LD A,0C ; Change the value of the "I" Register - LD I,A ; so the top line chosen is more interesting! LD IX,HRESGEN ; Pointer to the replacement high res routine set! RET ; Return LO-RES: HALT ; Wait for an interrupt - used to sync the changeover! LD A,(FRAMES) ; Wait LD C,A ; for the SYNC2: LD A,(FRAMES) ; next CP C ; new JR Z SYNC2 ; tv frame - used to sync the changeover! LD A,1E ; Reset the "I" Register LD I,A ; to the ROM default (30 decimal) LD IX,0281 ; Pointer to the ROM display routine set! RET ; Return HRESGEN:LD HL,E71E ; Start address of (HRES DFILE - 33) + 32768 ; i.e. Set BIT 15 of address for ULA LD DE,0021 ; Amount to add each time for address of next line DI ; Disable interrupts LD C,FE ; The ULA port address LD B,16 ; Delay to sync the tv signal SYNC3: DJNZ SYNC3 ; Sync it! LD B,C0 ; The amount of hi res lines: 192 = 8*24 GENLINE:IN A,(C) ; Fool the ULA into thinking it is only on the OUT (FF),A ; top "line" of a character by resetting the ULA ROW ; counter (exactly timed with every tv VSYNC pulse) ADD HL,DE ; Calculate next screen address CALL ULAOUT ; and actually "jump" to it! DEC B ; Decrease counter JP NZ GENLINE ; Repeat until all done CALL 0292 ; ROM housekeeping routines - must be called! CALL 0220 ; ROM housekeeping routines - must be called! LD IX,HRESGEN ; Reload the hi res handler address as the ROM ; routines above reset it! JP 02A4 ; Give control back to the ROM for now ULAOUT: JP (HL) ; Yes, actually, jump into the display file! - ; The ULA will handle the rest - the Z80 "RET" ; op-code has BIT 6 SET (C9), so will be ; "executed" and control will return to the ; above "calling routine" - honest! Support ------- If you have any further questions about these routines, contact me at the email address below: stevemcd@easynet.co.uk The Sinclair ZX81 Support Page on the WWW now at: ------------------------------------------------- http://surf.to/zx81 Join the mailing list for the latest updates! This document: (C)1997 Tech/Worlde - http://welcome.to/techworlde -----------------------------------------------------------------