Tuesday, 6 August 2019

My "Black Magic" BASIC speed-up tricks


Recently I became aware of Steven Wozniak's short time working for Atari to create the major arcade hit "Breakout." I hadn't realized that this experience was in part what led him to design the Apple II. He wanted to be able to create games just using software rather than huge numbers of ICs. No surprise that when he got the Apple 1 working and finished making a BASIC for it (called "integer Basic" but originally called "Game Basic") that he programmed a simple version of Breakout out called "Little Brick Out." It was really hard finding source code for the game, which is surprising considering the influence of it. There are thousands of versions of Breakout programs out there, but they can all trace their origins to Atari Breakout and Woz's program.

I eventually gave up trying to find a copy of it and some way to run it on an emulator. Instead I turned to the MC-10's implementation of the Breakout concept in the form of one of the programs for Tandy's "Game Pack" for the MC-10. These games were examples of the fewer than a dozen official programs released for the machine. It is not a very good program. It is slow. The paddle doesn't move quickly enough, so sometimes it is impossible for you to move it to the ball in time causing you to lose a ball through no fault of your own.This is a terrible sin for a game to commit. I decided to apply some of the tricks that I've developed over the last decade to speed up program execution. Carlos Camacho calls these my "black magic" tricks. Here's an incomplete list:
  • remove all spaces in code except in strings 
  • put frequently used subroutines at the top of the program
  • use single letter variables
  • replace common numeric constants with variables
  • renumber lines by stepping by 1 and keep main loops at the top of the program with the shortest line numbers
  • pre-calc commonly used values and store them in arrays
  • use . instead of 0 when assigning variables, in calculations, or in logical comparisons (this only works in MS BASICs)
  • replace IFtestANDtestTHEN with IFtestTHENIFtest
  • replace IFvar<>0THEN with IFvarTHEN (also good for test >0 if you know value will only be positive)
  • pack lines using colons. Use search and replace to see if a line number is called from elsewhere in the program, if not add it to previous line using colon (to max line length of 128)-- use ? instead of PRINT to pad lines even further (beyond the 128 limit)
  • use for ONK(keyinput)/GOTO or ONK(keyinput)GOSUB instead of multiple IF/THENS for parsing key input
  • use NEXT to return from GOTOs out of main loop defined by a FOR/NEXT loop (you can use FORA=1TO0 to define an endless loop which can be terminated by setting A to 1 within the loop or a subroutine)
  • USE POKEs instead of PRINT@s
  • reuse small # of scratch variables rather than assigning new variables for each unique task. Keep your list of variables as small as possible
  • DIM all variables, including non-arrays at program start up, with the most frequently used variables (e.g. X,Y coordinate for object used in graphic animation) at the front of the list and non-speed-critical variables at the end of the list (e.g. SCORE, HIGH SCORE, Player name)

I applied many of these to BREAKOUT for the MC-10. I renamed my version BRICKOUT in honour of Woz's original program. Now the paddle moves twice as fast as the original. But if you lightly tap the keys you can still make the paddle move one pixel at a time for fine tuning. I changed the way the number of balls is reported to a countdown to 0 rather than expecting the player to simply know that you get 5 balls. I added a few instructions and a title screen. I also added performance assessment messages at the end of the game, which I had noticed were a part of the Woz's original version. I made a few other minor cosmetic changes as well.

Here's what my version looks like:




I was inspired by some of Woz's enthusiasm, which is well on display here:


No comments:

Post a Comment