--- title: "FUDGE" id: 64542 type: "computer_media" slug: "fudge" url: "http://localhost/computer_media/fudge/" markdown_url: "http://localhost/computer_media/fudge.md" published_at: "2026-03-02T02:18:47+00:00" modified_at: "2026-03-30T21:42:48+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/03/SCR-20260301-slrx.png" excerpt: "FUDGE is a complete joystick-driven UDG editor with pull-down menus, pixel grid editing, flip, rotate, shift, animate, and tape save/load for all 21 user-defined graphics." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - 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: "Ryan Gray" slug: "ryan-gray" taxonomy: "indiv" url: "http://localhost/indiv/ryan-gray/" genre: - name: "User Defined Graphics" slug: "user-defined-graphics" taxonomy: "genre" url: "http://localhost/type/user-defined-graphics/" media_contents: - id: 60550 title: "Fort Worth TS2068 Club Library Tape" type: "computer_media" url: "http://localhost/computer_media/fort-worth-ts2068-club-library-tape/" media_type: "Program" programmers: - name: "Ryan Gray" slug: "ryan-gray" taxonomy: "indiv" url: "http://localhost/indiv/ryan-gray/" download_url: "https://archive.org/download/timex-sinclair-software-archive/FUDGE%20%281984%29%28Gray%2C%20Ryan%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "1984" images: - url: "http://localhost/wp-content/uploads/2026/03/SCR-20260301-slrx.png" media_type_tags: "User Defined Graphics" --- # FUDGE FUDGE (Friendly User Defined Graphics Editor) is a full-featured UDG (User Defined Graphics) editor for all 21 UDG characters (a–u). The program provides a joystick-driven graphical interface with pull-down menus for FILE, EDIT, PRINT, and TRICKS operations, allowing the user to design characters on an 8×8 pixel grid using an on-screen cursor. Editing operations include pixel-by-pixel toggle with drag support, invert, flip vertical, flip horizontal, rotate 90°, and cyclic shift in all four directions, plus animation preview. UDG data can be saved and loaded from tape using SAVE/LOAD CODE at USR “a” for 21×8 bytes, and decimal or hexadecimal row data can also be entered manually. The program stores each character’s working state in the string array `a$(8,8)` using block graphic characters, and uses `POKE 23675` to toggle between lower and upper-screen printing. Two custom UDG bytes are initialised at startup via DATA lines to create a cursor sprite stored as UDG “a”. *** ## Program Structure The program is divided into clearly labelled functional blocks, with high-numbered subroutines forming the menu and cursor system and lower-numbered routines handling individual editing operations. | Line range | Function | | --- | --- | | 1–4 | Initialisation: CLEAR, UDG cursor sprite setup via DATA | | 9–15 | Welcome screen, joystick wait, initial cursor placement | | 22–32 | Main loop: draw UDG palette, call cursor/menu handler | | 100–146 | Grid editor: pixel toggle, drag-fill, TRICKS menu dispatch | | 150–175 | Invert operation | | 200–235 | Flip vertical | | 250–295 | Flip horizontal | | 300–320 | Rotate 90° | | 350–385 | Shift (cyclic in all four directions) | | 400–445 | Animate: cycle through a user-typed string of UDGs | | 500–552 | Shift primitives: up, down, left, right | | 600–740 | Cancel / Finish edit, restore display | | 800–830 | Read UDG bytes into `a$(8,8)` array | | 9000–9003 | Screen setup, decorative PLOT/DRAW border | | 9100–9102 | Joystick cursor movement subroutine | | 9200–9300 | FILE pull-down menu | | 9400–9470 | FILE: load/save UDGs, quit | | 9500–9620 | EDIT pull-down: grid edit, enter decimal/hex, copy, switch | | 9650–9760 | Copy and Switch UDG operations | | 9800–9897 | PRINT pull-down: decimal list, test chars, big block, animate | | 9900–9960 | TRICKS pull-down: invert, flip, rotate, shift dispatch | ## Cursor and Display System The joystick cursor is a single-character sprite stored in `i$` (initially UDG “b”). Movement is handled entirely in subroutine `9100`–`9102`, which reads `STICK(1,1)`, updates row `r` and column `c`, erases the old cursor position and redraws it at the new position in a single compound `PRINT` statement using `OVER 1`, `PAPER 8`, `INK 8`, `FLASH 8`, and `BRIGHT 8` — the value 8 being the “transparent” attribute that leaves the background colour unchanged. System variable address `23675` (ATTR P / the lower-screen print flag area) is POKEd to 72 before attribute-sensitive printing and restored to 88 afterwards. This switches the default print position between upper and lower screen to prevent attribute bleed across screen sections. ## Pull-Down Menu Implementation Each menu (FILE at column 3, EDIT at column 9, PRINT at column 15, TRICKS at column 22) is drawn with `PLOT`/`DRAW` borders and managed by a polling loop. The currently highlighted item is indicated by `OVER 1; "█████..."` printed over the menu text, creating an XOR highlight effect. The cursor-is-stationary flag `f` is set when the joystick reports no horizontal movement (`s=0`, `s=4`, or `s=8`), and `GO TO 9x02+(2 AND f=1)` skips re-rendering unchanged state — a compact branch optimisation. TRICKS menu dispatch at line `9955` uses the expression `GO TO r*50+50`: when the cursor row is 2–6, this produces targets 150, 200, 250, 300, 350 — exactly the line numbers of the invert, flip-vert, flip-horiz, rotate, and shift subroutines respectively. This is an elegant computed-GOTO idiom. ## UDG Array and Pixel Representation The subroutine at line `800` reads each UDG’s 8 bytes from memory via `PEEK (USR c$+z)` and decomposes each byte into 8 bits by successive subtraction of powers of two (128, 64, 32, …), storing “█” or ” ” into a `DIM a$(8,8)` string array. A parallel numeric array `DIM q(8)` caches the original byte values, which allows the cancel operation (line `600`) to restore the UDG intact by POKEing back the saved values. The flip-horizontal operation (lines `250`–`295`) reverses each row of `a$` in place, then reconstructs byte values by scanning each row for “█” characters and accumulating powers of two starting from 128. The rotate operation (lines `300`–`320`) uses a second 8×8 string array `b$`, mapping `b$(y, 9-z) = a$(z, y)` for a 90° clockwise rotation, then falls through into the same reconstruction code at line `270`. ## Hexadecimal Input Parser The “Enter Decimal” function (lines `9566`–`9594`) also accepts hexadecimal values prefixed with `$`. The parser at lines `9584`–`9586` manually converts each hex digit: it first normalises lowercase to uppercase, then uses the expression `(CODE d$(n)-48 AND d$(n)<="9") + (CODE d$(n)-55 AND d$(n)>="A")`. This exploits the fact that `AND` in Sinclair BASIC returns its left operand if the right side is non-zero, otherwise 0 — a standard boolean-masking idiom used here for digit classification without IF statements. ## Tape Save/Load UDGs are saved and loaded as a raw CODE block: `SAVE f$ CODE USR "a", 21*8` and `LOAD f$ CODE USR "a", 21*8` (lines `9466`, `9486`). The base address `USR "a"` is the start of the UDG table, and `21*8 = 168` bytes covers all 21 standard UDG characters (a–u). After a load, the program restarts via `RUN 9` to redraw the display and re-initialise the cursor without repeating the UDG sprite DATA initialisation at line 2. ## Key BASIC Idioms Summary - `OVER 1` XOR cursor rendering for flicker-free sprite movement - `PAPER 8 / INK 8 / FLASH 8 / BRIGHT 8` transparent attributes - `x AND condition` as inline conditional expression (Boolean masking) - `GO TO r*50+50` computed GOTO for menu dispatch - `SCREEN$ (r,c)` used to identify which UDG the cursor is over, reading the character from screen memory - `USR c$` to compute UDG address from a single-character string variable - `POKE 23675, 72/88` to switch upper/lower screen print target ## Source Code ``` 1 REM RESET by Ryan Gray, 8/24/84; ALL RIGHTS RESERVED 2 RESTORE : CLEAR 65351: POKE 23675,72: FOR a=0 TO 15: READ x: POKE USR "a"+a,x: NEXT a: POKE 23675,88 3 DATA 6,12,42,127,126,126,127,62 4 DATA 0,32,48,56,60,56,44,6 9 DIM i$(1): LET i$="\b" 10 GO SUB 9000 11 PRINT AT 0,8;"WELCOME TO FUDGE" 12 POKE 23675,72: LET r=10: LET c=15: PRINT AT r,c; OVER 1; PAPER 8; INK 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88 13 PRINT #0;" MOVE THE JOYSTICK TO BEGIN" 14 IF STICK(1,1)=0 AND STICK(2,1)=0 THEN GO TO 14 15 INPUT "" 22 PRINT AT 0,3;"FILE EDIT PRINT " 23 PRINT AT 6,0; PAPER 4;" \a\b\c\d\e\f\g"'" abcdefg"''" \h\i\j\k\l\m\n"'" hijklmn"''" \o\p\q\r\s\t\u"'" opqrstu" 30 GO SUB 9100 31 IF STICK(2,1)=1 AND r=0 THEN GO SUB 9200 32 GO TO 30 99 REM EDIT 100 PRINT AT 8,20; PAPER 7; INK 0;" 01234567 ";AT 17,20;" ";: POKE 23675,72: PRINT PAPER 7; INK 2;"\a": POKE 23675,88: FOR a=9 TO 16: PRINT AT a,20; PAPER 7; INK 0;a-9; PAPER 4; INK 7;" █": NEXT a 101 PRINT AT 18,1; PAPER 0; INK 7;"CANCEL": BEEP .1,0: PRINT #0;"SELECT CHARACTER" 102 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 102 103 IF r=18 AND c>0 AND c<7 THEN PRINT AT 18,1; PAPER 0; INK 7; OVER 1;"CANCEL": INPUT "": GO TO 700 104 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: LET c$=SCREEN$ (r,c): IF c$<"a" OR c$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: GO TO 102 105 PRINT AT r,c; PAPER 4; INK 0; OVER 1; FLASH 1;" ": POKE 23675,88: LET i$="+": BEEP .1,0: INPUT "": GO SUB 800 106 LET c$=CHR$ (CODE c$+47) 107 FOR z=1 TO 8: PRINT AT 8+z,21; PAPER 4; INK 0;a$(z): NEXT z: PRINT AT 10,16; PAPER 4;c$ 108 PRINT AT 0,22;"TRICKS" 110 PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$ 115 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 115 116 IF r=18 AND c>0 AND c<7 THEN GO TO 600 117 IF r=0 AND c>21 AND c<28 THEN GO SUB 9900 120 IF r=17 AND c=29 THEN BEEP .05,10: BEEP .05,10: GO TO 700 121 IF c<21 OR c>28 OR r<9 OR r>16 THEN GO TO 115 125 IF a$(r-8,c-20)=" " THEN LET fl=1: LET a$(r-8,c-20)="█": PRINT AT r,c; PAPER 4; INK 0; OVER 1;"█": POKE USR c$+r-9,PEEK (USR c$+r-9)+2^(7-(c-21)): GO TO 130 126 IF a$(r-8,c-20)="█" THEN LET fl=0: LET a$(r-8,c-20)=" ": PRINT AT r,c; PAPER 4; INK 0; OVER 1;"█": POKE USR c$+r-9,PEEK (USR c$+r-9)-2^(7-(c-21)) 130 BEEP .01,0: PRINT AT 10,16; PAPER 4;c$ 131 IF STICK(2,1)=1 THEN GO TO 140 135 GO TO 115 140 GO SUB 9100: IF r<9 OR r>16 OR c<21 OR c>28 THEN GO TO 115 141 BEEP .01,0 142 IF fl=1 THEN POKE USR c$+r-9,PEEK (USR c$+r-9)+(2^(7-(c-21)) AND a$(r-8,c-20)=" ") 143 IF fl=1 THEN LET a$(r-8,c-20)="█": PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$: PRINT AT r,c; INK 0; PAPER 4;"█";AT r,c; OVER 1; INK 8; PAPER 8;i$: GO TO 146 144 IF fl=0 THEN POKE USR c$+r-9,PEEK (USR c$+r-9)-(2^(7-(c-21)) AND a$(r-8,c-20)="█") 145 IF fl=0 THEN LET a$(r-8,c-20)=" ": PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$: PRINT AT r,c; INK 0; PAPER 4;" ";AT r,c; OVER 1; INK 8; PAPER 8;i$ 146 PRINT AT 10,16; PAPER 4;c$: GO TO 131 150 REM invert 151 BEEP .05,0 152 PRINT AT 10,16; INK 0; PAPER 4; INVERSE 1;c$;AT 10,16;: LET ad=PEEK 23684+256*PEEK 23685 155 FOR z=0 TO 7: POKE USR c$+z,PEEK (ad+256*z): NEXT z 160 GO SUB 800 170 FOR z=1 TO 8: PRINT AT 8+z,21; INK 0; PAPER 4;a$(z): NEXT z 175 BEEP .05,0: BEEP .05,0: RETURN 200 REM flip vert 201 BEEP .05,0 205 DIM q(8) 210 FOR z=0 TO 7: LET q(z+1)=PEEK (USR c$+z): NEXT z 215 FOR z=7 TO 0 STEP -1: POKE USR c$+z,q(8-z): NEXT z 220 PRINT AT 10,16; PAPER 4;c$ 225 GO SUB 800: FOR z=1 TO 8: PRINT AT 8+z,21; INK 0; PAPER 4;a$(z): NEXT z 230 BEEP .05,0: BEEP .05,0 235 RETURN 250 REM flip horiz 251 PRINT #0;"PLEASE WAIT": BEEP .05,0: GO SUB 800 255 FOR z=1 TO 8: LET z$=a$(z) 260 FOR y=1 TO 8: LET a$(z,y)=z$(9-y): NEXT y 265 NEXT z: DIM q(8) 270 FOR z=1 TO 8: LET w=128: FOR y=1 TO 8 275 IF a$(z,y)="█" THEN LET q(z)=q(z)+w 276 LET w=w/2: NEXT y: NEXT z 280 FOR z=0 TO 7: POKE USR c$+z,q(z+1): NEXT z 285 PRINT AT 10,16; PAPER 4;c$ 290 FOR z=1 TO 8: PRINT AT 8+z,21; PAPER 4; INK 0;a$(z): NEXT z 295 BEEP .05,0: BEEP .05,0: INPUT "": RETURN 300 REM rotate 301 PRINT #0;"PLEASE WAIT": BEEP .05,0: GO SUB 800 302 DIM b$(8,8) 305 FOR z=1 TO 8: FOR y=1 TO 8 310 LET b$(y,9-z)=a$(z,y): NEXT y: NEXT z 315 FOR z=1 TO 8: LET a$(z)=b$(z): NEXT z 320 DIM q(8): GO TO 270 350 REM shift 351 BEEP .05,0: GO SUB 800 352 PRINT AT 18,1; PAPER 4;"USE JOYSTICK TO MOVE SHAPE";AT 19,1;"PRESS BUTTON TO FINISH" 355 IF STICK(2,1)=1 THEN BEEP .05,0: PRINT AT 18,1; PAPER 4;" ";AT 19,1;" ";AT 18,1; INK 7; PAPER 0;"CANCEL";#0;"PLEASE WAIT": DIM q(8): GO TO 270 360 LET s=STICK(1,1): IF s=1 OR s=9 OR s=5 THEN GO SUB 500 365 IF s=2 OR s=10 OR s=6 THEN GO SUB 510 370 IF s=4 OR s=5 OR s=6 THEN GO SUB 520 375 IF s=8 OR s=9 OR s=10 THEN GO SUB 550 380 FOR z=1 TO 8: PRINT AT 8+z,21; INK 0; PAPER 4;a$(z): NEXT z 385 GO TO 355 400 REM animate 401 PRINT AT 18,0; PAPER 4;"TYPE IN THE CHARACTERS FOR ANIMATION (ENTER ONLY TO CANCEL)" 410 INPUT Z$ 411 PRINT AT 18,0; PAPER 4;" " 412 IF Z$="" THEN RETURN 413 INPUT "PAUSE BETWEEN CHARACTERS:";P: IF P=0 THEN GO TO 412 414 PRINT #0;"PRESS BUTTON TO TERMINATE" 415 FOR Z=1 TO LEN Z$ 420 PRINT AT 10,16; PAPER 4;Z$(z) 425 PAUSE P 430 NEXT Z: IF STICK(2,1)=0 THEN GO TO 415 440 PRINT AT 10,16; PAPER 4;" ": INPUT "": BEEP .05,0 445 RETURN 500 REM up 501 LET z$=a$(1): FOR z=1 TO 7 502 LET a$(z)=a$(z+1): NEXT z 503 LET a$(8)=z$ 504 RETURN 510 REM down 511 LET z$=a$(8): FOR z=8 TO 2 STEP -1 512 LET a$(z)=a$(z-1): NEXT z 513 LET a$(1)=z$ 514 RETURN 520 REM left 521 FOR z=1 TO 8: LET a$(z)=a$(z,2 TO )+a$(z,1): NEXT z 522 RETURN 550 REM right 551 FOR z=1 TO 8: LET a$(z)=a$(z,8)+a$(z, TO 7): NEXT z 552 RETURN 599 RETURN 600 REM cancel 610 BEEP .1,10 620 FOR z=0 TO 7: POKE USR c$+z,q(z+1): NEXT z 700 REM finish 701 PRINT AT 0,22;" ";AT 18,1; PAPER 4;" " 702 PRINT AT 6,0; PAPER 4;" \a\b\c\d\e\f\g"'" abcdefg"''" \h\i\j\k\l\m\n"'" hijklmn"''" \o\p\q\r\s\t\u"'" opqrstu" 710 PRINT AT 10,16; PAPER 4;" " 720 FOR z=8 TO 17: PRINT AT z,20; PAPER 4;" ": NEXT z 730 LET i$="\b": POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88 740 RETURN 799 STOP 800 REM read c$ into array 810 DIM a$(8,8): DIM q(8) 820 FOR z=0 TO 7: LET x=PEEK (USR c$+z): LET q(z+1)=x: IF x>127 THEN LET a$(z+1,1)="█": LET x=x-128 821 IF x>63 THEN LET a$(z+1,2)="█": LET x=x-64 822 IF x>31 THEN LET a$(z+1,3)="█": LET x=x-32 823 IF x>15 THEN LET a$(z+1,4)="█": LET x=x-16 824 IF x>7 THEN LET a$(z+1,5)="█": LET x=x-8 825 IF x>3 THEN LET a$(z+1,6)="█": LET x=x-4 826 IF x>1 THEN LET a$(z+1,7)="█": LET x=x-2 827 IF x>0 THEN LET a$(z+1,8)="█" 830 NEXT z: RETURN 900 REM exit edit 9000 POKE 23675,72: INK 0: PAPER 4: BORDER 0: CLS : PAPER 7: PRINT AT 0,0;" \a ________________________________" 9001 PLOT 4,175: DRAW -4,0: DRAW 0,-1: DRAW 2,0: DRAW -1,-1: DRAW -1,0: DRAW 0,-2: PLOT 0,4: DRAW 0,-4: DRAW 1,0: DRAW 0,2: DRAW 1,-1: DRAW 0,-1: DRAW 2,0 9002 PLOT 251,175: DRAW 4,0: DRAW 0,-1: DRAW -2,0: DRAW 1,-1: DRAW 1,0: DRAW 0,-2: PLOT 251,0: DRAW 4,0: DRAW 0,1: DRAW -2,0: DRAW 1,1: DRAW 1,0: DRAW 0,2 9003 POKE 23675,88: RETURN 9100 POKE 23675,72 9101 LET xr=r: LET xc=c: LET s=STICK(1,1): LET r=r+((s=2 OR s=10 OR s=6) AND r<21)-((s=1 OR s=9 OR s=5) AND r>0): LET c=c+((s=8 OR s=9 OR s=10) AND c<31)-((s=4 OR s=5 OR s=6) AND c>0): PRINT AT xr,xc; PAPER 8; FLASH 8; INK 8; BRIGHT 8; OVER 1;i$;AT r,c;i$ 9102 POKE 23675,88: RETURN 9200 REM pull-down 9201 IF c<1 OR c>26 OR STICK(2,1)=0 THEN RETURN 9202 IF c=1 THEN PRINT AT 0,1; OVER 1;"█";AT 2,0;" ABOUT FUDGE ": PLOT 0,159: DRAW 0,-8: DRAW 13*8-1,0: DRAW 0,8: GO TO 9221 9203 IF c>2 AND c<7 THEN GO TO 9400 9204 IF C>8 AND c<13 THEN GO TO 9500 9205 IF c>14 AND c<20 THEN GO TO 9800 9220 RETURN 9221 IF c<1 OR c>11 OR r<>2 THEN PRINT AT 2,1;"ABOUT FUDGE" 9222 IF c>0 AND c<12 AND r=2 THEN POKE 23675,72: PRINT AT r,c; OVER 1;i$; OVER 0;AT 2,1; INVERSE 1;"ABOUT FUDGE"; INVERSE 0; OVER 1;AT r,c;i$: POKE 23675,88 9230 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9250 9235 GO TO 9221 9250 IF r<>2 OR c<1 OR c>11 THEN GO TO 9300 9260 GO SUB 9300: POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$: POKE 23675,88 9265 POKE 23675,72: PRINT AT r,c; PAPER 8; INK 8; BRIGHT 8; FLASH 8; OVER 1;i$: POKE 23675,88 9270 PRINT AT 14,1; INK 1; PAPER 5;"▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜";AT 15,1;"▌Friendly ▐";AT 16,1;"▌User OK▐";AT 17,1;"▌Defined ▐";AT 18,1;"▌Graphics ▐";AT 19,1;"▌Editor ▐" 9271 PRINT AT 20,1; INK 1; PAPER 5;"▌ by Ryan Gray▐";AT 21,1;"▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟" 9273 GO SUB 9100: IF STICK(2,1)=1 AND r=16 AND c>13 AND c<16 THEN POKE 23675,72: PRINT AT r,c; INK 8; PAPER 8; OVER 1;i$: GO TO 9275: POKE 23675,88 9274 GO TO 9273 9275 FOR z=14 TO 21: PRINT AT z,1; INK 0; PAPER 4;" ": NEXT z 9276 POKE 23675,72: PRINT AT r,c; OVER 1; PAPER 8; INK 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: RETURN 9300 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$;AT 0,1;"█"; OVER 0;AT 2,0; PAPER 4; INK 0;" ";AT 3,0;" ";AT r,c; OVER 1; INK 8; PAPER 8;i$: POKE 23675,88: RETURN 9400 REM FILE 9401 PRINT AT 2,2;" LOAD UDG's ";AT 3,2;" SAVE UDG's ";AT 4,2;" QUIT ";AT 5,2;AT 0,3; OVER 1;"████": PLOT 16,159: DRAW 0,-24: DRAW 12*8-1,0: DRAW 0,24 9402 LET f=0: IF c<3 OR c>12 OR r<2 OR r>4 THEN PRINT AT 2,3;"LOAD UDG's";AT 3,3;"SAVE UDG's";AT 4,3;"QUIT " 9403 IF c>2 AND c<14 AND r>1 AND r<5 THEN PRINT AT r,3; OVER 1;"██████████"; OVER 0;AT 2,3;"LOAD UDG's" AND r<>2;AT 3,3;"SAVE UDG's" AND r<>3;AT 4,3;"QUIT " AND r<>4 9404 LET F=0 9405 GO SUB 9100: IF S=0 OR S=4 OR S=8 THEN LET F=1 9406 IF STICK(2,1)=0 THEN GO TO 9420 9410 GO TO 9402+(2 AND f=1) 9420 IF r>1 AND r<5 AND c>2 AND c<13 THEN GO TO 9450 9430 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$;AT 0,3;"████"; OVER 0;AT 2,2; PAPER 4; INK 0;" ";AT 3,2;" ";AT 4,2;" ";AT 5,2;" ";AT r,c; OVER 1; INK 8; PAPER 8;i$ 9431 POKE 23675,88 9435 RETURN 9450 GO SUB 9430 9455 IF r=2 THEN GO TO 9480 9456 IF r=3 THEN GO TO 9460 9457 PRINT AT 9,3; INK 0; PAPER 5; BRIGHT 1;"▌THANK YOU FOR USING FUDGE▐";AT 8,3;"▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜";AT 10,3;"▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟" 9458 BEEP .1,0: BEEP .5,0: STOP 9460 BEEP .1,10: INPUT "SAVE UDG's AS:";f$: IF f$="" THEN RETURN 9462 IF LEN f$>10 THEN INPUT "10 CHARACTERS OR LESS (ENTER)"; LINE f$: GO TO 9460 9465 PRINT AT 18,1; INVERSE 1;"PREPARE TAPE";AT 19,1;"FOR SAVING ";AT 20,1;"UDG's. " 9466 SAVE f$CODE USR "a",21*8 9467 PRINT AT 18,1; PAPER 4; INK 0;" "'" "'" " 9468 PRINT #0; FLASH 1;" STOP THE TAPE, SAVE DONE. ": BEEP .1,0 9469 IF STICK(1,1)=0 AND STICK(2,1)=0 THEN GO TO 9469 9470 INPUT "": RETURN 9480 PRINT AT 18,1; INVERSE 1;"PREPARE TAPE";AT 19,1;"FOR LOADING ";AT 20,1;"UDG's. " 9482 BEEP .1,0: INPUT "FILE TO LOOK FOR:";f$: IF LEN f$>10 THEN GO TO 9498 9485 PRINT #0;"PRESS PLAY NOW" 9486 PAPER 4: PRINT AT 2,0;: LOAD f$CODE USR "a",21*8: PAPER 7 9498 RUN 9 9500 REM EDIT 9501 PRINT AT 0,9; OVER 1;"████"; OVER 0;AT 2,8;" GRID EDIT ";AT 3,8;" ENTER DECIMAL ";AT 4,8;" COPY ";AT 5,8;" SWITCH ": PLOT 64,159: DRAW 0,-32: DRAW 15*8-1,0: DRAW 0,32 9502 LET f=0: IF c<9 OR c>21 OR r<2 OR r>5 THEN PRINT AT 2,9;"GRID EDIT ";AT 3,9;"ENTER DECIMAL";AT 4,9;"COPY ";AT 5,9;"SWITCH " 9503 IF c>8 AND c<22 AND r>1 AND r<6 THEN PRINT AT r,9; OVER 1;"█████████████"; OVER 0;AT 2,9;"GRID EDIT " AND r<>2;AT 3,9;"ENTER DECIMAL" AND r<>3;AT 4,9;"COPY " AND r<>4;AT 5,9;"SWITCH " AND R<>5 9504 LET F=0 9505 GO SUB 9100: IF S=0 OR S=4 OR S=8 THEN LET F=1 9506 IF STICK(2,1)=0 THEN GO TO 9520 9510 GO TO 9502+(2 AND f=1) 9520 IF r>1 AND r<6 AND c>8 AND c<22 THEN GO TO 9550 9521 PRINT AT 0,9; OVER 1;"████" 9525 POKE 23675,72: PRINT AT R,C; OVER 1; PAPER 8; INK 8;I$: FOR Z=2 TO 6: PRINT AT Z,8; PAPER 4;" ": NEXT Z: PRINT AT R,C; OVER 1; INK 8; PAPER 8;I$: POKE 23675,88 9530 RETURN 9550 GO SUB 9521 9555 IF R=2 THEN GO TO 100 9560 IF R=4 THEN GO TO 9650 9565 IF R=5 THEN GO TO 9700 9566 REM ENTER DECIMAL 9567 BEEP .1,0: PRINT AT 18,1; PAPER 0; INK 7;"CANCEL"; PAPER 0; INK 7;#0;"SELECT CHARACTER" 9568 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9568 9569 IF r=18 AND c>0 AND c<7 THEN BEEP .1,5: INPUT "": GO TO 9596 9570 POKE 23675,72: PRINT AT R,C; OVER 1; PAPER 8; INK 8; FLASH 8; BRIGHT 8;I$ 9572 LET C$=SCREEN$ (R,C): IF C$<"a" OR c$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: GO TO 9568 9574 PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: INPUT "": BEEP .1,0 9575 PRINT AT 18,1; PAPER 4;"HEX DATA PRECEEDED BY A '$'" 9580 FOR Z=0 TO 7 9581 INPUT "DATA FOR ROW ";STR$ Z;":";D$: IF D$="" THEN GO TO 9581 9582 IF D$(1)="$" AND LEN D$>3 THEN GO TO 9581 9583 IF D$(1)<>"$" THEN GO TO 9590 9584 IF D$(2)>="a" THEN LET d$(2)=CHR$ (CODE d$(2)-32) 9585 IF D$(3)>="a" THEN LET d$(3)=CHR$ (CODE d$(3)-32) 9586 LET d=16*(CODE d$(2)-48 AND d$(2)<="9")+16*(CODE d$(2)-55 AND d$(2)>="A")+(CODE d$(3)-48 AND d$(3)<="9")+(CODE d$(3)-55 AND d$(3)>="A") 9587 GO TO 9592 9590 LET d=VAL d$ 9592 IF d>255 OR d<-255 THEN BEEP .1,-5: GO TO 9581 9594 POKE USR c$+z,d: NEXT z 9596 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88 9600 PRINT AT 6,0; PAPER 4;" \a\b\c\d\e\f\g"'" abcdefg"''" \h\i\j\k\l\m\n"'" hijklmn"''" \o\p\q\r\s\t\u"'" opqrstu" 9610 PRINT AT 18,1; PAPER 4;" " 9615 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88 9620 RETURN 9650 REM COPY 9651 BEEP .1,0: PRINT AT 18,1; INK 7; PAPER 0;"CANCEL";#0;"SELECT CHARACTER" 9652 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9652 9653 IF r=18 AND c>0 AND c<7 THEN PRINT AT 18,1; OVER 1; PAPER 4; INK 0;"CANCEL": INPUT "": BEEP .1,5: RETURN 9655 POKE 23675,72: PRINT AT R,C; OVER 1; PAPER 8; INK 8; FLASH 8; BRIGHT 8;I$ 9658 LET C$=SCREEN$ (R,C): IF C$<"a" OR c$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: GO TO 9652 9660 PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: INPUT "": BEEP .1,0 9665 PRINT #0;"SELECT PLACE FOR COPY" 9670 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9670 9675 POKE 23675,72: PRINT AT R,C; OVER 1; BRIGHT 8; FLASH 8; INK 8; PAPER 8;I$: LET D$=SCREEN$ (R,C): IF D$<"a" OR d$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: GO TO 9670 9676 BEEP .1,0: INPUT "": POKE 23675,88 9677 FOR z=0 TO 7: POKE USR d$+z,PEEK (USR c$+z): NEXT z 9680 PRINT AT 6,0; PAPER 4;" \a\b\c\d\e\f\g"'" abcdefg"''" \h\i\j\k\l\m\n"'" hijklmn"''" \o\p\q\r\s\t\u"'" opqrstu" 9681 PRINT AT 18,1; PAPER 4;" " 9685 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88 9690 RETURN 9700 REM SWITCH 9701 BEEP .1,0: PRINT AT 18,1; PAPER 0; INK 7;"CANCEL";#0;"SELECT FIRST CHARACTER" 9702 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9702 9703 IF r=18 AND c>1 AND c<7 THEN PRINT AT 18,1; OVER 1; INK 0; PAPER 4;"CANCEL": INPUT "": BEEP .1,5: RETURN 9705 POKE 23675,72: PRINT AT R,C; OVER 1; PAPER 8; INK 8; FLASH 8; BRIGHT 8;I$ 9710 LET C$=SCREEN$ (R,C): IF C$<"a" OR c$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: GO TO 9702 9711 PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: INPUT "": BEEP .1,0 9712 PRINT #0;"SELECT SECOND CHARACTER" 9720 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9720 9725 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$ 9730 LET d$=SCREEN$ (r,c): IF d$<"a" OR d$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: GO TO 9720 9735 POKE 23675,88 9740 FOR z=0 TO 7: LET y=PEEK (USR c$+z): POKE USR c$+z,PEEK (USR d$+z): POKE USR d$+z,y: NEXT z 9745 PRINT AT 18,1; PAPER 4;" " 9750 PRINT AT 6,0; PAPER 4;" \a\b\c\d\e\f\g"'" abcdefg"''" \h\i\j\k\l\m\n"'" hijklmn"''" \o\p\q\r\s\t\u"'" opqrstu" 9755 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: BEEP .1,0: INPUT "" 9760 RETURN 9800 REM PRINT 9801 PRINT AT 0,15; OVER 1;"█████"; OVER 0;AT 2,14;" DECIMAL LIST ";AT 3,14;" TEST CHARS. ";AT 4,14;" BIG BLOCK ";AT 5,14;" ANIMATE ": PLOT 112,159: DRAW 0,-32: DRAW 14*8-1,0: DRAW 0,32 9802 LET f=0: IF c<15 OR c>26 OR r<2 OR r>4 THEN PRINT AT 2,15;"DECIMAL LIST";AT 3,15;"TEST CHARS. ";AT 4,15;"BIG BLOCK ";AT 5,15;"ANIMATE " 9803 IF c>14 AND c<26 AND r>1 AND r<6 THEN PRINT AT r,15; OVER 1;"████████████"; OVER 0;AT 2,15;"DECIMAL LIST" AND r<>2;AT 3,15;"TEST CHARS. " AND r<>3;AT 4,15;"BIG BLOCK " AND r<>4;AT 5,15;"ANIMATE " AND r<>5 9804 LET f=0 9805 GO SUB 9100: IF s=0 OR s=4 OR s=8 THEN LET f=1 9806 IF STICK(2,1)=0 THEN GO TO 9820 9810 GO TO 9802+(2 AND f=1) 9815 PRINT AT 0,15; OVER 1;"█████": FOR Z=2 TO 7: PRINT AT Z,14; PAPER 4;" ": NEXT Z 9820 IF r>1 AND r<6 AND c>14 AND c<26 THEN GO TO 9831 9825 POKE 23675,72: PRINT AT R,C; OVER 1; PAPER 8; INK 8;I$: PRINT AT 0,15; OVER 1;"█████": FOR Z=2 TO 6: PRINT AT Z,14; PAPER 4;" ": NEXT Z: PRINT AT R,C; OVER 1; INK 8; PAPER 8;I$: POKE 23675,88 9830 RETURN 9831 GO SUB 9825 9832 IF r=3 THEN GO TO 9855 9833 IF r=2 THEN GO TO 9880 9834 IF r=5 THEN GO TO 400 9836 PRINT AT 18,1; INK 7; PAPER 0;"CANCEL";#0;"SELECT CHARACTER": BEEP .1,0 9837 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9837 9838 IF r=18 AND c>0 AND c<7 THEN PRINT AT 18,1; PAPER 4; INK 0; OVER 1;"CANCEL": GO TO 9850 9839 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$: LET C$=SCREEN$ (R,C): IF C$<"a" OR c$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$: POKE 23675,88: GO TO 9837 9840 INPUT "": PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$: POKE 23675,88: PRINT AT 18,1; PAPER 5; INK 0;"SEND TO PRINTER ALSO? YESNO": BEEP .05,5 9841 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9841 9842 IF r=18 AND c>22 AND c<26 THEN LET pf=1: GO TO 9845 9843 IF r=18 AND c>25 AND c<28 THEN LET pf=0: GO TO 9845 9844 GO TO 9841 9845 PRINT AT 18,1; PAPER 4;" ": GO SUB 800: POKE 23675,72: PRINT AT r,c; OVER 1; PAPER 8; INK 8;i$: POKE 23675,88 9846 PRINT AT 7,18; PAPER 4;"GRAPHICS '";c$;"'": IF pf=1 THEN LPRINT "GRAPHICS '";c$;"'" 9847 FOR z=1 TO 8: PRINT AT 8+z,21; INK 0; PAPER 5;a$(z): IF pf=1 THEN LPRINT TAB 8;a$(z) 9848 NEXT z: PRINT #0;"DONE: PRESS BUTTON TO CONTINUE": BEEP .05,0 9849 IF STICK(2,1)=0 THEN GO TO 9849 9850 BEEP .01,0: INPUT "" 9851 PRINT AT 7,18; PAPER 4;" " 9852 FOR z=9 TO 16: PRINT AT z,21; PAPER 4;" ": NEXT z 9853 RETURN 9855 REM test chars. 9856 LET i=7: LET p=0: PAPER 0: INK 7: BORDER 0: CLS 9857 PRINT AT 9,0;"UP-DOWN: INK COLOR";AT 11,0;"LEFT-RIGHT: PAPER COLOR";AT 13,0;"BUTTON: BEGIN TEST" 9858 PRINT AT 21,0; INK 9;"INK ";i,"PAPER ";p 9859 IF STICK(2,1)=1 THEN GO TO 9870 9860 LET s=STICK(1,1): LET i=i+(s=1 AND i<7)-(s=2 AND i>0): LET p=p+(s=8 AND p<7)-(s=4 AND p>0) 9861 PAPER p: INK i: BORDER p: CLS : GO TO 9857 9870 CLS : PRINT AT 0,1;" TEST CHARACTERS";AT 21,0;"INPUT CHARACTERS LINE BY LINE." 9871 FOR z=1 TO 20: PRINT AT z,0;">": INPUT z$: PRINT AT z,0;z$: NEXT z 9872 INPUT "DONE: PRESS ENTER>";z$ 9875 RUN 9 9880 REM decimal list 9881 PRINT AT 18,1; INK 7; PAPER 0;"CANCEL";#0;"SELECT CHARACTER": BEEP .05,0 9882 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9882 9883 POKE 23675,72: PRINT AT r,c; OVER 1; INK 8; PAPER 8; FLASH 8; BRIGHT 8;i$ 9884 LET c$=SCREEN$ (r,c): IF c$<"a" OR c$>"u" THEN PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$: POKE 23675,88: GO TO 9882 9885 BEEP .05,0: INPUT "": PRINT AT r,c; OVER 1; INK 8; PAPER 8;i$: POKE 23675,88: PRINT AT 18,1; PAPER 5; INK 0;"SEND TO PRINTER ALSO? YESNO" 9886 GO SUB 9100: IF STICK(2,1)=0 THEN GO TO 9886 9887 IF r=18 AND c>22 AND c<26 THEN LET pf=1: GO TO 9890 9888 IF r=18 AND c>25 AND c<28 THEN LET pf=0: GO TO 9890 9889 GO TO 9886 9890 BEEP .05,0: PRINT AT 18,1; PAPER 4;" ": POKE 23675,72: PRINT AT r,c; OVER 1; PAPER 8; INK 8;i$: POKE 23675,88 9891 PRINT AT 7,16; PAPER 4;CHR$ (CODE c$+47);" GRAPHICS '";c$;"'": IF pf=1 THEN LPRINT CHR$ (CODE c$+47);" GRAPHICS '";c$;"'" 9892 FOR z=0 TO 7: PRINT AT 9+z,24; PAPER 4;PEEK (USR c$+z): IF pf=1 THEN LPRINT TAB 11;PEEK (USR c$+z) 9893 NEXT z 9894 PRINT #0;"DONE: PRESS BUTTON TO CONTINUE" 9895 IF STICK(2,1)=0 THEN GO TO 9895 9896 PRINT AT 7,16; PAPER 4;" ": FOR z=9 TO 16: PRINT AT z,24; PAPER 4;" ": NEXT z 9897 BEEP .05,0: INPUT "": RETURN 9900 REM TRICKS 9901 PRINT AT 0,22; OVER 1;"██████"; OVER 0;AT 2,20;" INVERT ";AT 3,20;" FLIP VERT ";AT 4,20;" FLIP HORIZ ";AT 5,20;" ROTATE ";AT 6,20;" SHIFT ": PLOT 160,159: DRAW 0,-40: DRAW 12*8-1,0: DRAW 0,40 9902 LET f=0: IF c<21 OR c>30 OR r<2 OR r>6 THEN PRINT AT 2,21;"INVERT ";AT 3,21;"FLIP VERT ";AT 4,21;"FLIP HORIZ";AT 5,21;"ROTATE ";AT 6,21;"SHIFT " 9903 IF c>20 AND c<31 AND r>1 AND r<7 THEN PRINT AT r,21; OVER 1;"██████████"; OVER 0;AT 2,21;"INVERT " AND r<>2;AT 3,21;"FLIP VERT " AND r<>3;AT 4,21;"FLIP HORIZ" AND r<>4;AT 5,21;"ROTATE " AND r<>5;AT 6,21;"SHIFT " AND R<>6 9904 LET f=0 9905 GO SUB 9100: IF s=0 OR s=4 OR s=8 THEN LET f=1 9906 IF STICK(2,1)=0 THEN GO TO 9920 9910 GO TO 9902+(2 AND f=1) 9920 IF r>1 AND r<7 AND c>21 AND c<31 THEN GO TO 9950 9925 POKE 23675,72: PRINT AT R,C; OVER 1; PAPER 8; INK 8;I$: PRINT AT 0,22; OVER 1;"██████": FOR Z=2 TO 7: PRINT AT Z,20; PAPER 4;" ": NEXT Z: PRINT AT R,C; OVER 1; INK 8; PAPER 8;I$: POKE 23675,88 9930 RETURN 9950 GO SUB 9925 9955 GO TO r*50+50 9998 REM 9999 REM FUDGE © August 24, 1984 by Ryan Gray ```