--- title: "Pallet" type: "article" slug: "pallet" url: "http://localhost/article/pallet/" markdown_url: "http://localhost/article/pallet.md" published_at: "2020-10-27T17:14:56+00:00" modified_at: "2026-07-26T23:16:23+00:00" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "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…" category: - name: "Update Magazine" slug: "update-magazine" taxonomy: "category" url: "http://localhost/category/periodicals/update-magazine/" post_tag: - name: "Best of Timex/Sinclair 2068 Articles and Documents" slug: "ts2068best" taxonomy: "post_tag" url: "http://localhost/tag/ts2068best/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" - name: "Type-in program" slug: "type-in-program" taxonomy: "post_tag" url: "http://localhost/tag/type-in-program/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Charles Bothner" slug: "bothner-charles" taxonomy: "indiv" url: "http://localhost/indiv/bothner-charles/" publication: "Update Magazine" publication_r: id: 10283 title: "Update Magazine" type: "periodical" url: "http://localhost/periodical/update-magazine/" authors: "Charles Bothner" authors_r: - name: "Charles Bothner" slug: "bothner-charles" taxonomy: "indiv" url: "http://localhost/indiv/bothner-charles/" issues_articles: - id: 26488 title: "Update April 1993" type: "issue" url: "http://localhost/issue/ts-2068-up-date-april-1993/" pages: "3-14" pubdate: "April 1993" archive_link: false volumeissue: "vn" --- # Pallet After reading your article on “[TS2068 Video Bells and Whistles](http://localhost/article/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 ```