100 REM BASIC Month: Terraspin 110 REM http://reddit.com/r/RetroBattlestations 120 REM written by FozzTexx - TRS-80 Model II CP/M MBASIC port by FozzTexx 130 REM CP/M MBASIC has bitwise operators so much of the line 140 REM clipping logic is simplified compared to the Apple II version. 150 REM The TRS-80 Model II has no pixel graphics at all. Graphics are 155 REM simulated using inverse spaces. Line drawing is handled through 160 REM the complicated routine at 1500 (borrowed from the C64 165 REM version). MBASIC has no cursor positioning built-in. Plotting is 170 REM done by the routine at 1700 by homing the cursor and then moving 175 REM it right and down. 200 REM === Initialize variables 210 CLEAR 200 220 SW = 80:SH = 24:XS = SW / 1000:YS = (SH * 4) / (1000 * 3) 230 SW = SW - 1:SH = SH - 1 240 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 )" 490 PRINT CHR$(12); 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 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 PRINT CHR$(6); 1720 FOR X = 1 TO X1%:PRINT CHR$(29);:NEXT 1730 FOR Y = 1 TO Y1%:PRINT CHR$(10);:NEXT 1740 PRINT CHR$(14);" ";CHR$(15); 1750 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