Martin (mvdzwan@syncnet.dmrt.nl) - Question:
>This little routine (I did not write it) can print to
the screen in
>fast mode and lets you see it, it is a compromise
between fast and
>slow so the screen flickers when this routine is used.
>Note: This routine will only make sense when used on a
real ZX81/Timex 1000
>Perhaps someone here could explain how this routine
works, I tried to put
>some comments and looked up the Rom Calls, but I do not
really understand it.
wilf rigter (wrigter@dccnet.com) - Answer:
As requested here is a full explanation of the program
listing you posted
including annotated references to the ROM code.
Note that, with exception of the START and BASIC routines,
all this code runs
in the background as part of the interrupt driven video
processing and sync
loop. In my comments I used the term PROGRAM to mean any
"foreground" code
such as application programs other than the code in the
background loop.
Actually, I simplified your program slightly for
clarification and to keep the
focus on key elements.
*****************************************************************************
*START: ;INSERT NEW VIDEO ROUTINES IN THE VIDEO
DISPLAY LOOP
;Sinclair SLOW video routine sequence is altered by
replacing
;parts with new video code.
CALL 0F2B SLOW COMMAND routine
;this is the functionally the same as: Set 6,(IY+4B)
, JP 0207
LD IX,VID1 ;Save vector to START OF VIDEO DISPLAY
routine
RET ; return from USR call
***********************************************
* NEW
INTERRUPT DRIVEN BACKGROUND LOOP *
***********************************************
VID1: ;START OF VIDEO DISPLAY routine
;similar to ROM routine @ 0282
;no comments in the ZX81 ROM DISASSEMBLY by IAN LOGAN
LD R,A ;delay 7 T states (note the change to
another 7 T instruction)
LD BC,1901 ;B = 24 character rows, C = 1 of 8
scanlines / CHR$ (wait 1 INT)
;experiment with B= 16 to 19 and C = to 1
and note effect
;on start of the first row, truncated character
height, rollover
LD A,F5 ;later transferred to R and determines
the left edge of 1st row
CALL 02B5 ;START DISPLAY OF DFILE - see ROM code
shown below
CALL ROM2 ;RETURN TO PROGRAM - see ROM code shown
below
CALL ROM3 ;
LD IX,VID2 ;save vector to END OF DISPLAY routine
JP ROM4 ;ROM code at 02A4 shown below
*****************************************************************************
VID2: ;END DFILE DISPLAY routine - similar
to ROM routine @ 28F
;this contains the only piece of code that actually
changes the
;original Sinclair SLOW mode. Note the large number
of extra
;blank lines that are added to margin, providing 20
msec extra
;CPU time for the application program every vertical
sync period.
;The display vertical frequency is actually 25 Hz but
the TV
;displays this as two alternating/superimposed live
and blank
;screens. No
wonder it runs faster and no wonder it flickers!
OUT (FD),A ;Turn off the NMI generator
LD A,(4028) ;get margin (A=1F)
ADD A,C2 ;1F+C2=E1
LD (4028),A ;(MARGIN)=E1
CALL ROM2 ;Return to PROGRAM
CALL ROM3 ;save PROGRAM registers and process
FRAMES, KEYBOARD and VSYNC
LD IX,VID1 ;Vector back to DISPLAY DFILE routine
JP ROM4 ;Return to PROGRAM
**************************
* ZX81 ROM
ROUTINES *
**************************
;ROM CODE @ 02B5 - DISPLAY DFILE ROUTINE
;Sets up R register and waits for interrupt (IAN
LOGAN)
;Sets up R register, enables INT, JP (HL) to DFILE
above 32K
;halts execution at first HALT of DFILE and waits for
INT.
LD R,A ;R increments with each M1 and is put
on A0 to A7 during refresh
;When CPU HALTs at CHR$118, R continues to increment
until A6
;goes low which causes an INT signal. (A6 is
connected to INT)
;this ensures that the end of line timing is
consistent also
;during a collapsed display when there may only be a
HALT.
LD A,DD ;Set the left margin of all other
lines, loaded into R at 0041
;try E6 to shift screen right one character (change
LD A,F5 too)
EI ;Now that R is set up enable INT
JP (HL) ;(rem HL = (DFILE)+32K)
"executes" the DFILE starting with HALT
;and wait for the first INT to come to the rescue.
*****************************************************************************
;ROM CODE @ 0292 - RETURN TO PROGRAM ROUTINE
;IX is loaded with "return" address and
main registers restored
;after a slow display (IAN LOGAN)
;Save return address of live display or vertical sync
interval
;routines in
IX , PROGRAM registers are restore ( which were
;previously saved when PROGRAM was interrupted for by
NMI @ 0066
;and NMI-CONT @ 006F) and finally RETURNs to PROGRAM
execution,
;interrupted every ~ 64 usec by NMI until AF'= 0
POP IX ;Normally IX=0281 or 028F to flip
between DISPLAY and VSYNC
;in this case IX=VID1 or VID2 to execute special
video routines
LD C,(IY+56) ;load number of blank lines from MARGIN (1F
in 60 Hz option)
BIT 7,(IY+59) ;test
FAST/SLOW bit
JR Z,2A9 ;never branches in SLOW mode
LD A,C ;LD A,(MARGIN) (MARGIN contains 1F for
60 Hz)
NEG ;A=E1
INC A ;A=E2 which means 30 blank lines above and below the display
EX AF,AF' ;during NMI @ 0066 - AF' is incremented
and tested for zero
OUT (FE),A ;turn on NMI generator in ULA which
interrupts every 64 uSec.
POP HL ;self explanatory
POP DE
POP BC
POP AF
RET ;returns to program later interrupted
by NMI and NMI-CONT
*****************************************************************************
;ROM CODE @ 0220 - VERTICAL SYNC INTERVAL PROCESSING
ROUTINE
PUSH AF ;save PROGRAM main registers
PUSH BC
PUSH DE
PUSH HL
JP 0229 ;Jump to long complicated Sinclair ROM
segment not copied here
;decrement FRAME counter, read the keyboard, generate
vertical
;sync and end with CALL 0292 to return PROGRAM
*****************************************************************************
;ROM CODE @ 02A4
POP HL ;self explanatory
POP DE
POP BC
POP AF
RET ;return to program interrupted by
NMI and NMI-CONT
*****************************************************************************
Here is a simplified basic
routine to test it:
1 REM "PUT HERE THE MACHINE CODE"
10 FOR A=1 TO 21
;fill the screen
20 PRINT "TEST OF NEW SLOW MODE VIDEO EXPERIMENTS"
30 NEXT A ;
with 22 rows of characters
40 RAND USR 16516 ; call new slow display mode
50 GOSUB 100 ;
delay and display 0 to 9
60 SLOW ;
flip back to Sinclair slow mode
70 GOSUB 100 ;
delay and display 0 to 9
80 GOTO 40 ;
loop indefinitely
100 FOR N= 0 TO 9 ;
delay loop used to measure execution time
110 PRINT AT 21,13;N ;
real-time count display
120 NEXT N
130 FAST ;
effectively LD IX, 0281 to escape from VID1/2
140 RETURN