

              WRX1K V1.0 1996 - HIRES ON A 1K ZX81

                 wilf rigter (rigter@cafe.net)



This article contains all information needed to demonstrate WRX true

 bit mapped high resolution graphics on a 1K/2K Sinclair ZX81.

The full size program WRX16 generates a 256x192 pixel array while the

WRX1K demo generates a 64x48 pixel array in the center of the screen.

The small scale demo runs on an unmodified 1K/2K ZX81/TS1000 and is

small enough to type in by hand. The small hires screen has another

interesting side effect: it runs SLOW mode programs almost 4X faster

than the Sinclair SLOW video mode while providing a continuous display.

I would like to acknowledge the wonderful work of Dr. Carlos Delhez for

creating XTender and Jack Raats for the PC tools to transfer XTender

files to ASCII.



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 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 made the inevitable

speed/size tradeoffs, experienced the occasional flash of insight and

used a large trash can 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 normal

Sinclair display. This is required for users to be able to list and edit

the BASIC program lines on a 1K machine. While I could spend time explaining

how it all works, I suggest reading the annotated source code and send me

an email if you like more information. WRX1K.ZIP which includes the binary

C and XTENDER compatable P files, will be available at the NVG site.



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 be able 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)



TS1000 (2K) USERS



The 2K memory in a TS1000 permits the demo program

to be expanded in several ways ie.



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.

A companion file WRX1K11.ZIP will be posted on the NVG ftp site.

If you have any problems, questions, or if you have any

neat demo source code post them on comp.sys.sinclair (no binaries

please) or contact me via email at:



rigter@cafe.net



enjoy



wilf



----------------------------------------------------



                       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 -------





