PSGE 32/64

Developer(s): Stan Lemke
Date: 198x
Type: Program
Platform(s): TS 2068

PSGE 32/64 is a screen conversion utility that transforms a standard 32-column display into a 64-column high-resolution screen layout using machine code routines loaded from DATA statements. Five conversion modes are available: doubling the image across both halves, placing content on the left half only, the right half only, a user-specified column offset, or merging two separate 32-column screens side by side into a single 64-column result. Machine code is POKEd into memory starting at address 57000 and provides four subroutines: a video mode switcher, a pixel-coordinate locate function, and two display-frame copy routines. Each DATA block is checksum-verified after loading to detect transcription errors before any conversion is attempted.


Program Structure

The program is organized into clearly separated functional blocks:

  1. Lines 1–140: REM header and machine code address map comments
  2. Lines 300–530: Initialization, mode selection menu, and input validation
  3. Lines 540–580: Option 4 (user-specific column) parameter input
  4. Lines 600–900: Screen load, dispatch, save, and exit
  5. Lines 1000–5010: Five conversion subroutines (one per mode)
  6. Lines 9000–9150: Machine code DATA and loader/verifier subroutine
  7. Lines 9800–9998: Error handler and SAVE line

Machine Code Routines

Four machine code routines are loaded via GO SUB 9100 into addresses 57000–57116:

AddressDATA linePurpose
570009000Video mode switcher (OUT 244, port handling)
570409010Locate routine — converts (x,y) pixel coords to screen address
570759020Clear display frame 2 (LDIR from 24576)
570909030Copy DF3 to DF1 (LDIR)
571059040Clear display frame 3 (LDIR)

The locate routine stores results at fixed scratchpad addresses: the pixel screen address is read back from PEEK 65399/PEEK 65398 (low/high bytes) and the attribute address from PEEK 65375/PEEK 65374. Parameters are passed by POKEing x into 6541465415 and y into 6541665417.

Checksum Verification

Each DATA block is verified by summing all byte values and comparing to a hardcoded expected total. Subroutine 9100 performs five such checks (lines 9100–9140). On mismatch, the offending DATA line number is stored in l and execution branches to line 9800, which prints a diagnostic message and halts. This guards against transcription errors when entering the program by hand.

Conversion Logic

All five conversion modes share the same inner-loop structure. For each pixel row y (175 down to 0), the locate routine is called to find the screen and attribute addresses for the leftmost byte of that row. The loop then walks across 32-column positions (incrementing by 16 pixel units, stepping through 15 bytes with the loop guard IF x<238). Each source byte v is read, the source cell is blanked to 255 (all pixels white), and v is written to one or both destination offsets in the alternate display frames.

  • Mode 1 (1000): Writes v to both r+0 and r+16 / q+0 and q+16 — doubling into both halves.
  • Mode 2 (2000): Writes only to r and q (left half only).
  • Mode 3 (3000): Writes only to r+16 and q+16 (right half only).
  • Mode 4 (4000): Writes to r+b and q+b, where b is the user-specified column divided by 2.
  • Mode 5 (5000): Calls mode 2, pauses to allow a second tape load, then calls mode 3 — merging two distinct screens side by side.

The offsets +8192 (stored in q) and +33536 (stored in r) represent the two alternate display frame bases relative to the standard screen at 16384.

Key BASIC Idioms

  • NOT PI evaluates to 0 (since PI is nonzero, NOT PI = 0), used throughout as a compact zero literal in POKE arguments and loop bounds.
  • VAL "256* PEEK 65399+ PEEK 65398" forces expression evaluation in a string to reconstruct a 16-bit address from two POKEd bytes — a workaround for expression-length or precedence concerns.
  • GO TO (1000* VAL a$) at line 700 dispatches to the correct conversion subroutine based on the menu digit, avoiding a chain of IF tests.
  • RESTORE 9000 before each DATA read ensures the DATA pointer is reset to the correct block for each checksum pass.
  • Line 4010 uses STEP -SGN m where m is uninitialized (defaults to 0), making SGN m = 0 and therefore STEP 0 — this is effectively an infinite loop that processes only y=175. This appears to be a latent bug; the variable m was probably intended to hold a row count but was never assigned.

Save Strategy

Line 800 performs a two-part SAVE: first SAVE n$ SCREEN$ saves the standard screen area (6912 bytes from 16384), then SAVE n$ CODE 24576,6912 saves the converted 64-column screen data from address 24576. The user is warned via the lower display frame to prepare the tape before either SAVE executes.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    1 REM \{6}\{6}           \{20}\{1}PS/GE  APPEND\{20}\{0}\{6}\{6}\{6}     \{18}\{1}\*\{18}\{0}    by   S D Lemke\{6}\{6}\{6}     Lemke Software Development\{6}     2144 White Oak\{6}     Wichita, Ks    67207\{6}\{6}\{6}
   10 PRINT TAB 10;"\{18}\{1}WORKING\{18}\{0}"
  100 REM  57000 -- video mode
  110 REM  57040 -- locate
  120 REM  57075 -- clear DF 2
  130 REM  57090 -- DF3 -> DF1
  140 REM  57105 -- clear DF 3    
  300 GO SUB 9100:RANDOMIZE USR 57000:OUT 255,0:PAPER 1:BORDER 1:INK 7:CLS :RANDOMIZE USR 57075:RANDOMIZE USR 57105
  400 CLS 
  500 PRINT "        \{20}\{1}PS/GE   32->64\{20}\{0}"''"Use this program to  convert a  standard 32 column screen to a  64 (hi res) column screen."''" Press 1-5 to select an option."
  510 PRINT ''" 1) DOUBLE IMAGE (32 => 32 + 32) 2) LEFT ONLY"'" 3) RIGHT ONLY"'" 4) USER SPECIFIC"'" 5) LEFT + RIGHT (32 + 32 => 64)"
  520 PAUSE 0:LET a$= INKEY$:IF a$<"1" OR a$>"5" THEN BEEP 1,0:GO TO 520
  530 PRINT AT 8+ VAL a$,1; OVER 1; FLASH 1;" ":IF a$ <>"4" THEN GO TO 600
  540 INPUT "Specify Beginning Column ";b$:LET lb= LEN b$:IF lb=0 THEN BEEP 1,0:GO TO 540
  550 FOR i=1 TO lb:IF b$(i)<"0" OR b$(i)>"9" THEN BEEP 1,0:GO TO 540
  560 NEXT i
  570 LET b= VAL b$:IF b>32 THEN BEEP 1,0:GO TO 540
  580 LET b= INT (b/2)
  600 INPUT "Screen Name? ";n$:PRINT AT 14,10;"\{18}\{1}LOAD SCREEN\{18}\{0}":LOAD n$ SCREEN$ 
  700 GO SUB (1000* VAL a$)
  800 PRINT #0; NOT PI, NOT PI;"Prepare tape to SAVE your new 64Column SCREEN, Note: \{18}\{1}2 part SAVE\{18}\{0}\{20}\{0}":PAUSE 300:PRINT #0; AT NOT PI, NOT PI,,,,:PRINT #0; AT NOT PI, NOT PI;"   Press any KEY to CONTINUE":PAUSE NOT PI:INPUT "Screen Name? ";n$:OUT 255, NOT PI:SAVE n$ SCREEN$ :SAVE n$ CODE 24576,6912
  900 OUT 255,54:STOP 
 1000 REM    \{20}\{1}32 ->   32 + 32\{20}\{0}
 1010 FOR y=175 TO 0 STEP -1:LET x=0:POKE 65414,x:POKE 65415,0:POKE 65416,y:POKE 65417,0:RANDOMIZE USR 57040:LET p= VAL "256* PEEK 65399+ PEEK 65398":LET q=p+8192:LET r=p+33536:LET s= VAL "256* PEEK 65375+ PEEK 65374"
 1020 LET v= PEEK p:POKE p,255:POKE s,15:POKE r,v:POKE r+16,v:LET p=p+1:LET s=s+1:LET v= PEEK p:POKE p,255:POKE s,15:POKE q,v:POKE q+16,v:IF x<238 THEN LET x=x+16:LET p=p+1:LET s=s+1:LET r=r+1:LET q=q+1:GO TO 1020
 1030 NEXT y
 1040 OUT 255,54:RANDOMIZE USR 57090
 1050 RETURN 
 2000 REM    \{20}\{1}32 ->   32 + 00\{20}\{0}
 2010 FOR y=175 TO 0 STEP -1:LET x=0:POKE 65414,x:POKE 65415, NOT PI:POKE 65416,y:POKE 65417, NOT PI:RANDOMIZE USR 57040:LET p= VAL "256* PEEK 65399+ PEEK 65398":LET q=p+8192:LET r=p+33536:LET s= VAL "256* PEEK 65375+ PEEK 65374"
 2020 LET v= PEEK p:POKE p,255:POKE s,15:POKE r,v:LET p=p+1:LET s=s+1:LET v= PEEK p:POKE p,255:POKE s,15:POKE q,v:IF x<238 THEN LET x=x+16:LET p=p+1:LET s=s+1:LET r=r+1:LET q=q+1:GO TO 2020
 2030 NEXT y
 2040 OUT 255,54:RANDOMIZE USR 57090
 2050 RETURN 
 3000 REM    \{20}\{1}32 ->   00 + 32\{20}\{0}
 3010 FOR y=175 TO 0 STEP -1:LET x= NOT PI:POKE 65414,x:POKE 65415, NOT PI:POKE 65416,y:POKE 65417, NOT PI:RANDOMIZE USR 57040:LET p= VAL "256* PEEK 65399+ PEEK 65398":LET q=p+8192:LET r=p+33536:LET s= VAL "256* PEEK 65375+ PEEK 65374"
 3020 LET v= PEEK p:POKE p,255:POKE s,15:POKE r+16,v:LET p=p+1:LET s=s+1:LET v= PEEK p:POKE p,255:POKE s,15:POKE q+16,v:IF x<238 THEN LET x=x+16:LET p=p+1:LET s=s+1:LET r=r+1:LET q=q+1:GO TO 3020
 3030 NEXT y
 3040 OUT 255,54:RANDOMIZE USR 57090
 3050 RETURN 
 4000 REM    \{20}\{1}32 -> SPECIFIC\{20}\{0}
 4010 FOR y=175 TO NOT PI STEP - SGN m:LET x= NOT PI:POKE 65414,x:POKE 65415, NOT PI:POKE 65416,y:POKE 65417, NOT PI:RANDOMIZE USR 57040:LET p= VAL "256* PEEK 65399+ PEEK 65398":LET q=p+8192:LET r=p+33536:LET s= VAL "256* PEEK 65375+ PEEK 65374"
 4020 LET v= PEEK p:POKE p,255:POKE s,15:POKE r+b,v:LET p=p+1:LET s=s+1:LET v= PEEK p:POKE p,255:POKE s,15:POKE q+b,v:IF x<238 THEN LET x=x+16:LET p=p+1:LET s=s+1:LET r=r+1:LET q=q+1:GO TO 4020
 4030 NEXT y
 4040 OUT 255,54:RANDOMIZE USR 57090
 4050 RETURN 
 5000 REM    \{20}\{1}32 + 32 => 64\{20}\{0}
 5010 GO SUB 2000:PAUSE 60:OUT 255,0:CLS :PRINT AT 14,10;"\{18}\{1}LOAD SCREEN 2\{18}\{0}":INPUT "Screen Name? ";n$:LOAD n$ SCREEN$ :GO SUB 3000:RETURN 
 8999 STOP 
 9000 DATA 46,0,62,1,211,244,219,255,203,255,211,255,62,6,245,251,205,142,14,0,219,255,203,191,211,255,175,211,244,241,254,128,32,4,50,91,104,251,201
 9010 DATA 33,134,255,78,33,136,255,70,205,3,38,34,118,255,124,198,32,103,34,96,255,124,15,15,15,230,3,246,88,103,34,94,255,201
 9020 DATA 17,0,96,33,0,64,1,0,27,237,176,201
 9030 DATA 17,0,64,33,0,195,1,0,27,237,176,201
 9040 DATA 17,0,195,33,0,64,1,0,27,237,176,201
 9100 LET sum=0:RESTORE 9000:FOR i=57000 TO 57038:READ a:POKE i,a:LET sum=sum+a:NEXT i:IF sum <>6207 THEN LET l=9000:GO TO 9800
 9110 LET sum=0:RESTORE 9010:FOR i=57040 TO 57073:READ a:POKE i,a:LET sum=sum+a:NEXT i:IF sum <>3912 THEN LET l=9010:GO TO 9800
 9120 LET sum=0:RESTORE 9020:FOR i=57075 TO 57086:READ a:POKE i,a:LET sum=sum+a:NEXT i:IF sum <>852 THEN LET l=9020:GO TO 9800
 9130 LET sum=0:RESTORE 9030:FOR i=57090 TO 57101:READ a:POKE i,a:LET sum=sum+a:NEXT i:IF sum <>951 THEN LET l=9030:GO TO 9800
 9140 LET sum=0:RESTORE 9040:FOR i=57105 TO 57116:READ a:POKE i,a:LET sum=sum+a:NEXT i:IF sum <>951 THEN LET l=9040:GO TO 9800
 9150 RETURN 
 9800 CLS :PRINT "You have an error in line ";l:BEEP 1,1:STOP 
 9997 STOP 
 9998 SAVE "PSGE 32/64" LINE 1

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top