--- title: "Sinc-Artist v1.3" id: 51772 type: "computer_media" slug: "sinc-artist-v1-3" url: "http://localhost/computer_media/sinc-artist-v1-3/" markdown_url: "http://localhost/computer_media/sinc-artist-v1-3.md" published_at: "2023-08-13T23:14:31+00:00" modified_at: "2026-04-03T13:36:15+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A machine-code drawing suite hidden inside a single REM statement, offering pencil, brush, shapes, flood fill, pattern editing, and adjustable cursor speed from layered menus." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Callisto Software" slug: "callisto-software" taxonomy: "post_tag" url: "http://localhost/tag/callisto-software/" - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Art" slug: "art" taxonomy: "genre" url: "http://localhost/type/art/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Sinc-Artist v1.3 (1984)(Callisto Sofware)(CA)(TS1000)(Cassette).zip" mediadate: "1984" producer_company: - id: 27781 title: "Callisto Software" type: "company" url: "http://localhost/company/callisto-software/" related_products: - id: 27782 title: "SincArtist" type: "product" url: "http://localhost/product/sinc-artist/" - id: 14381 title: "Thrust" type: "product" url: "http://localhost/product/thrust/" - id: 34773 title: "SincArtist HR" type: "product" url: "http://localhost/product/sinc-artist-hr/" media_type_tags: "Art" --- Sinc-Artist v1.3 is a full-featured drawing and painting program that provides pencil, brush, horizontal and vertical marker, line, ray, and shape-drawing tools (circles, rectangles, triangles, and quadrilaterals, each with filled variants), along with pattern editing, transparent and opaque paint flood-fill modes, an inverse tool, and adjustable cursor speed. The program is almost entirely implemented in machine code embedded in the REM statement at line 1; the BASIC bootstrap (lines 3–8) uses PEEK/POKE on system variables 16396–16397 to locate the program area, patches the first byte of the REM payload to 192 (a JP instruction), and then jumps into it via RAND USR 16516. Line 6 conditionally restores that byte and line 7 halts execution when PEEK 16389 equals 127, providing a mechanism to exit cleanly back to BASIC. The menus—Main, Draw, Shape, Goodies, Speed Adjust, and Pattern Editor—are stored as display strings inside the REM block and rendered using block-graphic characters for bordered panels. *** ## Program Analysis ### Program Structure The entire program is only 8 BASIC lines long. The real application — several kilobytes of Z80 machine code — lives in the `REM` statement at line 1. Lines 2–8 form a minimal BASIC bootstrap whose sole job is to locate, patch, and jump into that machine code. | Line | Purpose | | --- | --- | | 1 | `REM` — entire machine-code payload, menu strings, and block-graphic display data | | 2 | Empty `REM` — spacer / version marker | | 3 | `FAST` — switches to fast mode for initialisation | | 4 | Patches byte at `(1 + PEEK 16396 + 256 * PEEK 16397)` to 192 — writes a Z80 `JP` opcode over the first data byte of the REM block | | 5 | `SAVE "SINC-ARTIST 1.3"` — saves the patched program to tape | | 6 | If `PEEK 16389 = 127`, restores that byte to 0 (un-patches), allowing safe return to BASIC | | 7 | If `PEEK 16389 = 127`, `STOP`s — complement to line 6 exit mechanism | | 8 | `RAND USR 16516` — transfers control to the BASIC interpreter’s own entry point, which immediately executes the patched jump in the REM | ### Machine Code Loader Technique System variable addresses 16396 (low byte) and 16397 (high byte) together hold the address of the start of the BASIC program area. Adding 1 to that address gives the offset of the first token byte inside the `REM` statement (past the line-number and length fields). Line 4 writes the value 192 (`0xC0`) there. In the Z80 instruction set, `0xC0` alone is `RET NZ`, but combined with the two address bytes that follow in the REM data it forms a three-byte `JP NZ, addr` or, depending on the intended opcode, the machine code begins executing the full routine from that offset. The effect is that `RAND USR 16516` triggers a chain that lands execution inside the REM payload. System variable 16389 (`MARGIN` / last `K` channel position) being equal to 127 is used as a sentinel — lines 6 and 7 check it to decide whether to undo the patch and stop, providing an orderly exit path without corrupting the saved image. ### Feature Set Decoded from the REM Payload The text fragments visible in the REM block correspond to menu labels and internal routines. The application exposes four nested menu layers: - **Main Menu**: Clear, Save, Load, Print (LPRINT), Banner, Goodies, Draw Menu, Shape Menu - **Draw Menu**: Pencil, Brush, H-Marker, V-Marker, Lines, Rays, Shape Menu, Main Menu, Goodies - **Shape Menu**: Circle, Filled Circle, Rectangle, Filled Rectangle, Triangle, Filled Triangle, Quadrilateral, Filled Quadrilateral, plus navigation back - **Goodies**: Edit Pattern, Transparent Paint, Opaque Paint, Inverse, Cursor Speed, navigation A Speed Adjust sub-screen renders a horizontal bar using block graphics (`█` fill) with *SLOW* and *FAST* labels. A Pattern Editor sub-screen shows a 6×6 grid bordered with `▒` characters and a pattern number readout. ### Use of Block Graphics All menu panels are drawn with ZX81/TS1000 block-graphic characters: vertical bars (`▐`) form the sides, bottom edges use `▄▄▄…▟`, and panel corners use `▛`/`▜` characters. This technique requires no machine-code drawing routine for the UI chrome — the characters are stored as literal data inside the REM and sent directly to the display. ### Key BASIC Idioms - `PEEK 16396 + 256 * PEEK 16397` — standard two-byte address reconstruction from system variable pair, used to locate the program start dynamically so the code works regardless of where BASIC loaded. - `RAND USR 16516` — `RAND` discards its return value, making `USR` a fire-and-forget machine-code call; 16516 is the address of the main BASIC execution loop, re-entered so the interpreter re-reads line 1’s (now patched) REM. - `FAST` at line 3 — disables the display during initialisation to speed up the POKE and SAVE operations. ### Save / Load Mechanism The `SAVE` on line 5 stores the already-patched program. Subsequent loads will therefore have the `JP` opcode already in place, and `RAND USR 16516` at line 8 will jump straight into the machine code without needing to re-patch. This is a common distribution technique: the first run patches and saves; all later runs execute directly. ### Notable Observations - The REM payload contains fragments that decode as BASIC keywords (`GOSUB`, `LPRINT`, `PLOT`, `UNPLOT`, `INKEY$`, `POKE`, `USR`, `COPY`, etc.) — these are tokenised keyword bytes that form part of the machine-code binary, not real BASIC statements. This is a well-known side-effect of storing arbitrary Z80 code in a REM: many byte values coincide with BASIC token codes. - The LPRINT / COPY calls visible in the payload suggest the machine code drives the ZX Printer directly for the “Print” and “Banner” functions. - Mathematical function names (`ACS`, `ASN`, `ATN`, `SQR`, `TAN`, `LN`, `EXP`, `SGN`) appearing throughout the REM are again tokenised bytes whose numeric values happen to fall in the floating-point/trig opcode range — they are data, not calls. - The pattern editor’s 6×6 grid and the speed-adjust bar both suggest the machine code maintains internal state arrays, consistent with the `DIM` tokens visible in the REM fragment (likely encoded array-dimension data structures). ## Source Code ``` 1 REM ## NEXT LPRINT LPRINT 5[;]RND)## GOSUB #▖RND▘#+ GOSUB [K]##▀LN \~~#LN F?LN [:]#)▗#LN GOSUB #LN STEP #CHR$ 1S RAND RETURN▒K PRINT LN \~~##▞ [R]ACS )ACS (5[3]#\,,\,,\,, DIM #INT # ▘\~~ TAN ▘= TAN LN *#####V# #CODE # #▘# ### E£RND▘# \,,) RUN #, RETURN COPYC▞#7<# OR #LN STEP # RETURNNASN ## RETURNYTAB SLOW#LN #####SURE? Y/N COPYLN [:]#)7#LN GOSUB #LN STEP #CHR$ 1 AND \~~# RETURN\,,K POKE LN \~~##▞ [R]ACS )ACS (5C#\,,\,,\,, DIM LN O##▘#LN [,]##▘#LN U##▘#LN COS ##▘#LN [A]##▘#LN G##▘#### ### #CODE # LN [:]#)LN #LN GOSUB #LN STEP #CHR$ 1S RAND RETURN"K PRINT LN \~~#▞ #[R]ACS )ACS (5▙#\,,\,,\,, DIM LN PRINT ####LN ▘####LN #####LN CONT ####LN #####LN *####LN 7####LN J#####▘# ### #CODE # LN [:]#)[X]#LN GOSUB #LN STEP #CHR$ 1S RAND RETURN▒K PRINT LN \~~##▞ [R]ACS )ACS (5 REM #\,,\,,\,, DIM LN ,##CODE #LN G##CODE #LN P##CODE #LN [S]##CODE #LN U##CODE #### #▘# ### YTAN M##MUSR #LN [:]#) SLOW#LN GOSUB #LN ##YACS M##MUSR #TAN + LN [:]#)##LN GOSUB # GOSUB ###E##6S#LN [M]#VAL LN STEP #AT RETURN5ASN ## RETURN8ASN ▐# RETURN#ASN [B]####UR# RETURN ASN ##LN ACS #XMR#LN [M]#LN K#5\~~ \,,#####UR# RETURNEASN ##LN ACS #WMR#LN [M]#LN K###▘\~~ [R] GOSUB PI##### GOSUB ###ES#6##TAN VAL YFM##UR#M##LN FOR #YEM##LN FOR #AT TAN PRINT VAL YFM##LN VAL #YEM##LN VAL #AT LET TAN LN [V]▝##GC SAVE LN [X]▛#TAN E£RND7##, RETURN COPYCOS # RETURN▐C▖7>▐▖ ▗ ▖▐█████████████████████▌▐SLOW FAST▐▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ COPY COPYPATTERN NO.: *▐ ▒▒▒▒▒▒ ▐ ▒ ▒ ▐ ▒ ▒ ▐ ▒ ▒ ▐ ▒ ▒ ▐ ▒▒▒▒▒▒ ▐▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟ COPY COPY ▘ ▘▝▀▖▌▞▛▗▚▐▜▄▙▟█E£RND7U###YJ[)]**ACS ▗ACS ?)5 RETURN C▖;X4 UNPLOT U## RETURNRNDK$#ACS ▗ACS ?#- ;Y▘[R]TAN RTAN RETURN▒S> RETURN#K▖Y /\~~ RETURN[▒]S▝Y█#Y[?][>]#TAN LN ##**# FASTLN [H]#2▘ACS RNDC▝ACS ▀ACS INKEY$ 4▖ACS ▀ACS ▀#[N]#- 5##;# LPRINT #TAN LN ##**# FASTLN [H]#2▘ACS RNDC▝ACS ▀ACS INKEY$ 4▖ACS ▀ACS ▀# INPUT COPY[6]/CHR$ LN ##Y/M##LN SQR #Y M##Y4M##Y[(]M##TAN LN [V]▝ GOSUB ####INKEY$ #ACS #4*ACS #4<▌ACS #45ACS #4▀£/,ACS #C-$/]M## RETURN SAVE C\~~▞▛ GOSUB ###.#[H]#Y M###TAN U##-▒▙M## RETURN[/]C>:C FASTE##) ▘[R] GOSUB ### LPRINT #[H]#Y[(]M##:JTAN U##-▒[>]M## RETURN SAVE C(:▛ FASTE##) ▘;## LPRINT #[H]#Y M###TAN GOSUB ###"#[L]4 CLSTAN LN SQR #LN 9#LN [▒]#ACS #COS ACS #C▛ACS #ATN ##/ GOTO FASTLN FOR #LN *#LN ## LPRINT ACS #ATN ##/ AND LN ##ACS INKEY$ COS LN VAL #TAN LN [▒]#LN [V]▝ACS #""# NEW/ RETURN/4 LIST LN [▒]#LN [V]▝ACS #""# NEW/ RETURN/C LIST TAN FASTLN VAL #LN E#LN FOR #LN E#LN ## LPRINT TAN LN SQR #LN 9# FASTLN FOR # LPRINT ACS #COS ACS #C▛ACS #ATN ##/ REM FASTLN ##LN *#UY#XMY#LN *#UZ#XMZ#LN *#UY#WMY#LN *#UZ#WMZ#LN RUN # LPRINT ACS #ATN ###[1]#LN ##LN E#LN ##LN E#LN ##ACS INKEY$ CODE VAL #UY#XMY#U##XM##LN ##ACS INKEY$ CODE VAL #UZ#XMZ#U##XM##LN ##ACS INKEY$ CODE VAL #UY#WMY#U##WM##LN ##ACS INKEY$ CODE VAL #UZ#WMZ#U##WM##TAN LN VAL #U##XM##LN VAL #U##XM##LN VAL #U##WM##LN VAL #U##WM##TAN LN FOR #U##XM##LN FOR #U##XM##LN FOR #U##WM##LN FOR #U##WM##TAN Y M[6]#LN SQR #LN 9#LN [▒]#ACS #ASN Z#ACS #ATN ##ACS #4 GOTO UPI#M[9]#Y MPI#LN O# GOSUB #Y# GOSUB #[7]#LN 9#LN [▒]#ACS #ASN Z#ACS #ATN ##ACS #4 GOTO LN O#U[6]# RETURN▘C5EY#6RND#E[7]#6Y#U[9]#MPI#LN [2]#LN SQR #EY#6[7]##**#E[7]#6RND#U[9]#MPI#LN [2]#LN SQR ##**#Y▘M[6]##[F]#LN [V]▝ACS #C RAND LN *#TAN LN [▒]#LN [V]▝ACS #C PLOT LN [▒]#LN [V]▝#WC PLOT ACS #COS #[I]# Y M##M##LN SQR #LN 9#LN [▒]#ACS #COS ACS #ATN ##ACS #4 INPUT LN ###M POKE #UPI#M[9]#Y MPI#LN O#EY#6[7]#LN 9#LN [▒]#ACS #COS ACS #ATN ##ACS #4 INPUT EY#6RND#E[7]#6Y#U POKE # RETURN▘C▒Y▛MPI#LN *#U[9]#MPI#U## RETURN▘ASN £#U## RETURN▘ASN >=#LN #####LN 7?LN [>]#LN F?###Y▘M##XM##### Y M##WM#####Y▘M##M#####UY#W RETURN▘4▀MY#UZ#W RETURN▘4▀MZ#URND#W4▀MRND#UINKEY$ #W RETURN▘4▀MINKEY$ #U## RETURN▘C▞LN #####LN 7?LN ##LN F?### Y M##M##LN SQR #LN 9#LN [▒]#ACS #COS ACS #ATN ##ACS #4 INPUT UPI#M[9]#Y MPI#LN O#EY#6##LN 9#LN [▒]#ACS #COS ACS #ATN ##ACS #4 INPUT LN O#EY#6##LN 9#LN [▒]#ACS #COS ACS #ATN ##ACS #4 INPUT LN O#EY#6##U## RETURN▘4ULN 9#LN [▒]#ACS #COS ACS #ATN ##ACS #4 INPUT LN O#EY#6##U[9]#MPI#U## RETURN▘C▞LN PAUSE ####LN 7?LN [D]#LN F?###U[9]#MPI#U## RETURN▘C▞LN [S]####LN 7?LN PLOT #LN F?###Y M##WM#####Y▘M##XM#####Y▘M##M#####LN SQR #LN 9#LN [▒]#ACS #COS ACS #ATN ##ACS #4 INPUT LN ##ACS INKEY$ 4#UY#M[7]#U##M[9]#LN ##ACS INKEY$ TAB ▜#LN *#LN ##UY#XMY# RETURN COPYC\,,U##XM##/ THENU[7]#WMY#CBU[9]#WM##LN ##ACS INKEY$ TAB [O]#LN *#LN ##UY#WMY#C\,,U##WM##/ STEP U[7]#MY#U[9]#M###X#LN [V]▝LN [▒]#ACS #C[,,]ACS #C PAUSE #X#ACS #""LN [V]▝G4 IF E£RND7)[F]#, RETURN COPYC▌#7#LN *#LN ##UZ#XMZ# RETURN COPYC\,,U##XM##/ THENU[7]#WMZ#U[9]#WM##LN ##ACS INKEY$ TAB RND#LN *#LN ##UZ#WMZ#C\,,U##WM##/ STEP U[7]#MZ#U[9]#M###ACS # LN [V]▝LN [▒]#ACS #C[,,]ACS #C PAUSE #ACS # LN NOT #UPI# RETURN▛C PLOT RETURN C PAUSE Y MPI#5[>]#)##▞▒LN [3]#EY#6[7]#E##6##U[9]#▞ #[R]ACS )ACS (ACS )ACS (ACS )ACS (5[,]RND\,,##5[>]#▞▒VAL ▘4 ,#\,,]#▞▒LN [3]#5[>]#)##▞▒VAL ▘4 ,#\,,\,,]#▘ /Q 7"#[L]4 SAVE LN ##TAN LN ##E##▞/VAL ▞▒VAL ▘4 FAST#\,,#▞▖Y [R]ACS ACS *ACS >ACS *5##STR$ - #;SGN #E##7# RETURN#C IF 6###(USR LPRINT 7AT (VAL ▘S \,,AT ([V]TAN 5[>]#UZ##Y[Z][)]#**#▞ ACS )ACS (ACS )ACS (ACS )ACS (ACS )ACS (ACS )ACS (\,,[R]UY##ACS 3ACS 3ACS 3 NEW3## NEW▛W#▞ \,,TAN FASTSTR$ VAL LN >=# AND M#UPI# RETURN 4?PI##Y▘ACS ?( UNPLOT [L]#AT SGN LPRINT TAN FAST5[,]RND#▞ [R]ACS )ACS (ACS )ACS (ACS )ACS (\,,# NEW▛▞ #\,,# LPRINT #PIACS )( UNPLOT PISACS ##Y RETURNACS ?( UNPLOT [5]#L##[U]4▖#[S]CG#[(]▞▘K▖ GOSUB #▞ COPY4▝▞ ##[>]#:▘K▖ GOSUB #: COPY4▝: ##[W]S▞##- /▝2 [O]TAN STR$ VAL 5Y##7#7#7#LN ##ASN )# GOSUB ### GOSUB ###6###ACS G#▞ GOSUB ###M##LN *#U###A GOSUB ###\,,6## GOSUB ###U###▞ #[S]4▖#[T]S\~~[R] GOSUB PI6## GOSUB ###UY#▙MY#UZ#▄MZ#U##X4[W] GOSUB #RND# GOSUB #Y#AT SGN LN *#TAN LN 7?<= CLSACS *ACS ***▞ COPYY PEEK CLS<= CLSACS 3K IF ( POKE Y▖PEEK CLS5[>]#▞""VAL Y PEEK CLS<= CLSACS *K IF -4##7▞▒ACS )ACS 3#<= CLSACS 3K IF # NEW█PEEK CLS( INPUT +4 NEW<= CLSACS 3K IF Y▖PEEK CLSAT (ATN LN F?TAN 5[>]#6##TAN Y M##EY# FOR ERND##▄3##▙3# GOSUB ###[W]K▝##[=]▞ # GOSUB ####[X]K▝##[+]# GOSUB ###5 6##5 ▘6##▞#VAL GOSUB ###LN PI#U####ACS +[£]MZ##ACS <[0]MINKEY$ #E## GOSUB ###LN PI#U####ACS +[£]MRND###ACS <[0]MY##LN 0#E## GOSUB ###▞▞[R]ACS EACS .( IF ;6## FOR E##▞▞[R]ACS EACS .( IF [R] GOSUB #6##AT ([.]TAN U## RETURN▘C.LN *##MY#LN *#UINKEY$ #MZ#LN *##MY#LN *#TAN LN ##TAN ▞(## FOR 5 ACS TACS 3K▘; FOR D FOR ( POKE TAN Y▘###LN >=##PI*( CLEAR▘ ACS )TAN UY##UZ##UINKEY$ ##MZ#LN [2]##MINKEY$ #LN [2]##MRND#LN [2]##MINKEY$ #LN [2]#TAN UY##UINKEY$ ##UZ##[V]K▀###MINKEY$ #MZ##MY#LN [2]##[V]COS $X/ GOTO -▀STR$ GOSUB ### GOSUB #Y# GOSUB ### GOSUB #RND#LN [2]# GOSUB ### GOSUB #RND#LN [2]#SGN # RETURN▀C" GOSUB ### GOSUB #RND#LN [2]# GOSUB #RND#LN [2]#TAN -▖/CODE LN 4#LN \,,#LN 4#LN \,,#LN 4#LN \,,#TAN GOSUB ### GOSUB ###E##6## GOSUB ### GOSUB ###TAN GOSUB ### GOSUB #RND# GOSUB ### GOSUB #Y# GOSUB ### GOSUB ####[U]4▌#[V]4▘TAN ##INKEY$ ##LN ## GOSUB ### GOSUB ###6###ACS G#▞ GOSUB ###M##LN [2]#U###A GOSUB ###\,,6## GOSUB ###U###▞ #[S]4▖#[T]S\~~[R] GOSUB PI6## GOSUB ###U##▙M##MY#U##▄M##MZ#U##X4[Q]TAN LN PLOT # GOSUB ### GOSUB ###LN PLOT #TAN ▘ /5[>]## INPUT COPY#7"#[L]4 PLOT TAN 5##Q#7Q#7QYTAN 5##Q#7▘M##7#TAN XXXXXXXXXX 2 REM 3 FAST 4 POKE (1+PEEK 16396+256*PEEK 16397),192 5 SAVE "SINC-ARTIST 1.[3]" 6 IF PEEK 16389=127 THEN POKE (1+PEEK 16396+256*PEEK 16397),0 7 IF PEEK 16389=127 THEN STOP 8 RAND USR 16516 ```