My Nostalgia: Code from the Legacy BASIC Family (GW-BASIC, QuickBASIC, etc.) before Visual Basic
- Draw a Square, Triangle, and Circle (2025.06.30)
- Lotto 6/45 Number Generator (2024.08.28)
- Simultaneous Equations Solver (2024.08.20)
- Decimal/Hexadecimal Convertor (2023.12.10)
- Line Numbering 2 (2023.07.22)
- Pong The Origin: 1972 Atari Style Reimplementation v1.1 (2026.02.16)
- Pong The Origin: 1972 Atari Style Reimplementation v1.0 (2026.02.07)
- Line Numbering (2023.07.19)
- Draw A Car (2022.02.09)
- Play Music (2021.02.20)
- Hello World (2020.02.27)
🔄 Improvements from v1.0 (2026.02.07)
- Enhanced Initial Serve Logic: Overhauled the fixed-direction serve mechanism (1P → 2P) with no waiting time; implemented a 1.5-second pre-game countdown followed by a randomized serve direction and angle.
- Enlarge Score Display: Introduced bitmap font-based multi-row graphics rendering with a custom 5-row character array, scaling scores closer to the original 1972 Atari aesthetic and improving visibility.
- Eliminate Paddle Flickering: Implemented directional-selective erasing for paddles—only the regions affected by movement are cleared.
- Fine-Tuned Wall Collision Angles: Refined ball trajectory calculations at wall boundaries with anti-sticking bounce logic, including force-back positioning to prevent edge-case adhesion.
- CPU-Dependent Execution Speed: An attempt was made to implement hardware-independent frame rates using the
TIMERfunction. However, the nativeTIMERin QuickBASIC provides a resolution of only approximately 1/18.2 seconds (≒55ms), which is insufficient for the fine-grained precision required for smooth gameplay (e.g., 60 FPS or 16ms intervals). - Optimization for DOSBox: Due to these technical limitations, the game utilizes an old-fashioned
FOR …… NEXTloop to control execution speed. While this introduces CPU dependency, it has been optimized at 3000 Cycles in DOSBox. - References: Detailed documentation on QuickBASIC timer precision can be found at QB64 Wiki: TIMER.
- Environment: QuickBASIC 4.5 or other compatible environments(e.g., QB64)
- Screen Mode: VGA Screen Mode 12 (640x480, 16 Colors)
- 1P/2P Modes: Play against a dynamic AI or a local friend.
- Difficulty Scaling: Choose among 3 difficulty tiers (Easy, Normal, Hard) affecting AI reaction and paddle speed.
- Kinetic Ball Physics:
- Acceleration: Velocity increases on every successful hit, demanding higher focus over time.
- Segment Hits: Trajectory angles are calculated based on the hit position (top/center/bottom) of the paddle.
- Optimization:
- Flicker-Free: Implements selective erasing (
LINE...0, BF) for smooth motion instead of full-screen clears. - Input Sync: Non-blocking
INKEY$handling for responsive 2-player controls.
- Flicker-Free: Implements selective erasing (
- Soundscape: Legacy-style
SOUNDfrequencies for wall bounces, paddle collisions, and match victory jingles.
| Action | Player 1 (Left) | Player 2 (Right) |
|---|---|---|
| Move Up | W |
Up Arrow |
| Move Down | S |
Down Arrow |
| Exit | Esc |
- |
-
My eternal nostalgia!
-
Code
SHAPES.BAS
100 REM =================================================== 110 REM Draw a Square, Equilateral Triangle, and Circle 120 REM 2025.06.30. 130 REM [Description] 140 REM - SHAPEHT: Common height for all shapes (in pixels) 150 REM - CX, CY: Screen center coordinates 160 REM - Triangle base length is calculated automatically 170 REM - Circle radius = SHAPEHT / 2 180 REM =================================================== 200 REM ---- Initialize Constants ---- 210 ON ERROR GOTO 700 220 SCREEN 1 ' 320x200 graphics mode 230 SHAPEHT = 80 ' Common height of all shapes 240 CX = 160 : CY = 100 ' Screen center 300 REM ---- Draw Title ---- 310 LOCATE 2, 17 : PRINT "My Shapes" 320 LOCATE 4, 16 : PRINT "2025.06.30." 400 REM ---- Draw Square ---- 410 SQSIZE = SHAPEHT 420 SQX = CX - 100 - SQSIZE / 2 ' Square left-top X coordinate 430 LINE (SQX, CY - SQSIZE / 2)-(SQX + SQSIZE, CY + SQSIZE / 2), 1, B 500 REM ---- Draw Equilateral Triangle ---- 510 TRIX = CX ' Triangle center X coordinate 520 TRIBASE = SHAPEHT * 2 / SQR(3) ' Triangle base length 530 REM Calculate Triangle Vertices 540 X1 = TRIX - TRIBASE / 2 : Y1 = CY + SHAPEHT / 2 550 X2 = TRIX + TRIBASE / 2 : Y2 = Y1 560 X3 = TRIX : Y3 = CY - SHAPEHT / 2 570 LINE (X1, Y1)-(X2, Y2), 2 ' Draw triangle base 580 LINE (X2, Y2)-(X3, Y3), 2 ' Draw triangle right side 590 LINE (X3, Y3)-(X1, Y1), 2 ' Draw triangle left side 600 REM ---- Draw Circle ---- 610 CIRX = CX + 100 ' Circle center X coordinate 620 CIRCLE (CIRX, CY), SHAPEHT / 2 * 1.15, 3 ' 1.15 : Magic Number! 700 REM ---- Wait for Key Press ---- 710 LOCATE 24, 1 : PRINT "Press any key..."; 720 IF INKEY$ = "" THEN GOTO 720 730 SCREEN 0 740 WIDTH 80 800 END
-
Generates n sets of 7 unique numbers between 1 and 45
- If user inputs numbers, those are fixed and others are generated
- Displays the numbers in the format: a b c d e f + lucky number
-
Migrated from kimpro82/MyBizApps#61
-
Code :
LOTTO.BAS100~190 : Main part
100 SETSNUM = 4 ' Constant for the number of sets to generate 110 RANDOMIZE TIMER ' Initialize random number generator 120 PRINT "Press ENTER or input your fixed numbers (space-separated):" 130 INPUT USERSTR$ ' Get user input 140 DIM NUMSET(7) ' Declare array to hold one set of numbers 150 ' Parse user input and validate 160 IF USERSTR$ = "" THEN GOTO 200 ' No input, generate all random 170 GOSUB 500 ' Validate and parse user input 180 ' If invalid input, re-prompt user 190 IF ERRORFLAG = 1 THEN PRINT "Invalid input. Please try again." : GOTO 110
200~420 : Start generating sets of numbers
200 ' Start generating sets of numbers 210 FOR I = 1 TO SETSNUM ' Generate sets based on the constant 220 GOSUB 900 ' Initialize array for each set 230 COUNT = 0 ' Reset count for each set 240 ' Fill array with user-provided numbers 250 FOR J = 1 TO USERINDEX 260 NUMSET(J) = USERNUMS(J) 270 COUNT = COUNT + 1 280 NEXT J 290 ' Generate remaining random numbers 300 WHILE COUNT < 7 ' Generate random numbers until the total count is 7 310 NEWNUM = INT(RND * 45) + 1 320 GOSUB 700 ' Check if number is already in the set 330 IF INSET = -1 THEN GOTO 310 ' If number is already in the set, generate again 340 COUNT = COUNT + 1 350 NUMSET(COUNT) = NEWNUM 360 WEND 370 ' Sort only the numbers from position USERINDEX + 1 to 6, leaving the last number (NUMSET(7)) unsorted 380 GOSUB 800 ' Sort the numbers from position USERINDEX + 1 to 6 390 ' Display the result with numbers formatted to two characters each 400 PRINT USING "## ## ## ## ## ## + ##"; NUMSET(1); NUMSET(2); NUMSET(3); NUMSET(4); NUMSET(5); NUMSET(6); NUMSET(7) 410 NEXT I 420 END
500~690 : Subroutine to validate and parse user input
500 ' Subroutine to validate and parse user input 510 DIM USERNUMS(6) ' Maximum 6 numbers can be fixed 520 USERINDEX = 0 530 ERRORFLAG = 0 540 ' Split user input by spaces 550 TMP$ = "" ' Initialize temporary string 560 FOR K = 1 TO LEN(USERSTR$) 570 CHAR$ = MID$(USERSTR$, K, 1) 580 IF CHAR$ >= "0" AND CHAR$ <= "9" THEN TMP$ = TMP$ + CHAR$ 590 IF CHAR$ <> " " AND K < LEN(USERSTR$) THEN GOTO 680 600 IF LEN(TMP$) = 0 THEN GOTO 680 610 VALNUM = VAL(TMP$) 620 IF VALNUM < 1 OR VALNUM > 45 THEN ERRORFLAG = 1 : RETURN 630 GOSUB 700 ' Check if number is already in the user input set 640 IF INSET = -1 THEN ERRORFLAG = 1 : RETURN 650 USERINDEX = USERINDEX + 1 660 USERNUMS(USERINDEX) = VALNUM 670 TMP$ = "" 680 NEXT K 690 RETURN
700~750 : Subroutine to check if a number is in the set
700 ' Subroutine to check if a number is in the set 710 INSET = 0 720 FOR L = 1 TO COUNT 730 IF NUMSET(L) = NEWNUM THEN INSET = -1 : RETURN 740 NEXT L 750 RETURN
800~880 : Subroutine to sort the numbers from position USERINDEX + 1 to 6
800 ' Subroutine to sort the numbers from position USERINDEX + 1 to 6 810 START = USERINDEX + 1 820 ENDIDX = 6 ' Sort up to NUMSET(6), excluding NUMSET(7) 830 FOR M = START TO ENDIDX - 1 840 FOR N = M + 1 TO ENDIDX 850 IF NUMSET(M) > NUMSET(N) THEN SWAP NUMSET(M), NUMSET(N) 860 NEXT N 870 NEXT M 880 RETURN
900~940 : Subroutine to initialize the NUMSET array
900 ' Subroutine to initialize the NUMSET array 910 FOR T = 1 TO 7 920 NUMSET(T) = 0 930 NEXT T 940 RETURN
-
System of Linear Equations Calculator using Determinant Method
- Enter six floating-point numbers:
a,b,c,d,e, andf - If fewer than six numbers are provided, zeros will be substituted for the missing values
- Enter six floating-point numbers:
-
Code :
SESOLVER.BAS100~160 : Initialize and get input data
100 ' Initialize and get input data 110 DIM COEF#(5) ' Array to store coefficients 120 PRINT "The system of equations is:" 130 PRINT " ax + by = c" 140 PRINT " dx + ey = f" 150 PRINT "Enter coefficients a, b, c, d, e, f (separated by spaces), or Q/q to quit:" 160 INPUT INPUTDATA$ ' Get user input
200~250 : Check for quit command or process input
200 ' Check for quit command or process input 210 IF INPUTDATA$ = "Q" OR INPUTDATA$ = "q" THEN GOTO 900 220 ' GOSUB 800 ' Initialize variables; Not use 230 GOSUB 300 ' Process input or substitute missing values with zeros 240 GOSUB 500 ' Solve the equations 250 GOTO 150
300~450 : Parse input or use default values
300 ' Parse input or use default values 310 INPUTDATA$ = INPUTDATA$ + " 0 0 0 0 0 0" ' Pad the input with zeros if fewer than 6 values are provided 320 INDEX = 1 330 FOR I = 0 TO 5 340 WORD$ = "" 350 CONDITION = 1 360 WHILE CONDITION 370 CHAR$ = MID$(INPUTDATA$, INDEX, 1) 380 IF CHAR$ <> " " THEN WORD$ = WORD$ + CHAR$ ELSE CONDITION = 0 390 ' PRINT "I:"; I; "/ INDEX:"; INDEX; "/ CHAR:"; CHAR$; " / WORD:"; WORD$; " / CONDITION:"; CONDITION ' Debug print 400 INDEX = INDEX + 1 410 WEND 420 COEF#(I) = VAL(WORD$) 430 NEXT I 450 RETURN
500~650 : Solve the system of linear equations
500 ' Solve the system of linear equations 510 A = COEF#(0): B = COEF#(1): C = COEF#(2) 520 D = COEF#(3): E = COEF#(4): F = COEF#(5) 530 PRINT "The equations you entered are:" 540 PRINT " "; A; "x +"; B; "y ="; C 550 PRINT " "; D; "x +"; E; "y ="; F 560 DETERMINANT = A * E - B * D 600 IF DETERMINANT = 0 THEN PRINT "The system has no unique solution." 610 IF DETERMINANT <> 0 THEN X = (C * E - B * F) / DETERMINANT 620 IF DETERMINANT <> 0 THEN Y = (A * F - C * D) / DETERMINANT 630 IF DETERMINANT <> 0 THEN PRINT "Solution: x = "; X; ", y = "; Y 640 ' It is crazy to handle IF conditions in GW-BASIC! 650 RETURN
800~840 : Initialize variables; Not use
800 ' Initialize variables; Not use 810 ' FOR I = 0 TO 5 820 ' COEF#(I) = 0 ' Set all coefficients to 0 830 ' NEXT I 840 ' RETURN
900~920 : Quit the program
900 ' Quit the program 910 PRINT "Program terminated." 920 END
-
To practice Subroutine with
GOSUB~RETURNstatements- Reference : 8비트 컴퓨터에서 게임 만들기 (YouTube)
-
Be aware of BOM(Byte-Order Mark;
EF BB BF) signature generation when creating a code file with an external editorCode : HEXCONV.BAS
0 CLS 10 PRINT "*************************************" 20 PRINT "* <Decimal/Hexadecimal Convertor> *" 30 PRINT "* kimpro82 / 2023.12.10, not 1993 *" 40 PRINT "* * * * * * * * * * * * * * * * * * *" 50 PRINT "* 1. Convert Decimal to Hexadecimal *" 60 PRINT "* 2. Convert Hexadecimal to Decimal *" 70 PRINT "* 3. Exit *" 80 PRINT "*************************************" 90 INPUT " Select a menu (1, 2, 3): "; MENU 100 IF MENU = 1 THEN GOSUB 200 110 IF MENU = 2 THEN GOSUB 300 120 IF MENU = 3 THEN END 130 GOTO 90 200 ' Subroutine for Decimal to Hexadecimal Conversion 210 INPUT " Enter a decimal value: "; DEC 220 PRINT " Hexadecimal value : "; HEX$(DEC) 230 RETURN 300 ' Subroutine for Hexadecimal to Decimal Conversion 310 INPUT " Enter a hexadecimal value: "; HEXA$ 315 ' The keyword HEX$(X) is already in use 320 PRINT " Decimal value : "; VAL("&H" + HEXA$) 330 RETURN
-
Finally I've got GW-BASIC 3.23!
-
Reversed line numbers are automatically rearranged as increasing order
-
Line numbers are allowed only when they are not exceeding
65529and without decimal points.Why `65529`, not `65535`?
-
Variances in Basic highest line numbers (retrocomputing.stackexchange.com)
Line numbers are stored as a two byte word but the largest allowed by the input routines is 65529. Primarily because this is an easier limit to test rather than checking for overflow. The line number is converted from ASCII to binary a character at a time using a pretty standard algorithm. Start with a 16 bit value
line= 0. For each digit multiplylineby 10 and add the digit toline.To check if the line number is acceptable, compare
lineagainst 6552 before multiplying it by 10. This will guarantee the value is <= 65529 because a digit can add only 9 at most.
What does `!` mean?
-
Microsoft > Learn > Documentation > .NET > Visual Basic > Single Data Type
This is not exactly GW-BASIC, but it is a descendant with some traces of its syntax.
Type Characters. Appending the literal type character
Fto a literal forces it to theSingledata type. Appending the identifier type character!to any identifier forces it toSingle.
Code : LINENUM2.BAS
- Saved in the file
10 PRINT 10 20 PRINT 20 30 GOTO 50 40 PRINT 40 ' Pass 50 PRINT 50 60 PRINT 60 55 PRINT 55 ' Rearranged as increasing order 70.5 PRINT 70.5 ' Syntax rrror; 70 .5 PRINT 70.5 65530 PRINT 65530 ' Syntax rrror; 6553 0 PRINT 65530! 65529 PRINT 65529 ' 65529! 65531 PRINT 65531 ' Syntax rrror
- Loaded on the GW-BASIC console
10 PRINT 10 20 PRINT 20 30 GOTO 50 40 PRINT 40 ' Pass 50 PRINT 50 55 PRINT 55 ' Rearranged as increasing order 60 PRINT 60 70 .5 PRINT 70.5 ' Syntax rrror; 70 .5 PRINT 70.5 6553 0 PRINT 65530! ' Syntax rrror; 6553 0 PRINT 65530! 65529 PRINT 65529! ' 65529! Syntax error
- Output
RUN 10 20 50 55 60 Syntax error in 70 Ok
-
-
I intended to write GW-BASIC code, but I actually executed it in QuickBASIC.
-
Unexpectedly, many things are allowed, including aspects that were not even considered.
Ex) Line numbers including decimal points, reversed, or exceeding 65535 ……Code : LineNum.bas
'-10 print "-10" ' A negative line number causes an error 0 CLS 10 PRINT "10" 15 GOTO 30 20 PRINT "20" ' Pass 30 PRINT "30" 25 PRINT "25" ' Decreasing numbering is OK 30.5 PRINT "30.5" ' Decimal point is allowed A: GOTO C B: PRINT "B" C: PRINT "C" ' Alphanumeric line labels can be mixed PRINT "No label" ' Lines without labeling is also available 65535 PRINT "65535" 65536 PRINT "65536" ' The line number can be over 65536
10 30 25 30.5 C No label 65535 65536
-
References
- The BASIC Program Line from QUICKBASIC 4.5 Help file
- Q73084: Differences Between GW-BASIC and QBasic
-
Remember how I felt when I was a primary school student
Code : DrawCar.bas
CLS SCREEN 12 '640 x 480 / 16 colors wid% = 640 'Can I get these parameters automatically? hei% = 480 'Border LINE (10, 10)-(wid% - 10, 10), 15, B LINE (10, hei% - 80)-(wid% - 10, hei% - 80), 15, B LINE (10, 10)-(10, hei% - 80), 15, B LINE (wid% - 10, 10)-(wid% - 10, hei% - 80), 15, B 'Memo LOCATE 3, 5 PRINT "QuickBasic : My Nostalgia" LOCATE 3, 67 PRINT "2022.02.09" 'Body LINE (wid% / 2 - 100, hei% / 2 - 100)-(wid% / 2 + 100, hei% / 2), 7, BF LINE (wid% / 2 - 200, hei% / 2)-(wid% / 2 + 200, hei% / 2 + 100), 7, BF 'Windows LINE (wid% / 2 - 100, hei% / 2 - 80)-(wid% / 2 - 60, hei% / 2), 9, BF LINE (wid% / 2 - 50, hei% / 2 - 80)-(wid% / 2 - 5, hei% / 2), 9, BF LINE (wid% / 2 + 5, hei% / 2 - 80)-(wid% / 2 + 50, hei% / 2), 9, BF LINE (wid% / 2 + 60, hei% / 2 - 80)-(wid% / 2 + 100, hei% / 2), 9, BF 'Wheels CIRCLE (wid% / 2 - 90, hei% / 2 + 100), 50, 8 CIRCLE (wid% / 2 + 90, hei% / 2 + 100), 50, 8 PAINT (wid% / 2 - 120, hei% / 2 + 100), 8, 8 PAINT (wid% / 2 + 120, hei% / 2 + 100), 8, 8 CIRCLE (wid% / 2 - 90, hei% / 2 + 100), 30, 7 CIRCLE (wid% / 2 + 90, hei% / 2 + 100), 30, 7 PAINT (wid% / 2 - 90, hei% / 2 + 100), 7, 7 PAINT (wid% / 2 + 90, hei% / 2 + 100), 7, 7 END
-
Practice of functions :
BEEPSOUNDPLAY -
Run by MS QuickBASIC 4.5
Code : Xerxes.bas
- Using
SHELLfunction to borrow theCLScommand from DOS
SHELL "CLS" PRINT "I am generous"
I am generous
Code : Sound.bas
- Refer to ☞ https://en.wikibooks.org/wiki/QBasic/Sound
SHELL "CLS" 'BEEP PRINT "BEEP" BEEP PRINT CHR$(7) SLEEP 'SOUND PRINT "SOUND" + CHR$(13) 'CHR$(13) : Line break FOR i% = 1 TO 30 SOUND i% * 100, 1 'Frequency, Duration NEXT SLEEP 'PLAY PRINT "PLAY" + CHR$(13) PLAY "L16 CDEFGAB>C" '> : Move up one octave SLEEP
Code : SchoolBell.bas
- Play the same song with the keys of both C major and C minor
SHELL "CLS" PRINT "School Bell" PRINT "C major" PLAY "MS G8G8A8A8 G8G8E4 G8G8E8E8 D6 P8" PLAY "MS G8G8A8A8 G8G8E4 G8E8D8E8 C6 P8" PRINT "C minor" PLAY "MS G8G8A-8A-8 G8G8E-4 G8G8E-8E-8 D6 P8" PLAY "MS G8G8A-8A-8 G8G8E-4 G8E-8D8E-8 C6 P8"
- Using
-
PRINT, notprintCode : HelloWorld.bas
print "Hello World!"
Call to undefined sub 'print'
print("Hello World!")
Call to undefined sub 'print'
print 'Hello World!'
Call to undefined sub 'print'
How can I make
printwork?PRINT "Hello World!"
Hello World!
The secret was UPPER CASE!
PRINT 'Hello World!'
''seems to be used for single-line comments.'You can't see what I'm saying.'ㅋ
Links
- BASIC
- BASIC (Wikipedia)
https://en.wikipedia.org/wiki/BASIC
- BASIC (Wikipedia)
- QuickBASIC
- QuickBASIC (Wikipedia)
https://en.wikipedia.org/wiki/QBasic
- QuickBASIC (Wikipedia)
- QBasic
- Online IDE for QBasic
https://repl.it/ - QBasic/Full Book View (Wikibooks)
https://en.wikibooks.org/wiki/QBasic/Full_Book_View - Programmed Lessons in QBasic (Central Connecticut State University)
https://chortle.ccsu.edu/QBasic/ - QBasic Tutorials and Articles (QBasic Cafe)
https://www.qbasic.net/en/qbasic-articles/
- Online IDE for QBasic
- QB64
- QBasic / QB64 Tutorial List (SchoolFreeware)
https://www.schoolfreeware.com/QBasic_Tutorials_-_QB64_Tutorials_-_Programming_And_Code_Examples.html
- QBasic / QB64 Tutorial List (SchoolFreeware)


