WRX1K
V1.0 1996 - HIRES ON A 1K ZX81 - wilf rigter (updated 04/2005)
This
article contains all information needed to demonstrate WRX true
bit
mapped high resolution graphics on a barebones ZX81 or TS1000.
The
WRX1K program is a demo that will work with just 1K of RAM.
It
is a scaled down version of WRX16, which generates a 256x192 pixel
array
but that would require 6Kbytes for the
hires video screen alone.
Unlike
pseudo hires, in true hires any pixel on the screen can be directly
set
or reset.
The
WRX1K video driver and the demo Basic and M/C application program
and
the display are all crammed into 1K of RAM space.
WRX1K
video driver generates a smooth, non-flicker 64x48 pixel hires mini
display
in the center of the screen which is actually the same resolution as
a
screen plot generated by the ZX PLOT commands.
The
WRX video driver replaces the main part of the ZX video routine. The
driver
runs in the background and uses the equivalent of just six normal
lines
of ZX video characters to generate the mini display.
This
frees up a lot more CPU time for the demo Basic and M/C programs,
which
run in the SLOW mode 4X faster than with the normal ZX video screen.
The
whole demo program is small enough to type in by hand but a companion
zip
file is available here WRX1K1.ZIP
including a ready to run .p file.
A
16K demo version with the Hires file between 8-16K can be found here:
INTRODUCTION
WRX1K
and it's big brother WRX16 use the same algorithm of addressing
the
hires screen memory with the I and R registers. Both require SRAM
for
the hires screen and this means that (unmodified) 16K-64K DRAM packs
are
not suitable. While a few people may have installed 8K or 32K SRAM chips
in
their ZX81, everyone has 1K or 2K installed. With the 1K memory as
the
lowest common denominator, I modified the WRX16 program to run on
this
minimal platform.
I
must confess to being a minimalist at heart and the challenge of packing
performance
into a small package is a little like writing code for a controller chip.
I
had to make the inevitable speed/size tradeoffs and used a large trashcan to
write
this program.
The
resulting code is short (210 bytes) and relatively easy to type in,
even
from a ZX81 keyboard. This is important here since there is (still)
no
standard way to transfer programs from a PC to a ZX81.
The
WRX1K program has some special features to operate with only 1K memory.
When
starting the hires mode, it dynamically creates a 384 byte space above
RAMTOP
for the hires screen but reclaims this space when returning to the
Normal
Sinclair display. This is required for users to be able to list and edit
the
BASIC program lines on a 1K machine. Rather then explaining the details
here,
I suggest reading the annotated source code and send me an email if you
like
more information
For
TS1000 users, the 2K RAM in a TS1000 permits the demo program
to
be expanded in several ways :
1.
Multiple screens of 64x48
2.
Larger hires screen of 128x96
2.
No need to reclaim screen memory
3.
Lower case and special character pattern tables
4.
bigger BASIC and ML programs.
5.
Line and circle plotting utilities.
I
will post WRX2K if there is interest (or you may prefer to "roll"
your
own version).
FEEDBACK
The
information in this package is enough to get started.
If
you have any problems, questions, or if you have any
neat
demo source code post them on www.ts1000.us or
contact
me via email at: wrigter@dccnet.com
enjoy
wilf
--------------------------------------------------------------------------------------
This
article includes the following listings:
LOADER.BAS
LOADER.HEX
WRX1K1.HEX
WRX1K1.BAS
LOADER.SRC
WRX1K1.SRC
INSTALLING
WRX1K1.SRC WITH ZXAS
ZXAS
is the ARTIC assembler used to write this program and may be used
on
a ZX81 or on a PC using XTender, the shareware ZX81 emulator by
Dr.
Carlos Delhez. Using the ZX81, you can type in the source listing
WRX1K1.SRC
(;comments are optional) and assemble the required object code
in
line 1 REM. In order to use ZXAS you must have a 16K+ rampack installed.
After
assembling the ML code and entering the WRX1K1.BAS listing, you must
lower
RAMTOP with POKE 16389,68 and SAVE to tape. Finally remove the
rampack,
LOAD the saved program into the 1K/2K ZX81 and RUN.
INSTALLING
WRX1K1.HEX WITH HEX LOADER
In
order to load the WRX1K1.HEX FILE, type in the BASIC program LOADER.BAS
Since
the ML code is stored in a large REM line this is created first by
entering
a short 16 hex byte program called LOADER.HEX which will
expand
the 1 REM 0123456789ABCDEF line by 256 bytes.
USING
THE HEX LOADER
The
HEX LOADER accepts the following commands "Q"=QUIT,
"N"=NEXT LINE,
"P"=PREVIOUS.
Hex code is entered 16 bytes at a time in one line of 32
hex
values WITHOUT spaces. The HEX listing includes spaces between each
two
digit hex value for clarity and line numbers for reference only .
Compare
the typed in hex data in the command line with the listing before
pressing
the N/L key. The HEX data is checked for 32 character length.
After
entering the LOADER.HEX line, press "Q" to quit the loader.
SAVING
to tape is optional at this point since this format may be used
as
the starting point for entering your own ML programs in hex format.
Next
enter RAND USR 16516. This executes the LOADER.HEX code just
entered
and expands the existing 1 REM line by adding 256 new spaces.
Don't
worry if the 1REM line appears to be empty, this is caused by the
first
two characters chr$118 which make the contents of 1 REM invisible.
To
see the rest of the BASIC listing POKE 16419,10 and LIST 10.
Next
restart the loader with RUN and enter the 14 lines of 16 hex values
each
line ending with a N/L (enter). Please double check the hex data
before
pressing the enter key. After the last hex data line is entered
erase
the LOADER.BAS lines (but not the 1 REM line). SAVE again and then
type
in the WRX1K.BAS program. Finally SAVE this program to tape and start
the
WRX1K demo with RUN.
STARTING
WRX1K
RUN
starts the WRX1K hires mode with RAND USR 16516, which lowers RAMTOP
(and
changes Stack Pointer without NEW), and starts the hires video mode.
RAND
USR 16709 clears the hires display file and RAND USR 16696 selects a
white
or black background. The BASIC program uses Marvin Minsky's circle
plotting
algorithm to calculate the coordinates for a series of concentric
circles.
This algorithm is faster than the COS/SIN function. The X and Y
coordinates
are poked into variables 16507/16508 and the plot bit is set
in
variable 16417. The program loops endlessly plotting white on black
and
then black on white. The BREAK key returns to Sinclair video,
interrupts
the program and automatically reclaims the hires screen
memory.
You can list the basic with POKE 16419,5 and LIST 5. On a 1K
ZX81
the basic listing may be short because of the limited memory.
Use
LIST with higher line numbers to view the remainder of the program.
WRX1K
VARIABLES
WRX1K
uses several System Variable (SYSVAR) bytes to transfer data
to
the machine language program:
POKE
16507,X - the X coordinate for plotting pixels (0-63)
POKE
16508,Y - the Y coordinate for plotting pixels (0-47)
POKE
16417,Z - the plot/unplot flag (0=unplot 1=plot)
WRX1K
UTILITIES
The
entry points for the ML program are :
RAND
USR 16516 - START the hires mode
RAND
USR 16648 - HPLOT or unplot pixel at x,y (uses SYSVAR 16417,16507/8)
RAND
USR 16693 - INVERT hires screen (plot black on white or white on black)
RAND
USR 16709 - CLEAR hires screen
RAND
USR 16723 - USER routine (60 bytes free)
----------------------------------------------------
START OF LISTINGS
-----------------
LOADER.BAS
----------
1 REM 0123456789ABCDEF
70 PRINT " HEX LOADER
BY WILF RIGTER"
80 LET L=NOT PI
90 LET A=VAL "16514"
100 PRINT AT PI,NOT PI;"Q=STOP,N=NEXT,P=PREVIOUS LINE
";CHR$ (L+28)
110 INPUT A$
120 IF A$="N" THEN GOTO VAL "200"
130 IF A$="P" THEN GOTO VAL "300"
140 IF A$="Q" THEN STOP
150 IF LEN A$<>VAL "32" THEN GOTO VAL
"100"
160 FOR N=0 TO 31 STEP 2
170 POKE A+N/2,16*CODE A$(N+1)+CODE A$(N+2)-476
180 NEXT N
200 LET A=A+VAL "16"
210 LET L=L+PI/PI
220 IF L<VAL "16" THEN GOTO VAL "100"
300 LET A=A-VAL "16"
310 LET L=L-PI/PI
320 IF L>NOT PI THEN GOTO VAL "100"
330 GOTO VAL "80"
LOADER.HEX -
STARTS AT 16514 (4082$)
----------------------------------------
LINE 0 7676CD230F01000121804034C39E0900
WRX1K1.HEX -
STARTS AT 16514 (4082$)
----------------------------------------
LINE 0 7676DD21BF40018001CDC50E2A0440C5
LINE 1 D13FED52D3FD2204402B363E2BF92B2B
LINE 2 220240D3FEC37606E3E3E3E3ED4F0000
LINE 3 0000000000004040404040DDE9060410
LINE 4 FE2A04400630DD21CE40180811080019
LINE 5 05CADD407CED477DC3AAC0DD21E6403E
LINE 6 98C3A102CD2002CD460F3009DD21BF40
LINE 7 3E98C3A1023E1EED472A044011800119
LINE 8 DD218102188E2A7B407DE6074704AF37
LINE 9 1F10FD4F7D1717E6E06F3E2F94D867AF
LINE A 2929296C8F67ED5B0440197EB1FDCB21
LINE B 462001A977C9060821B0407EEE807723
LINE C 10F9C92A0440AF77545D13017F01EDB0
LINE D C9000000000000000000000000000000
LINE E 00000000000000000000000000000000
LINE F 00000000000000000000000000000000
WRX1K1.BAS - DEMO PROGRAM PLOTS CIRCLES
1 REM line created by LOADER or ZXAS
5 REM WRX1K1.BAS
10 RAND USR VAL "16516"
20 RAND USR VAL "16709"
30 RAND USR VAL "16696"
40 POKE VAL "16417",PI/PI
50 LET P=VAL "16648"
60 LET X1=VAL "16507
70 LET Y1=X1+PI/PI
80 LET T=VAL "24"
90 LET S=VAL "32"
100 FOR R=PI/PI TO VAL "24" STEP VAL "4"
110 LET X=R
120 LET Y=PI-PI
130 FOR N=1 TO 3.2*R
140 LET X=X-Y/R
150 LET Y=Y+X/R
160 POKE X1,S+X
170 POKE Y1,T+Y
180 RAND USR P
190 POKE X1,S-X
200 POKE Y1,T-Y
210 RAND USR P
220 NEXT N
230 NEXT R
240 GOTO 20
LOADER.SRC
CALL 0F23 ;SET FAST
MODE
LD BC,0100 ;256 SPACES
LD HL,4080 ;MSB OF
LINE LENGTH
INC (HL) ;ADD 256
BYTES
JP 099E ;MAKE ROOM
AND EXIT
WRX1K1.SRC
;************************
;WRX1K1-1996 WILF RIGTER*
;CREATES A 64X48 HIRES
*
;SCREEN ON A 1K SINCLAIR*
;INCLUDES INITIALIZATION*
;CLEAR,INVERT SCREEN AND*
;PLOT/UNPLOT ROUTINES
*
;CODE LENGTH = 210 BYTES*
;HFILE LENGTH= 384 BYTES*
;************************
;A SMALL SCALE DEMO OF
;WRX16 - TRUE BIT MAPPED
;256X192 HIRES GRAPHICS
;----------------------
;THE MAIN HIRES ROUTINES
START ;LOCATED AT 16516
($4084)
;MAKE ROOM ABOVE RAMTOP
;AND START HIRES VIDEO
;----------------------
LD IX,HR ;HR VECTOR
LD BC,180 ;64X48
BITS
CALL EC5 ;TEST ROOM
LD HL,(4004);LOWER RAMTOP
PUSH BC
POP DE
CCF
SBC HL,DE
STACK OUT FD,A ;TURN OFF NMI
LD (4004),HL;NEW RAMTOP
DEC HL
LD (HL),3E
DEC HL
LD SP,HL ;NEW SP
DEC HL
DEC HL
LD (4002),HL;NEW ERROR SP
OUT FE,A ;TURN ON
NMI
JP 676 ;NEXT LINE
LBUF
;DUMMY DFILE LINE =
;1 LINE OF 64 PIXELS
;EXECUTED ABOVE 32K
;-------------------
E3 E3 E3 E3;DELAY 76T
LD R,A ;NOW LOAD R
LBYTE 00 00 00 00;8 LBYTES
WITH
00 00 00 00;8 PIXELS EACH
40 40 40 40;DELAY 20T
40 ;DELAY 4T
JP (IX) ;RETURN TO
HR
HR ;THE 64X48 VIDEO ROUTINE
;NEVER CALL DIRECTLY:MUST
;INITIALIZE WITH "START"
;CHECKS BREAK KEY:IF DOWN
;JUMPS VIA STOP TO NORMAL
;SINCLAIR VIDEO
;OR ELSE LOOPS TO VSYNC
;-----------------------
LD B,04 ;LOAD DELAY
HR0 DJNZ HR0
;DELAY 56T
LD HL,(4004);TOP OF HFILE
LD B,30 ;48 LINES
LD IX,HR1 ;RETURN VECTOR
JR HR2 ;SKIP HR1
HR1 LD DE,08
;8*8 BITS
ADD HL,DE ;NEXT LINE
DEC B
JP Z HR3 ;LAST LINE?
HR2 LD A,H
;REFRESH
LD I,A ;ADDRESS IN
LD A,L ;REG I AND R
JP C0AA ;JUMP TO
LBUF
HR3 LD IX,HR4 ;VSYNC VECTOR
LD A,98 ;104 BLANK
JP 2A1 ;POP MAIN
REG
HR4 CALL 220
;DUMMY PUSH
CALL F46 ;BREAK KEY
JR NC STOP;TO EXIT HR
LD IX,HR ;HR VECTOR
LD A,98 ;BLANK LINES
JP 2A1 ;POP MAIN
REG
STOP ;BREAK EXIT TO
LD A,1E ;SINCLAIR
VIDEO
LD I,A ;ROM
PATTERNS
LD HL,(4004) ;RAMTOP + 1
LD DE,180 ;HFILE LENGTH
ADD HL,DE ;RESTORE RAMTOP
LD IX,0281;SINCLAIR
VIDEO
JR STACK ;
;------------------------
;START OF THE HIRES
;SCREEN UTILITIES
;------------------
PLOT ;LOCATED AT 16648 (4108$)
;PLOT ROUTINE CALCULATES
;BYTE LOCATION AND BIT
;POSITION FROM THE X/Y
;COORDINATES. PLOT/UNPLOT
;FLAG IS BIT 0 OF (4021)
;IF BIT 0 = 1 THEN PLOT
;IF BIT 0 = 0 THEN UNPLOT
;-----------------------
LD HL,(407B);L=X H=Y
BIT LD A,L
;3 LSB OF X
AND 7 ;BIT
LOCATION
LD B,A
INC B
XOR A
SCF ;SET C
FLAG
BIT1 RRA
;SHIFT BIT
DJNZ BIT1
LD C,A ;SAVE BIT
BYTE LD A,L
;CALCULATE
RLA ;OFFSET =
RLA ;Y*8+X/8
AND E0
LD L,A ;START PLOT
LD A,2F ;ORIGIN AT
SUB H
;BOTTOM/LEFT
RET C ;EXIT IF
OUT
LD H,A ;OF BOUNDS
XOR A ;A=0
ADD HL,HL ;SHIFT
INTO
ADD HL,HL
ADD HL,HL
LD L,H ;LSB = 0
TO
ADC A,A ;GET 9TH
BIT
LD H,A ;MSB = 0
TO
LD DE,(4004);DE=HFILE
ADD HL,DE ;BYTE
ADDRESS
LD A,(HL) ;FETCH
BYTE
OR C ;AND SET
BIT
BIT 0,(IY+33);TEST FOR UN
JR NZ LDPLT ;SKIP UNPLOT
XOR C ;RESET BIT
LDPLT LD (HL),A ;LD HFILE
RET
INVERT
;LOCATED AT 16696 (4138$)
;INVERTS SCREEN WITH
;8TH BIT IN LBUF
;----------------------
LD B,8 ;8 LBYTES
LD HL,LBYTE;FIRST
INV1 LD A,(HL)
;INVERT 8TH
XOR 80 ;BIT
LD (HL),A
INC HL ;NEXT LBYTE
DJNZ INV1 ;REPEAT 8X
RET
CLEAR ;LOCATED AT 16709
(4145$)
;LOADS HFILE WITH ZEROES
;-----------------------
LD HL,(4004); HFILE
XOR A ;ZERO
LD (HL),A ;FIRST
LD D,H
LD E,L
INC DE ;NEXT
LD BC,017F ;384 BYTES
LDIR ;COPY OVER
RET
USER ;LOCATED AT 16723 (4153$)
;START OF USER CODE BLOCK
;LAST BYTE 16788 (4194$)
;-----------------------
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0
RET
------- END OF LISTINGS -------