100 REM BASIC Month: Terraspin 110 REM http://reddit.com/r/RetroBattlestations 120 REM written by FozzTexx - Commodore 64 port by FozzTexx 130 REM Commodore 64 BASIC has bitwise operators so much of the line 140 REM clipping logic is simplified compared to the Apple II version. 150 REM The Commodore 64 has *no* graphics commands at all. All graphics 160 REM has to be done using PEEKs and POKEs. Line drawing is handled by 170 REM a complicated routine at 1500. Individual pixels are then plotted 180 REM with the routine at 1700. 200 REM === Initialize variables 210 SW = 320:SH = 200:XS = SW / 1000:YS = (SH * 4) / (1000 * 3) 220 SW = SW - 1:SH = SH - 1 230 PI = 3.14159 250 REM === Set turtle start at center of screen pointing up, pen up 260 TX = 500:TY = SH / YS / 2:TA = 90:TP = 0 300 REM === Get command to execute 310 CM$="5 ( D 12 ( 210 M 5 ( 30 T 10 M ) ) U 100 T 150 M )" 460 REM ### If the program crashes it will 470 REM ### be stuck in graphics mode. 480 REM ### Type RUN 999 to get back to text. 490 GOSUB 6010 500 REM === Command interpreter 510 IP = 1:SP = 0 520 C$ = MID$(CM$, IP, 1) 530 IF C$ = " " THEN IP = IP + 1:GOTO 520 540 IF C$ >= "-" AND C$ <= "9" THEN V = VAL(MID$(CM$, IP)):GOSUB 1010:GOSUB 1210 550 IF C$ = "(" THEN V = IP:GOSUB 1010 560 IF C$ = ")" THEN GOSUB 2010 570 IF C$ = "M" THEN GOSUB 2510 580 IF C$ = "T" THEN GOSUB 3010 590 IF C$ = "U" THEN GOSUB 3510 600 IF C$ = "D" THEN GOSUB 4010 610 IP = IP + 1 620 IF IP > LEN(CM$) THEN END 630 GOTO 520 999 POKE 53272,PEEK(53272) AND 247:POKE 53265,PEEK(53265) AND 223:END 1000 REM === Push onto stack 1010 SP = SP + 1:SK(SP) = V 1020 RETURN 1100 REM === Pop from stack 1110 V = SK(SP):SP = SP - 1 1120 RETURN 1200 REM === Skip over number 1210 IP = IP + 1 1220 IF IP > LEN(CM$) THEN 1250 1230 C2$ = MID$(CM$, IP, 1) 1240 IF C2$ >= "-" AND C2$ <= "9" THEN GOTO 1210 1250 IP = IP - 1 1260 RETURN 1500 REM === Plot a line 1510 X1% = X1:X2% = X2:Y1% = Y1:Y2% = Y2 1520 DX% = ABS(X2% - X1%):SX% = -1:IF X1% < X2% THEN SX% = 1 1530 DY% = ABS(Y2% - Y1%):SY% = -1:IF Y1% < Y2% THEN SY% = 1 1540 ER% = -DY%:IF DX% > DY% THEN ER% = DX% 1550 ER% = ER% / 2 1560 GOSUB 1710 1570 IF X1% = X2% AND Y1% = Y2% THEN RETURN 1580 E2% = ER% 1590 IF E2% > -DX% THEN ER% = ER% - DY%:X1% = X1% + SX% 1600 IF X1% = X2% AND Y1% = Y2% THEN RETURN 1610 IF E2% < DY% THEN ER% = ER% + DX%:Y1% = Y1% + SY% 1620 IF X1% = X2% AND Y1% = Y2% THEN RETURN 1630 GOTO 1560 1700 REM === Plot a point 1710 CH% = INT(X1% / 8):RO% = INT(Y1% / 8):LN% = Y1% AND 7 1720 BY = BASE + RO% * 320 + 8 * CH% + LN%:BI% = 7 - (X1% AND 7) 1730 POKE BY,PEEK(BY) OR (2 ^ BI%) 1740 RETURN 2000 REM === Loop instruction end 2010 GOSUB 1110:BP = V 2020 GOSUB 1110:LR = V 2030 LR = LR - 1 2040 IF LR < 1 THEN RETURN 2050 V = LR:GOSUB 1010 2060 V = BP:GOSUB 1010 2070 IP = BP 2080 RETURN 2500 REM === Move 2510 GOSUB 1110 2520 LX = V * COS((360 - TA) * PI / 180):LY = V * SIN((360 - TA) * PI / 180) 2530 IF TP > 0 THEN X1 = TX:Y1 = TY:X2 = X1 + LX:Y2 = Y1 + LY:GOSUB 4510 2540 TX = TX + LX:TY = TY + LY 2550 RETURN 3000 REM === Turn 3010 GOSUB 1110 3020 TA = TA + V 3030 IF TA < 0 THEN TA = TA + 360:GOTO 3030 3040 IF TA >= 360 THEN TA = TA - 360:GOTO 3040 3050 RETURN 3500 REM === Pen up 3510 TP = 0 3520 RETURN 4000 REM === Pen down 4010 TP = 1 4020 RETURN 4500 REM === Draw line, clipping if needed 4510 X1 = X1 * XS:X2 = X2 * XS:Y1 = Y1 * YS:Y2 = Y2 * YS 4520 X = X1:Y = Y1:GOSUB 5010:C1 = C 4530 X = X2:Y = Y2:GOSUB 5010:C2 = C 4540 IF C1 = 0 AND C2 = 0 THEN GOSUB 1510:RETURN 4550 IF C1 AND C2 THEN RETURN 4560 C = C1:IF C = 0 THEN C = C2 4570 IF C AND 1 THEN X = X1 + (X2 - X1) * (SH - Y1) / (Y2 - Y1):Y = SH:GOTO 4610 4580 IF C AND 2 THEN X = X1 + (X2 - X1) * (0 - Y1) / (Y2 - Y1):Y = 0:GOTO 4610 4590 IF C AND 4 THEN Y = Y1 + (Y2 - Y1) * (SW - X1) / (X2 - X1):X = SW:GOTO 4610 4600 IF C AND 8 THEN Y = Y1 + (Y2 - Y1) * (0 - X1) / (X2 - X1):X = 0:GOTO 4610 4610 IF C = C1 THEN X1 = X:Y1 = Y:GOTO 4630 4620 X2 = X:Y2 = Y 4630 GOTO 4520 5000 REM === Calculate region code 5010 C = 0 5020 IF Y > SH THEN C = C OR 1 5030 IF Y < 0 THEN C = C OR 2 5040 IF X > SW THEN C = C OR 4 5050 IF X < 0 THEN C = C OR 8 5060 RETURN 6000 REM === Enable graphics and clear screen 6010 BASE = 2 * 4096:POKE 53272,PEEK(53272) OR 8:POKE 53265,PEEK(53265) OR 32 6020 FOR I = 1024 to 2023:POKE I,3:NEXT 6030 FOR I = BASE TO BASE + 7999:POKE I,255:POKE I, 0:NEXT 6040 RETURN