Plotting a function in hi-res graphics mode on a Commodore 64

I wrote a program to plot a function in hi-res graphics mode on the C64. It is entirely in BASIC, so it is mind-numbingly slow, but it works, and can be used to plot some fairly interesting functions.

This mode only allows one background color and one foreground color for each 8×8 block of pixels. It would, I suppose, be possible to plot multiple functions in multiple colors, but the intersections would be strange, as each 8×8 block can only have two colors, including the background. An obvious next step is to use the multi-color bitmap mode, but which this would allow four colors in any given 8×8 block, it would reduce the resolution from 320×200 down to 160×200. I will try this soon.

Another obvious improvement will be to move much of the setup stuff (like erasing the graphics ram ($2000-$3fff)) down into machine language, which would speed things up significantly.

The Graphics Book for the Commodore 64 was indispensable.

Here is the plot of f(x) = sin(x) + sin(1.5*x + pi/2)

And here is the code:

 10 rem *** funcplot
 20 rem
 30 pi = 3.141592653
 40 yu = 2.2 : yd = -2.2
 50 xu = 6pi : xd = -6pi
 60 xr = xu - xd : yr = yu - yd
 70 xs = xr/320 : ys = yr/200
 80 def fn f(x) = sin(x) + sin(1.5*x + pi/2)
 100 rem set vic address
 110 v = 53248
 120 rem set graphic ram address
 130 ga = 8192
 140 rem set video ram address
 150 vr = 1024
 160 rem set border to black
 170 poke v+32,0
 500 gosub 20000 : rem turn on hires
 510 gosub 21000 : rem graphic ram area
 520 gosub 22000 : rem set color ram
 530 gosub 23000 : rem clr graphic ram
 1000 rem draw x axis
 1005 y=0 : yc=int(200-(y-yd)*(200/yr)) 
 1010 for xc = 0 to 319 
 1020 gosub 30000 : rem set (xc,yc) 
 1030 next xc 
 1100 rem draw y axis
 1110 x = 0
 1120 for yc = 1 to 200
 1130 xc = int((x-xd)*(320/xr))
 1140 gosub 30000 : rem set (xc,yc)
 1150 next yc
 1300 rem plot function
 1310 for x = xd to xu step xs
 1320 y = fn f(x)
 1330 xc = int((x-xd)*(320/xr))
 1340 yc = int(200-(y-yd)*(200/yr))
 1350 gosub 30000 : rem set (xc,yc)
 1360 next x
 1400 poke 198,0 : wait 198,1
 1450 gosub 24000
 1500 end
 20000 rem turn on hi res graphics
 20010 rem   1. set bits 5/6 of v+17
 20020 rem   2. clr bit 4 of v+22
 20030 poke v+17,peek(v+17) or (11*16)
 20040 poke v+22,peek(v+22) and (255-16)
 20050 return
 21000 rem set graphic ram area
 21010 rem   1. set bit 3 of v+24
 21020 poke v+24, peek(v+24) or 8
 21030 return
 22000 rem set color ram
 22010 rem   1. color ram is 1024-2023
 22020 rem   2. set background 1 - white
 22030 rem   3. set foreground 0 - black
 22040 co = 0*16 + 1
 22050 for i = vr to vr+1000
 22060 poke i,co
 22070 next i
 22080 return
 23000 rem clear graphic ram
 23010 rem   1. graphic ram is ga to
 23020 rem        ga + 8000
 23030 for i = ga to ga +8000
 23040 poke i,0
 23050 next i
 23060 return
 24000 rem turn graphics off
 24010 rem   1. clr bits 5/6 of v+17
 24020 rem   2. clr bit 4 of v+22
 24030 rem   3. clr bit 3 of v+24
 24040 poke v+17,peek(v+17) and (255-96)
 24050 poke v+22,peek(v+22) and (255-16)
 24060 poke v+24,peek(v+24) and (255-8)
 24070 return
 30000 rem set pixel
 30010 ra = 320*int(yc/8)+(yc and 7)
 30020 ba = 8*int(xc/8)
 30030 ma = 2^(7-(xc and 7))
 30040 ad = ga + ra + ba
 30050 poke ad,peek(ad) or  ma
 30060 return
 31000 rem clr pixel
 31010 ra = 320*int(yc/8)+(yc and 7)
 31020 ba = 8*int(xc/8)
 31030 ma = 255-2^(7-(xc and 7))
 31040 ad = ga + ra + ba
 31050 poke ad,peek(ad) or  ma
 31060 return
 

One thought on “Plotting a function in hi-res graphics mode on a Commodore 64

  1. Hi Paul! I ported your code for the subroutines to machine language routines to be used by all the gosubs. Interestingly, plotting a point isn’t faster. But the setup definitely is as you already suspected. If one was drawing lines, then that’s the probably the next recommended enhancement.

    1 REM ORIGINALLY FROM
    2 REM PAULNOTEBOOK.NET/2019/06/08
    3 REM /PLOTTING-A-FUNCTION-IN-HI-RES-
    4 REM GRAPHICS-MODE-ON-A-COMMODORE-64/
    5 REM
    6 REM MACHINE LANGUAGE ROUTINES PORTED
    7 REM BY DAVE@DAVEVW.COM
    8 REM TECHWITHDAVE.DAVEVW.COM
    9 REM
    10 REM *** FUNCPLOT
    20 REM
    30 PI = 3.141592653
    40 YU = 2.2 : YD = -2.2
    50 XU = 6*PI : XD = -6*PI
    60 XR = XU – XD : YR = YU – YD
    70 XS = XR/320 : YS = YR/200
    80 DEF FN F(X) = SIN(X) + SIN(1.5*X + PI/2)
    90 ML=7922:FOR I=ML TO 8191:READ B:POKE I,B:NEXT
    100 REM SET VIC ADDRESS
    110 V = 53248
    120 REM SET GRAPHIC RAM ADDRESS
    130 GA = 8192
    140 REM SET VIDEO RAM ADDRESS
    150 VR = 1024
    160 REM SET BORDER TO BLACK
    170 POKE V+32,0
    500 GOSUB 20000 : REM TURN ON HIRES
    510 GOSUB 21000 : REM GRAPHIC RAM AREA
    520 GOSUB 22000 : REM SET COLOR RAM
    530 GOSUB 23000 : REM CLR GRAPHIC RAM
    1000 REM DRAW X AXIS
    1005 Y=0 : YC=INT(200-(Y-YD)*(200/YR))
    1010 FOR XC = 0 TO 319
    1020 GOSUB 30000 : REM SET (XC,YC)
    1030 NEXT XC
    1100 REM DRAW Y AXIS
    1110 X = 0
    1120 FOR YC = 1 TO 200
    1130 XC = INT((X-XD)*(320/XR))
    1140 GOSUB 30000 : REM SET (XC,YC)
    1150 NEXT YC
    1300 REM PLOT FUNCTION
    1310 FOR X = XD TO XU STEP XS
    1320 Y = FN F(X)
    1330 XC = INT((X-XD)*(320/XR))
    1340 YC = INT(200-(Y-YD)*(200/YR))
    1350 GOSUB 30000 : REM SET (XC,YC)
    1360 NEXT X
    1400 POKE 198,0 : WAIT 198,1
    1450 GOSUB 24000
    1500 END
    20000 REM TURN ON HI RES GRAPHICS
    20001 POKE 251,1:SYS ML:RETURN
    20010 REM 1. SET BITS 5/6 OF V+17
    20020 REM 2. CLR BIT 4 OF V+22
    20030 POKE V+17,PEEK(V+17) OR (11*16)
    20040 POKE V+22,PEEK(V+22) AND (255-16)
    20050 RETURN
    21000 REM SET GRAPHIC RAM AREA
    21001 POKE 251,2:SYS ML:RETURN
    21010 REM 1. SET BIT 3 OF V+24
    21020 POKE V+24, PEEK(V+24) OR 8
    21030 RETURN
    22000 REM SET COLOR RAM
    22001 POKE 251,3:POKE 252,1:SYS ML:RETURN
    22010 REM 1. COLOR RAM IS 1024-2023
    22020 REM 2. SET BACKGROUND 1 – WHITE
    22030 REM 3. SET FOREGROUND 0 – BLACK
    22040 CO = 0*16 + 1
    22050 FOR I = VR TO VR+1000
    22060 POKE I,CO
    22070 NEXT I
    22080 RETURN
    23000 REM CLEAR GRAPHIC RAM
    23001 POKE 251,4:SYS ML:RETURN
    23010 REM 1. GRAPHIC RAM IS GA TO
    23020 REM GA + 8000
    23030 FOR I = GA TO GA +8000
    23040 POKE I,0
    23050 NEXT I
    23060 RETURN
    24000 REM TURN GRAPHICS OFF
    24001 POKE 251,5:SYS ML:RETURN
    24010 REM 1. CLR BITS 5/6 OF V+17
    24020 REM 2. CLR BIT 4 OF V+22
    24030 REM 3. CLR BIT 3 OF V+24
    24040 POKE V+17,PEEK(V+17) AND (255-96)
    24050 POKE V+22,PEEK(V+22) AND (255-16)
    24060 POKE V+24,PEEK(V+24) AND (255-8)
    24070 RETURN
    30000 REM SET PIXEL
    30001 POKE 251,6
    30002 POKE 252,XC AND 255
    30003 POKE 253,YC
    30004 POKE 254,XC/256
    30005 SYS ML
    30006 RETURN
    30010 RA = 320*INT(YC/8)+(YC AND 7)
    30020 BA = 8*INT(XC/8)
    30030 MA = 2^(7-(XC AND 7))
    30040 AD = GA + RA + BA
    30050 POKE AD,PEEK(AD) OR MA
    30060 RETURN
    31000 REM CLR PIXEL
    31001 POKE 251,6
    31002 POKE 252,XC AND 255
    31003 POKE 253,YC
    31004 POKE 254,(XC/256) OR 2
    31005 SYS ML
    31006 RETURN
    31010 RA = 320*INT(YC/8)+(YC AND 7)
    31020 BA = 8*INT(XC/8)
    31030 MA = 255-2^(7-(XC AND 7))
    31040 AD = GA + RA + BA
    31050 POKE AD,PEEK(AD) OR MA
    31060 RETURN
    50000 DATA 165, 251, 201, 1, 208, 17, 173, 17, 208, 9, 176, 141, 17
    50001 DATA 208, 173, 22, 208, 41, 239, 141, 22, 208, 96, 201, 2, 208
    50002 DATA 9, 173, 24, 208, 9, 8, 141, 24, 208, 96, 201, 3, 208
    50003 DATA 20, 165, 252, 162, 0, 157, 0, 4, 157, 0, 5, 157, 0
    50004 DATA 6, 157, 0, 7, 232, 208, 241, 96, 201, 4, 208, 24, 169
    50005 DATA 0, 133, 254, 169, 32, 133, 255, 162, 32, 160, 0, 152, 145
    50006 DATA 254, 200, 208, 251, 230, 255, 202, 208, 246, 96, 201, 5, 208
    50007 DATA 25, 173, 17, 208, 41, 159, 141, 17, 208, 173, 22, 208, 41
    50008 DATA 239, 141, 22, 208, 173, 24, 208, 41, 247, 141, 24, 208, 96
    50009 DATA 201, 6, 240, 1, 96, 165, 252, 72, 165, 254, 72, 165, 253
    50010 DATA 72, 41, 248, 133, 251, 165, 254, 169, 0, 133, 252, 6, 251
    50011 DATA 38, 252, 6, 251, 38, 252, 162, 10, 169, 0, 133, 254, 133
    50012 DATA 255, 24, 165, 254, 101, 251, 133, 254, 165, 255, 101, 252, 133
    50013 DATA 255, 202, 208, 240, 104, 133, 252, 41, 7, 24, 101, 254, 133
    50014 DATA 254, 165, 255, 105, 0, 133, 255, 104, 133, 253, 104, 133, 251
    50015 DATA 41, 248, 24, 101, 254, 133, 254, 165, 253, 41, 1, 101, 255
    50016 DATA 133, 255, 165, 251, 41, 7, 133, 251, 169, 7, 162, 1, 56
    50017 DATA 229, 251, 134, 251, 168, 192, 0, 240, 5, 6, 251, 136, 208
    50018 DATA 251, 24, 165, 254, 105, 0, 133, 254, 165, 255, 105, 32, 133
    50019 DATA 255, 165, 253, 41, 2, 208, 7, 177, 254, 5, 251, 145, 254
    50020 DATA 96, 177, 254, 5, 251, 69, 251, 145, 254, 96, -1

    Like

Leave a Reply to David Van Wagner Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s