NOVA1000
(C) 1986 W.RIGTER
A VARIABLE DISPLAY ROUTINE
WITH MULTITASKING FEATURES
Revised 19/04/2005
INTRODUCTION
NOVA1000 is a 512 byte machine code
routine which replaces the SINCLAIR video
driver and provides some
powerful new display facilities. These include:
1. Increased horizontal line length
with up to 34 characters per line.
2. Increased number of lines with up
to 29 lines (in 50Hz mode)
3. No N/L character
(CHR$ 118) required to terminate video lines.
4. Sliding display window on memory
permits horizontal and vertical scrolling.
5. Rapid switching of Display files facilitates
screen animations.
6. Increased execution speed with
smaller screen displays for fast action.
7. View contents of large A$ string array directly
In addition to these display
features, NOVA1000 includes several new system
utilities such as
1. Repeating keys.
2. 100 Hour clock/timer
3. BASIC line number trace.
A USER JUMPVECTOR allows advanced users to add more short m/c
routines or
develop a multitasking system to run several longer programs
concurrently.
NOVA is designed to run above RAMTOP. When loaded from tape the
NOVA machine
code program is in a 0 REM line and RAND USR 16535 lowers RAMTOP
and then
relocates NOVA. The accompanying BASIC program provides an example
of using
the various NOVA screen modes and other features. The user program would
normally be combined with the 0 REM line and replace the NOVA
BASIC demo.
A copy of the demo program NOVA2005 is found here NOVA2005.p
NOVA DISPLAY - POSITION AND SIZE
The most powerful feature of this
program is the ability to create new Video
Display files located anywhere in
memory. A variable number of character per
line, a variable number of lines per
screen and the starting position (memory
address) of the screen are under
program control.
The NOVA video routines create a
window on the memory and this window can be
rapidly moved from one location to
another by changing the OFFSET parameter.
The height of this
window is controlled by the LINES parameter 1 to 28 lines.
Above the window is the
STATUS line which displays the TIMER/CLOCK (T/C)
and the TRACE line number.
Below the window the
24th line from D-FILE may be optionally displayed. This
is the BASIC
COMMAND/EDIT/INPUT line.
Like the normal screen, certain
illegal character codes must be avoided.
These illegal character codes
include CHR$64 to 127 and 192 to 256 with
exception of CHR$ 118 (N/L).
The ZX D-FILE display
can be viewed without problems and the A$ String
Variable can be used as
one large screen or multiple smaller Vfile screens.
The ZX D-FILE can be 1 to 23 lines high and 32 characters side
with the 24th
D-FILE edit line optionally shown.
To view a normal D-FILE screen for
BASIC listings etc, the screen location
parameter OFFSET is set to 0000. Since the normal expanded display
file
contains N/L characters, the line length is 32 characters. The
height of the
screen should be set for 23 and the COMMAND line turned on, to
view the normal
24th edit line. For faster program execution turn off
line 24 and or use fewer
displayed D-FILE lines. Maximum program speed is achieved with 1
displayed line.
The A$ VFILE can be much
bigger than the screen display and the display can
be moved like a window over this string array. All normal string
functions
can then directly operate on the screen. The Vfile does not
require N/L characters
to delimit each displayed line and as a result the lines are 34
characters wide.
In order to view the Variable Array, the screen location parameter
OFFST is set
to 1 or more determining the position of the start of the Vfile
window with
respect to the start of the variable array, but how do we ensure
that no portion
of memory after the end of the array displayed?
This problem of accidentally displaying data beyond the Vfile
display is
overcome by the use the Screen OFfseT (SOFT) routine, which tests
the length
of the array with the OFFSET value and sets this value to 0000 if
the offset
is too large and would result in display of data beyond the end of
the array.
In the direct edit mode or as part of a program, the SOFT routine
is called
in the form RAND USR 32680 + N where N is the offset.
Horizontal scrolling is achieved by changing OFFSET by +/- 1,
vertical
scrolling by changing OFFSET by +/- 34 and screens are paged by
changing
OFFSET +/-(34 x LINES)
If the OFFSET parameter is poked DIRECTLY to point to any other
part of
memory (ie above 32k) then the user has to ensure that this memory
to be
viewed is free of illegal character codes.
The parameter LINES holds the number
of lines between the top status line
and the bottom command line in the
range of 1 to 26.
The normal screen or D—FILE has only 24 lines of characters that
can be
viewed and any attempt to poke more into LINES may result in a
system crash.
When viewing less than 22 lines, the SLOW MODE execution of BASIC
and M/C
speed up inversely proportional to the number of viewable lines on
the screen.
The maximum speed is attained when
the value of LINES is 1 and TRACE is off
Finally the number of characters per
line can be varied by inserting a N/L
character in the line. However with
N/L’s scrolling is more difficult, for
example the vertical scroll must be
controlled by adjusting the OFFSET with
respect to the next N/L character or
34 characters whichever is less.
TIMER/CLOCK
The timer routine operates directly on 8 digits plus 3 :
delimiters in the
STATUS line. The routine increments the least significant digits
(1/60 sec per
tick) once per frame. At 59 ticks the LSD change to zero and
increments the
Second digits, which at 59+1 seconds increments Minutes, which at
59+1 minutes
increments Hours up to 99 hours. A 12 or 24 hr clock can be
implemented with
a short BASIC routine which resets the hours at 13hrs to 1hr or at
24hrs to
0 hr respectively.
The timer and in fact the entire status line can be transferred to
the COMVAR
variable as a 32 character string with RAND USER 32677. Conversely the
COMVAR contents can be transferred to the status line with RAND
USR 32674
COMVAR
The Communication Variable (COMVAR)is a string variable with a
user defined name.
COMVAR is initialized with DIM S$(RAND USR 32671) to 32 characters
and a copy of
the name, saved in the ATFR transfer byte is used to later find
the variable.
The first 11 characters correspond to the TIMER/CLOCK digits and
this is how the
TIMER is set up:
LET S$(1 TO 12) = ”00:00:00:00”
RAND USR 32674
To read the timer and compare against alarms, etc. you can use a
string function
IF S$(USR 32761 + 1 TO 11) > “10:11:12:13” THEN GOTO ALARM1
THE NOVA FLAG
The first 3 bits in the FLAG byte at location 32625 can be poked
to start and
stop various NOVA features.
The TRACE of BASIC lines numbers is a nice debug feature, which
can tell you
where the BASIC program spends most of its time. FLAG Bit 0 = 1
turns on the
TRACE feature.
Repeat key causes multiple key entries when held down. This is not
exactly a
typomatic routine so the speed depends on the calling program and number
of
lines displayed. Still I
have found it useful when a key must be recognized.
REPEAT applies to the entire keyboard. FLAG bit 1 = 1 turns on
REPEAT keys.
In some cases, it is desirable to control the visibility of the
bottom command
line. For example, turning off the command line speeds up program
execution.
FLAG bit 2 = 1 turns the COMMAND LINE on.
These are the values that may be poked into 32625
(0) trace off, repeat off, command
line off
(1) trace on , repeat off, command
line off
(2)
trace off, repeat on , command line off
(3) trace on , repeat on , command
line off
(4) trace off, repeat off, command
line on
(5) and so on to 7
The Line byte is at
32626. This byte controls the number of display
lines and therefore the
speed of user BASIC or M/C programs.
It is up to five times
faster than the SLOW mode and 80% as fast as the
normal video FAST mode
if the number of lines is reduced to 1 and
FLAG is set to
zero.
EXIT TO ZX BASIC
Exit to normal ZX video
by using FAST, SLOW, SAVE, LOAD or PAUSE xxx in
a BASIC program line.
When in the EDIT mode while NOVA is running EXIT to
ZX video by entering a
dummy program line (e.g. 1 , N/L)
Note: It is important to
remember that the NOVA timer/clock timer
does not
run in when returning to
ZX Video.
The user vector is a
three byte address starting at 32631. Location 32631 is
initially set to C9
(RET) but can be set to JP xxxx a short user routine
which must end with RET.
If the JP instruction is poked always start with the
address (32632 – LSB,
32633 – MSB before poking the C3 JP code into 32631.
MULTITASKING
MACHINE CODE PROGRAMS
For advanced programmers
NOVA can be revised and extended with additional
Machine Code routines.
The NOVA video routine is called 120 times per second
by the NMI service
routine and this provides a means to insert user routines
which run concurrently
with NOVA and any other basic or M/L programs.
The user may provide 2 types of M/C
routines to run concurrently with NOVA
and BASIC.
The first type is a
SHORT M/C ROUTINE and it is executed as part of the
program but must RETURN
before NOVA itself returns to the BASIC (or MC)
program.
The second type is the LONG M/C
PROGRAM and this program is alternating with
the main program 60
times per second, using up 50% of the available CPU time.
SHORT
USER M/C ROUTINE
The jump vector at 32631 is provided
so that NOVA may be expanded to include
user supplied routines. This may take
the form of a simple and short program,
which is terminated with
a RET instruction. It must execute in the time
between the end of the
vertical sync routine and the beginning of the active
display.
During this time, the
trace routine is also executed if enabled.
Failure to observe the time
limitation may return the system to the normal
screen or sometimes cause a system
crash. As pointed out, some more time is
available if the TRACE is never on at
the same time as the user routine.
It is recommended that the FLAG bit 4
is tested to make a conditional
RETURN Z if FLAG bit 4
is not enabled and in this way the user and TRACE
Routine can be
simultaneously controlled using POKE 32625,n or LD ($7F71),n
What can we do with such
a short routine?
1. PRINTER SPOOLER - the contents of a text
file may send to the printer
while
the current foreground program is
executing.
2.
Sensors may be scanned as part of a background home control or alarm
program
3.
Voice synthesizer may be loaded with phoneme data while displaying
characters on the screen.
4.
Joystick port can be read and characters entered as if keys were
pressed.
5. TIMER/CLOCK and REPEAT KEY are examples of the SHORT M/C ROUTINE.
Despite the limits of available time,
a SHORT M/C ROUTINE can do a lot.
LONG
USER M/C ROUTINE
The time limitation of the short user
routine may be overcome with a special
routine call TASKSWAP, which is
itself a short user routine but controls two
or more long programs
(tasks). One drawback is the need for separate M/L
stacks to save the register contents
of each task waiting to be executed. The
size of the stacks
depends on the number of nested CALLS and recursions.
In this version of
TASKSWAP the user must reserve the stack space (usually
256 bytes) and pass the
start location of the tasks to the task file.
The user can now install a second
main program (must be M/L program), which
runs concurrently with
the other main program (M/L or Basic) ,NOVA, and any
other short routines.
This means that we can run a M/L program which passes
some jobs to a second
program ( floating point calculations) but continues
with occasional checks
to see if the results are available.
The set up for running
alternating tasks is not a trivial problem and
presumes that the user
has some knowledge of the operating system as well as
the means to generate
his or her own programs.
For serious
investigation of ZX multitasking, users should develop their own
utility programs to make
this job easier.
A suggested first utility is TASKEDITOR, to start and stop tasks
controlled
by the Timer/Clock and to pass data between tasks.
Also required is a WINDOWMANAGER,
which transfers data from individual tasks
to the video window associated with that task The natural
approach is to
define various starting locations
within the viewable array as the start of
windows assign to each task and swap
them to the screen as needed.
Details of this are discussed in the
section on display size and position.
A refinement would be
multiple layered windows on one screen each with it’s
own priority, size and position which
show the viewable data produced by
each task
These and other
MULTITASKING UTILITIES have to wait for a future installment.
logging off: WILF R.
POKES
USR
POKE 32625,0 TO 15-FLAGS
RAND USR 32668 -START NOVA
POKE 32626,1 TO 26-LINES DIM
Z$ (USR 32671) -DEFINE COMVAR (B$-Z$)
POKE 32627/28,0 TO 64K-OFFSET RAND
USR 32674 -MOVE COMVAR TO STATUS
POKE 32631/3,JP VECTOR (RET)
RAND USR 32677 -MOVE STATUS TO COMVAR
POKE 32634/64,”XX..X”-STATUS
RAND USR 32680+N -USER FRIENDLY OFFSET
;NOVA SOURCE CODE LISTING
;COMPATIBLE
WITH ARTIC ASSEMBLER
;**
NEW VIDEO VECTOR **
STRT1
LD IX,VDR ;NEVER CALL VDR DIRECTLY
RET
;** MAIN LOOP **
VDR CALL SDP ;STATUS
LINE (RTC)
CALL FRM ;RTC
UPDATE
CALL VDP ;VARIABLE
LENGTH DFILE OR A$
;CALC BOTTOM BLANK LINES
CALL ZDP ;ZX
COMMAND LINE 24 (?)
CALL RTN ;KEY
REPEAT(?) AND RETURN TO BASIC
VDR1 CALL SNC ;FRAMES,
KEYBOARD, VERTICAL SYNC
LD B,07 ;ALIGN
SCREEN
CALL DLY ;VARIABLE
DELAY ROUTINE
LD A,EC ;NUMBER
OF TOP BLANK LINES
EX AF ;SAVE
FOR NMI
CALL TRCE ;BASIC LINE TRACE ROUTINE
CALL USR ;DO
USER ROUTINE
LD IX,VDR ;RESTORE VDR JUMP VECTOR
JP 02A4 ;EXIT
TO BASIC UNTIL NEXT VDR
;** VARIABLE DELAY
ROUTINE **
DLY NOP ;DELAY
TIME DEPENDS ON
DLY0 NOP ;REGISTER
B AND ENTRY POINT
DLY2 NOP ;
DLY3 NOP ;
DLY1 NOP ;EACH
NOP = 4T STATES
DLY4 NOP ;PLUS
REG B X 12T + 7T
DLY5 NOP
DLYB DJNZ DLYB
RET
;**
VSYNC VIA KEY SCAN **
SNC PUSH AF ;DUMMY
REGISTER PUSH TO
PUSH BC ;FORCE
RETURN TO VDR (NOT BASIC)
PUSH DE
PUSH HL
JP 0229 ;FRAMES,
KEYBOARD AND VSYNC
RTN LD A,(FLAG) ;CHECK
FLAG
BIT 1,A ;FOR
REPEAT BIT 1 SET
JR Z RTN1 ;EXIT IS NO REPEAT
XOR A ;REPEAT
SET SO
LD (4027),A ;RESET DEBOUNCE SYSVAR
RTN1 POP IX ;SAVE
RETURN ADDRESS IN REG IX
JP 02A2 ;START
NMI AND RETURN TO BASIC
;** TOP OF DISPLAY
SCREEM **
SDP LD B,02 ;SYNCHRONIZE
WITH DISPLAY
CALL DLY ;
LD HL,RTCL ;POINT TO THE STATUS LINE
JR ZDP1 ;AND
DISPLAY IT
;**
MIDDLE OF DISPLAY SCREEM **
VDP LD B,29 ;SYNCRONIZE
DISPLAY
CALL DLY1 ;
LD DE,(OFFST) ;FIND THE START OF THE MAIN DISPLAY
LD A,E ;IF
OFFSET IS ZERO,
OR D ;
JR Z VDP1 ;THEN DISPLAY D-FILE
LD HL,(4010) ;ELSE FIND START OF VARIABLES
ADD HL,DE ;ADD THE OFFSET
LD DE,0005 ;ADD A$ HEADER LENGTH
JR VDP2 ;AND
DISPLAY VFILE
VDP1 LD HL,(400C) ;LOAD
DFILE START
ADD HL,DE ;DELAY
LD DE,0001 ;SKIP LEADING N/L
JR NZ VDP2 ;DELAY
VDP2 ADD HL,DE ;TRUE
START OF DISPLAY
LD A,(LINES) ;CALCULATE NUMBER OF LINES
AND 1F ;
LD B,A ;SAVE
IN B
RLCA ;CALCULATE
BALNK LINES
RLCA ;
RLCA ;
ADD A,3B ;
EX AF ;SAVE
IN AF’ FOR NMI
LD C,08 ;
JR ZDP2 ;GO
DISPLAY MAIN SCREEN ALREADY
;**
BOTTOM OF DISPLAY SCREEN **
ZDP LD B,73 ;VSYNC
DELAY
CALL DLY5 ;
LD A,(FLAG) ;DISPLAY ZX COMMAND LINE 24 (?)
BIT 2,A ;
JR NZ ZDP0 ;YES, GO DISPLAY LINE 24
EX AF ;NO
LINE 24 = ADD EXTRA BLANK TIME
SUB
09 ;
EX AF ;SAVE
FOR NMI
RET ;
ZDP0 XOR A ;START
OF LINE 24 CAN BE FOUND BY
LD HL,(4010) ;START OF VAR AREA
LD DE,0021 ;32 CHARACTERS PLUS NEWLINE
SBC HL,DE ;SUBTRACT TO POINT TO START OF LINE 24
ZDP1 LD BC,0108 ;ONE
ROW OR 8 HORIZONTAL LINES
ZDP2 SET 7,H ;ECHO
DISPLAY ABOVE 32K
LD A,DD ;34
CHARACTERS PER LINE OR N/L (HALT WITH A6 INTERRUPT)
JP 0041 ;GO
TO ZX INTERRUPT ROUTINE AND RETURN
;CONVERT
LINE NUMBER IN (4007) TO DECIMAL
TRCE LD A,(FLAG) ;CHECK
FLAG FOR BASIC LINE TRACE ON (?)
BIT 0,A ;
RET Z ;RETURN
IF NO TRACE
LD DE,TRCL ;START OF TOP STATUS LINE
LD HL,(4007) ;BASIC LINE NUMBER
LD BC,FC18 ;DIVIDE BY 1000
CALL TR1 ;
LD BC,FF9C ;DIVIDE BY 100
CALL TR1 ;
LD BC,FFF6 ;DIVIDE BY 10
CALL TR1 ;
LD A,1C ;PLUS
UNITS
ADD A,L ;
JR TR3 ;
TR1 LD A,1C ;DECIMAL
CONVERSION HAS
TR2 ADD HL,BC ;VARIABLE
EXECUTION TIME
INC A ;SO
RUN WHILE NMI IS ON
JR C TR2 ;SUBTRACT
BC UNTIL OVERFLOW
SBC HL,BC ;SUBTRACT ONE LOOP
DEC A ;ADJUST
DIGIT
TR3 AND 3F ;LIMIT
RESULT
LD (DE),A ;LOAD DIGIT IN TRACE FIELD
INC DE ;NEXT
DIGIT
RET ;
;UPDATE 100 HR TIMER
FRM LD DE,TITL-1 ;POINTER TO TIMER FIELD LEAST SIGNIFICANT DIGIT
LD HL,FRM6+1 ;POINTER
TO DIGIT LIMITS AND COLON FLAG
LD B,08 ;8
DIGITS
SCF ;FIXED
EXECUTION TIME BETWEEN STATUS LINE AND VDP
FRM1 LD A,(DE) ;GET
DIGIT
ADC A,00 ;CARRY
FLAG ADDS ONE TO DIGIT
CP (HL) ;CHECK
AGAINST LIMIT
CCF ;IF
LIMIT THEN RESET DIGIT TO ZERO
JR C FRM2 ;AND CARRY INCREMENTS NEXT DIGIT
LD (DE),A ;ELSE NO CARRY AND LOAD TIMER FIELD WITH DIGIT+1
JR FRM3 ;
FRM2 LD A,1C ;SET
DIGIT TO ZERO
LD (DE),A ;LOAD TIMER FIELD WITH ZERO DIGIT
FRM3 DEC DE ;
DEC HL ;
BIT 7,(HL) ;TEST FOR COLON FLAG
JR Z FRM5 ;JR IF NOT COLON
DEC DE ;POINT
TO NEXT DIGIT
DEC HL ;POINT
TO NEXT LIMIT
FRM5 DJNZ FRM1 ;DO
EIGHT TIMES
RET ;
26 26 80 ; LIMIT 99: (HRS)
22 26 80 ;
LIMIT 59: (MIN)
22 26 80 ;
LIMIT 59: (SEC)
FRM6 22 26 ;
LIMIT 59 (1/60SEC)
;INITIALIZE THE COMVAR
STRING ARRAY
DIM1 XOR A ;USING
DIM ?$ (USR 32671)
LD HL,(4016) ;USE CH-AD TO POINT TO NAME
LD DE,000F ;IN THE BASIC LINE
SBC HL,DE ;
LD A,(HL) ;GET NAME
LD HL,ATFR ;SAVE NAME IN ATFR
LD (HL),A ;
LD C,20 ;USR
MUST RETURN 32
LD B,00 ;AS
THE DIMENSION OF THE ARRAY
RET ;
ULD1 CALL ALD ;LOAD
DATA FROM COMVAR TO STATUS LINE
JR DLD2 ;GO
TRANSFER
DLD1 CALL ALD ;LOAD
DATA FROM STATUS LINE TO COMVAR
EX DE,HL ;
DLD2 LDIR ;ACTUAL
TRANSFER
JR ALD1 ;
ALD LD HL,(4016) ;SAVE THE CH-ADD POINTER
EX (SP),HL ;
PUSH HL ;
LD HL,ATFR ;POINT TO COMVAR NAME
CALL 004D ;SET CH-ADD TO COMVAR NAME
CALL 111C ;LOOK UP COMVAR ADDRESS
LD DE,0006 ;SKIP COMVAR HEADER
ADD HL,DE ;
LD DE,RTCL ;POINTER TO TIMER/CLOCK FIELD
LD BC,000B ;LENGTH OF TIMER/CLOCK FIELD
RET ;
ALD1 POP HL ;RESTORE
CH-ADD
LD (4016),HL ;
RET ;
;CHECK IF OFFSET EXCEEDS VFIEL
SOFT1
LD HL,(4016) ;SAVE CH-ADD
PUSH HL ;
RST 20 ;FIRST
CHECK IF A$ EXISTS
LD HL,(4010) ;EXIT TO DFILE IF A$ WAS ERASED
LD A,(HL) ;BECAUSE OF RUN, CLEAR, ETC.
CP C6 ;
JR NZ SOFT2 ;
CALL 1300 ;NOW FIND END OF ARRAY
LD HL,0340 ;ASSUME A FULL SCREEN IS REQUIRED
EX DE,HL ;CAUSE
LINES CAN BE ADJUSTED
SBC HL,DE ;ENOUGH ROOM FOR A FULL SCREEN?
JR C SOFT2 ;
CALL 12DD ;EVALUATE THE USR EXPRESSION
JR NC SOFT3 ;AND SAVE IN BC
SOFT2
LD BC,0000 ;SET BC TO ZERO
SOFT3
LD (OFFST),BC ;SAVE IN OFFSET
JR ALD1 ;
JPTBL ;START OF PROGRAM VARIABLE
AREA
SPARE
"12345" ;SPARE BYTES
FLAG 04 ;FLAG
CONTROLS FEATURES (eg COMMAND LINE on)
LINES
18 ;NUMBER OF DISPLAYED
LINES
OFFST
00 ;OFFSET FROM START OF A$
VARIABLE
00 ;OR
“0000” IS DFILE
USR RET ;3
BYTE USER CALL TO SHORT ROUTINE
00 ;MUST
RETURN BEFORE TIME IS UP
00 ;
ATFR "Z$" ;NAME OF COMVAR (TRANSFERS DATA TO LINE 1)
RTCL "00:00:00:00" ;THESE THREE FIELDS MAKE UP STATUS LINE 1
TITL "
NOVA 1000 V1.0";
TRCL "
<" ;
;JUMP
TABLE FOR NOVA ROUTINES
STRT JP STRT1 ;ACTIVATE
NOVA VIDEO ROUTINE
DIM JP DIM1 ;INITIALIZE
COMVAR NAME
ULD JP ULD1 ;MOVE
COMVAR TO STATUS LINE
DLD JP DLD1 ;MOVE
STATUS LINE TO COMVAR
SOFT JP SOFT1 ;TEST
AND LOAD OFFSET
NOVA BASIC DEMO PROGRAM
Revision History
1986 –
first release of NOVA – minimal documentation
18/04/2005
– NOVA resurrected – full annotated documentation and source program
19/04/2005
– EXIT methods added and FRAMES now updates - Thanks to Siegfried Engel