Authors
Publication
Pub Details
Date
Pages
BASIC Terms
After reading your article on “TS2068 Video Bells and Whistles” in the October, 1992 issue of UPDATE, I decided to write a sample program which incorporated incorporated your your ideas on using the high resolution color graphics mode. The result is the enclosed program on disk in LKDOS format. “PALLET.B1” utilizes the entire 24 line screen to draw pictures. Only the pallet area of the screen is locked out for drawing color images. It also has a file saving and loading capability. When you run the program, the screen displays the available color pallet at the lower right and a small white area above it. A flashing cursor is displayed near the pallet area. The program is designed to operate with a standard TS2068 compatible joystick which is plugged into the port on the left side of the computer. If you desire to load a screen from disk instead of drawing a new one, then the first action must be to move the cursor to the small white area above the pallet. Pressing the button on the joystick at this time will result in a message asking you to input the name of a file to be loaded. I have included a sample file named “DEM01” which can be used to demonstrate this feature. The saved file consists of only the second display area of 6144 bytes which contains the color attributes for the display. Since the primary display file only consists of alternating 4 bit “BIXELS” of ink and paper, there is no need to save it. The “DEM01” program is not intended as a work of art since my artistic ability is slightly less than my musical talent, which is zero.
If you wish to create a new graphic drawing, then the initial action after running the program, would be to move the cursor to a selected color area on the pallet and pressing the joystick button. The selected color is displayed in a character position located near the pallet. After selecting a color, slew the cursor to a desired position on the screen and press the button, holding it until the cursor stops blinking. After this, moving the cursor will result in the selected color being left in the “BIXEL” positions that the cursor traverses. To turn off the painting of color, press the button again until the cursor stops blinking. The cursor can then be moved to a different part of the screen where the drawing can be continued or a new color may be selected from the pallet.
When you are finished with the drawing, you may move the cursor to the small white area and push the joystick button. you will be asked for the name of the file to be saved at which time you can enter a file name up to 6 characters long (the .C1 suffix is added by the program. If you “NOFILE” enter the name “NOFILE” or “nofile” then the program will terminate with all parameters returned to normal. You can also terminate the program at any time with the “BREAK” will also command which will also result in all parameters being returned to normal.
I wrote the bulk of the program in BASIC in order to demonstrate the feasibility of doing so. There are 152 bytes feasibility of machine code which is loaded into the printer buffer area of memory when the program is run. This code handles the video mode changes, the movement of the O.S. RAM code to high memory and back, and the primary and secondary display file initialization. It also has a section which moves the lower third of the second display file temporarily to high memory when this portion of the screen is enabled for print statements.
The only problem with writing the main program in BASIC is the fairly slow movement of the cursor. Although some speedup of the movement could be achieved by rearranging the order of the subroutines to shorten the search time, I will probably convert much of the program to machine code. You mentioned in your article that the two 768 byte areas normally used for the screen attribute files are available for machine code in the high resolution color but mode. This is true, but extreme care must be used in connection with the primary display file attributes area. Although the SCLD chip does not access this area when the high resolution color mode is active, HOME ROM routines PRINT such as CLS and PRINT will overwrite all or part of the primary screen attributes area with the ink and paper colors stored in the systems variables area of memory.
I have included a listing of the program and a listing of the code utilized for screen setup. I have also included a machine code utility program which generates a listing of all BASIC program variables which reside in the VARS area of memory. This program also resides in the printer buffer area when it is loaded with the command PRINT #4: LOAD”VARPRT.C1 “CODE. After listing a normal BASIC program RAND USR 23296 on my printer, I use the command RAND USR 23296 to activate the variables search routine which prints out the name and type of all variables which have been stored in the VARS area when the program has been run. This utility AERCO assumes that an AERCO type printer interface at port 127 (7FH) exists. If your printer port number is different, then it will be necessary to patch 3 locations (23522, 23529, and 23531) with the correct port address prior to running have it. I have found this utility to be useful for debugging programs to find out if certain areas of the program have not been accessed during the RUN sequence, since the VARS area will contain only those variables which have been encountered during execution of the program. This utility code is also useful in determining whether or not a variable name has been used already when you are patching a long BASIC program.
I hope that introducing a practical program which makes use of the heretofor largely ignored high resolution color mode will create continued interest in the TS2068 computer capabilities.
BASIC Listing
5 REM THIS PROGRAM GENERATES A HIGH RESOLUTION COLOR PALLET AT THE LOWER RIGHT CORNER OF THE SCREEN AND THEN ALLOWS DRAWING OF SELECTED COLORS AND IT HAS FILE SAVING CAPABILITY. "PALLET.B1" REV. 7, DECEMBER 30, 1992, BY C.G.BOTHNER
8 POKE 23730,24: POKE 23731,247: REM SET RAMTOP
10 LOAD "HIRESC"CODE : RANDOMIZE USR 23296
19 REM GENERATE PALLET DISPLAY
20 LET B=0: LET C=28703: LET D=0: LET COL1=9: LET COL2=9: LET S=0
25 ON ERR GO TO 9000
30 FOR K=224 TO 0 STEP -32
40 FOR I=C TO C+1536 STEP 512
50 FOR J=I TO I+K STEP 32
60 POKE J,B: NEXT J: NEXT I
70 LET C=C+31: LET B=B+9
80 NEXT K
90 LET B=0: LET C=28959
100 FOR K=0 TO 7
110 FOR I=C TO C+1536 STEP 512
120 FOR J=I TO I+K
130 POKE J,B: NEXT J: NEXT I
140 LET C=C+31: LET B=B+9
150 NEXT K: OUT 245,7: OUT 246,0
155 GO SUB 3000: REM MARK DISK ACCESS AREA
160 LET X=219: LET Y=55: REM CURSOR START LOCATION
170 GO SUB 1000: REM GET ATTR. BYTE ADDR.
190 GO SUB 5000: REM DETERMINE WHETHER PAPER OR INK CHANGES
210 IF P=0 THEN GO TO 250
220 LET CT1=INT (COLEV/8)*8: REM FLASH BLACK INK
230 LET CT2=INT (COLOD/8)*8
240 GO TO 270
250 LET CT1=((COLEV/8)-INT (COLEV/8))*8: REM BLACK PAPER
260 LET CT2=((COLOD/8)-INT (COLOD/8))*8
270 POKE ADDR,CT1: POKE (ADDR+256),CT2
280 IF P=0 THEN GO TO 320
290 LET CT1=INT (COLEV/8)*8+7: REM FLASH WHITE INK
300 LET CT2=INT (COLOD/8)*8+7
310 GO TO 340
320 LET CT1=((COLEV/8)-INT (COLEV/8))*8+56: REM WHITE PAPER
330 LET CT2=((COLOD/8)-INT (COLOD/8))*8+56
340 POKE ADDR,CT1: POKE (ADDR+256),CT2
350 POKE ADDR,COLEV: POKE (ADDR+256),COLOD: REM FLASH ORIGINAL COLORS
360 IF STICK (2,1)<>0 THEN GO SUB 2000: IF S=2 THEN GO TO 9000
370 LET Z= STICK (1,1)
380 IF Z=0 THEN GO TO 170
390 IF Z=1 THEN LET Y=Y+2
400 IF Z=2 THEN LET Y=Y-2
410 IF Z=4 THEN LET X=X-4
420 IF Z=8 THEN LET X=X+4
430 IF Z=5 THEN LET X=X-4: LET Y=Y+2
440 IF Z=6 THEN LET X=X-4: LET Y=Y-2
450 IF Z=9 THEN LET X=X+4: LET Y=Y+2
460 IF Z=10 THEN LET X=X+4: LET Y=Y-2
470 IF X>255 THEN LET X=255
480 IF X<0 THEN LET X=1
490 IF Y>191 THEN LET Y=191
500 IF Y<0 THEN LET Y=1
510 GO SUB 4000
520 IF D=1 THEN GO SUB 1000: GO SUB 5000: GO SUB 2140
530 GO TO 170
999 REM GET ATTR. BYTE ADDRESS
1000 LET L=191-Y: LET BLOCK=INT (L/64)
1010 IF BLOCK=0 THEN LET START=24576
1020 IF BLOCK=1 THEN LET START=26624
1030 IF BLOCK=2 THEN LET START=28672
1040 LET LINE=INT (L/8)-(BLOCK*8)
1050 LET SCAN=((L/8)-LINE-(BLOCK*8))*8
1060 LET ADDR=START+(32*LINE)+(256*SCAN)+INT (X/8)
1070 LET COLEV=PEEK ADDR: LET COLOD=PEEK (ADDR+256)
1080 RETURN
1999 REM PROCESS BUTTON PUSHES
2000 IF X>252 AND Y>73 AND Y<78 THEN GO TO 2300: REM DISK ACCESS
2010 IF INT (Y/8)>=8 THEN GO TO 2120
2020 IF X<(192+8*INT (Y/8)) THEN GO TO 2120
2030 REM PICKUP PALLET COLORS
2040 GO SUB 1000: REM GET ATTR. BYTE ADDR.
2050 LET COL1=PEEK ADDR: LET COL2=PEEK (ADDR+256)
2060 FOR I=28761 TO 30297 STEP 512
2070 POKE I,COL1: NEXT I
2080 FOR I=29017 TO 30553 STEP 512
2090 POKE I,COL2: NEXT I
2100 LET COL1=INT (COL1/8): LET COL2=INT (COL2/8)
2110 LET S=1: LET D=0: RETURN
2120 IF D=1 THEN LET D=0: GO TO 2122
2121 IF D=0 THEN LET D=1: GO TO 2140
2122 IF STICK (2,1)<>0 THEN GO TO 2122
2124 RETURN
2130 REM PLACE NEW COLORS ON SCREEN
2140 IF P=0 THEN GO TO 2180
2150 LET CT1=INT (COLEV/8)*8+COL1
2160 LET CT2=INT (COLOD/8)*8+COL2
2170 GO TO 2200
2180 LET CT1=((COLEV/8)-INT (COLEV/8))*8+8*COL1
2190 LET CT2=((COLOD/8)-INT (COLOD/8))*8+8*COL2
2200 POKE ADDR,CT1: POKE (ADDR+256),CT2
2220 IF STICK (2,1)<>0 THEN GO TO 2220
2230 RETURN
2300 RANDOMIZE USR 23366: REM SAVE LOWER PART OF SCREEN ATTR.
2310 IF S=0 THEN GO TO 2370
2320 INPUT "SAVE FILE NAME(6 CHAR.MAX)?";A$
2325 IF A$="NOFILE" OR A$="nofile" THEN GO TO 2360
2330 LET B$=A$
2340 RANDOMIZE USR 23343: REM RESTORE SCREENS
2350 SAVE B$ CODE 24576,6144
2360 LET S=2: RETURN
2370 INPUT "INPUT FILE NAME(6 CHAR.)?";A$
2380 LET B$=A$
2390 LOAD B$ CODE
2400 RANDOMIZE USR 23427: REM RESTORE PRIMARY DISPLAY FILE
2410 RETURN
2999 REM MARK DISK ACCESS TARGET AREA
3000 FOR I=27359 TO 28127 STEP 256
3010 POKE I,57: NEXT I: REM MARK IN WHITE
3020 RETURN
3999 REM TURN OFF PAINTING IF IN PALLET AREA OR DISK ACCESS AREA
4000 IF X>251 AND Y>73 AND Y<78 THEN LET D=0
4010 IF INT (Y/8)>=8 THEN GO TO 4030
4020 IF X>=(192+8*INT (Y/8)) THEN LET D=0
4030 RETURN
4999 REM DETERMINE IF PAPER OR INK IS CHANGED
5000 LET X1=INT (X/4)/2: LET P=0
5010 IF X1=INT X1 THEN LET P=1: REM 0=PAPER,1=INK
5020 RETURN
8999 REM EXIT ROUTINE
9000 ON ERR RESET
9010 RANDOMIZE USR 23406: REM RETURN TO NORMAL VIDEO MODE
9020 STOP
HIRES Listing
ORG $5B00
ENTR: DI ; disable ints.
PUSH BC ; save registers
PUSH HL
PUSH DE
LD A,80H ; set up for XROM access
OUT (0FFH),A
LD A,01H ; enable XROM
OUT (0F4H),A
LD A,02H ; hi-res color mode
CALL 0E8EH ; CHNGVID in XROM
XOR A ; clear A
OUT (0F4H),A ; enable HOME ROM
LD A,09H ; set up for blue ink,blue paper
LD HL,6000H ; start of display file 2
LD BC,1800H ; 6144 bytes in file
CALL STOR ; load attribute file
AA: LD A,0F0H ; ink bixel on left,paper on right
BB: LD HL,4000H ; start of display file 1
LD BC,1800H ; 6144 bytes in file
CC: CALL STOR ; load primary display file
POP DE ; restore regs.
POP HL
POP BC
EI ; enable ints.
RET ; done
RSTR: DI ; disable ints.
PUSH BC ; save regs.
PUSH HL
PUSH DE
LD HL,0EF18H ; start of temporary storage
LD DE,7000H ; lower 1/3 of display file 2
LD BC,0800H ; 2048 bytes to be moved
LDIR ; move them
LD HL,0F718H ; original RAMTOP
LD (5CB2H),HL ; store RAMTOP
JR,AA ; restore display file 1
ENBL: DI ; disable ints.
PUSH BC ; save regs.
PUSH HL
PUSH DE
LD HL,7000H ; lower 1/3 of display file 2
LD DE,0EF17H ; store new RAMTOP
LD (5CB2H),DE
INC DE ; point to start of storage area
LD BC,0800H ; 2048 bytes to be moved
LDIR ; move them
LD A,0FH ; setup for blue paper,white ink
LD HL,7000H ; lower 1/3 of display file 2
LD BC,0800H ; 2048 bytes to be written
CALL STOR ; set up attribute file
XOR A ; clear A
LD HL,5000H ; lower 1/3 of display file 1
LD BC,0800H ; 2048 bytes to be written
JR,CC ; clear part of display file 1
NORM: DI ; disable ints.
PUSH BC ; save regs.
PUSH HL
PUSH DE
LD A,80H ; set up for XROM access
OUT (0FFH),A
LD A,01H ; enable XROM
OUT (0F4H),A
XOR A ; clear A
CALL 0E8EH ; CHNGVID in XROM
XOR A
OUT (0F4H),A ; enable HOME ROM
JR,BB ; clear display file 1
PRIM: DI ; disable ints.
PUSH BC ; save regs.
PUSH HL
PUSH DE
JR,AA ; restore file 1 for hi-res color
TEMP: NOP ; temporary storage
STOR: LD (TEMP),A ; store a byte
DD: LD A,(TEMP) ; get the byte again
LD (HL),A ; store it in the display file
INC HL ; point to next address
DEC BC ; bump counter
LD A,B ; see if done
OR A,C
JR NZ,DD ; continue until done
RET ; done
VARPRT Listing
ORG $5B00
STRT: PUSH HL ; save regs.
PUSH DE
PUSH AF
LD HL,(5C4BH) ; get start of VARS area
AA: LD A,(HL) ; get the character
CP A,80H ; see if end of VARS area
JR Z,BB ; if so, we are done
PUSH AF ; save the character
AND A,1FH ; mask off upper bits
ADD A,40H ; convert to upper case ASCII
CALL PRTO ; send it to printer
POP AF ; get the char. back
AND A,0E0H ; save idendifier bits
CP A,40H ; is it a string variable ?
JR Z,CC ; process it if so
CP A,60H ; is it a single letter numeric ?
JR Z,KK ; process it if so
CP A,80H ; is it a numeric array ?
JR Z,DD ; process it if so
CP A,0A0H ; is it a long name numeric ?
JR Z,LL ; process it if so
CP A,0C0H ; is it a string array ?
JR Z,CC ; process it if so
CP A,0E0H ; is it a FOR/NEXT variable ?
JR Z,NN ; process it if so
RST 08H ; error return if not found
DEFB 01H ; "variable not found" message
BB: POP AF ; restore regs.
POP DE
POP HL
RET ; done
CC: PUSH AF ; save identifier
LD A,24H ; "$" ASCII
CALL PRTO ; send it to printer
POP AF ; get identifier back
DD: INC HL ; get # of bytes to jump
LD E,(HL)
INC HL
LD D,(HL)
ADD HL,DE ; update address
INC HL ; add 1
PUSH HL ; save new address
CP A,40H ; is it a string variable ?
JR NZ,EE ; jump if no match
LD HL,VARM ; address of "VARIABLE" message
JR,II ; go to output routine
EE: CP A,0C0H ; is it a string array ?
JR NZ,FF ; jump if not
LD HL,ARRM ; address of "ARRAY" message
JR,II ; go to output routine
FF: CP A,80H ; is it a numeric array ?
JR Z,GG ; if so, send message
RST 08H ; error return if not found
DEFB 0DBH ; "???????" message
GG: LD HL,ARRM ; address of "ARRAY" message
HH: CALL XSPA ; message out with extra space
JR,JJ ; go to finish sequence
II: CALL MOUT ; output the message
JJ: CALL CRLF ; output a CR and a LF
POP HL ; get new address back
JR,AA ; go to next item in table
KK: INC HL ; update address to next var.
INC HL
INC HL
INC HL
INC HL
INC HL
PUSH HL ; save new address
LD HL,VARM ; address of "VARIABLE" message
JR,HH ; go to output routine
LL: INC HL ; get next character
LD A,(HL)
PUSH AF ; save it
AND A,7FH ; form ASCII character
CP A,5BH ; jump if upper case or numeric
JR C,MM
AND A,5FH ; convert to upper case
MM: CALL PRTO ; send it to printer
POP AF ; get original character back
RLA ; test M.S.bit
JR NC,LL ; continue if not last char.
JR,KK ; update to next address
NN: LD E,13H ; update address to next var.
LD D,00H
ADD HL,DE
PUSH HL ; save new address
LD HL,FORN ; address of "FOR/NEXT" message
JR,II ; output message and return
XSPA: LD A,20H ; spacecharacter
CALL PRTO ; send it to printer
MOUT: LD E,(HL) ; get # of characters
PP: INC HL ; point to next
LD A,(HL) ; get the character
CALL PRTO ; send it to printer
DEC E ; decrement counter
JR NZ,PP ; continue if not done
RET ; done
CRLF: LD A,0DH ; CR character
CALL PRTO ; send it to printer
LD A,0AH ; linefeed character
CALL PRTO ; send it to printer
RET ; done
VARM: DEFB 0BH ; 11 chars. to be sent
DEFB " " ; space character
DEFB " "
DEFB " "
DEFB "V"
DEFB "A"
DEFB "R"
DEFB "I"
DEFB "A"
DEFB "B"
DEFB "L"
DEFB "E"
ARRM: DEFB 08H ; 8 chars. to be sent
DEFB " "
DEFB " "
DEFB " "
DEFB "A"
DEFB "R"
DEFB "R"
DEFB "A"
DEFB "Y"
FORN: DEFB 11H ; 17 chars. to be sent
DEFB " "
DEFB " "
DEFB " "
DEFB " "
DEFB "F"
DEFB "O"
DEFB "R"
DEFB "/"
DEFB "N"
DEFB "E"
DEFB "X"
DEFB "T"
DEFB " "
DEFB "V"
DEFB "A"
DEFB "R"
DEFB "."
PRTO: PUSH AF ; save regs.
PUSH BC
LD C,A ; save the char. in C
QQ: CALL 2009H ; see if BREAK is active
JR C,RR ; jump if not
RST 08H ; error type return
DEFB 14H ; "BREAK" message
RR: IN A,(7FH) ; read printer port
BIT 4,A ; test BUSY bit
JR NZ,QQ ; loop back if busy
LD A,C ; get the char.
OUT (7FH),A ; send it to printer
IN A,(7FH) ; reset the port
POP BC ; restore regs.
POP AF
RET ; done
Products
Media
Image Gallery
Source Code
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.