I was sorely tempted to move onto creating the enemy tanks so I would have something to shoot at (followed by explosions), but instead I opted to do something simpler and created the "fuel cells". In the original game there are eight of them placed as follows at the beginning of a game.

Since I was making the tanks a little different, I thought I would change the shape of the fuel cells too. I tried circles first thinking they would represent an overhead view of "oil drums", but I did not like the look of the circles at the scale required. On a raster display it's hard to get them to look sufficiently round. I also tried square and hex shapes, but at the end of the day the triangles just looked the best. I still might change but for now it's triangles.

I used the same technique as with tank drawing and generated code to efficiently render the triangles based on a central x,y coordinate.
/ Offsets in screen coordinates.
one, 000400 / 1 pixel.
two, 001000 / 2 pixels
tre, 001400 / 3 pixels.
for, 002000 / 4 pixels.
fiv, 002400 / 5 pixels.
six, 003000 / 6 pixels.
/ Draw triangle center coordinates.
tx, 0
ty, 0
/ Draw a right pointing triangle. Center: X in tx, Y in ty.
dtr, dap drx
lac tx
lio ty
sub six
sub two
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
add six
swap
sub six
swap
ioh
dpy-i 4200
add six
swap
sub six
swap
ioh
dpy-i 4200
add six
swap
sub six
swap
ioh
dpy-i 4200
sub six
swap
sub six
swap
ioh
dpy-i 4200
sub six
swap
sub six
swap
ioh
dpy-i 4200
sub six
swap
sub six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
ioh
drx, jmp .
/ Draw a left pointing triangle. Center: X in tx, Y in ty.
dtl, dap dlx
lac tx
lio ty
add six
add two
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
sub six
swap
sub six
swap
ioh
dpy-i 4200
sub six
swap
sub six
swap
ioh
dpy-i 4200
sub six
swap
sub six
swap
ioh
dpy-i 4200
add six
swap
sub six
swap
ioh
dpy-i 4200
add six
swap
sub six
swap
ioh
dpy-i 4200
add six
swap
sub six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
swap
add six
swap
ioh
dpy-i 4200
ioh
dlx, jmp .
I setup some constants with the coordinates of the fuel cells at the start of the game.
/ Initial fuel cell coordinates.
fcx, 746777
000000
031000
760777
017000
746777
000000
031000
000001 / End of data marker.
fcy, 036000
024000
036000
000000
000000
741777
753777
741777
In anticipation of having these cells move around the screen during the game I created "active" fuel cell tables.
/ Active fuel cell coordinates. acx, 0 0 0 0 0 0 0 0 0 acy, 0 0 0 0 0 0 0 0
At the beginning of a game I copy the initial coordinates to the active coordinates.
init cfi,fcx / Setup the coordinate table pointers. init cfo,acx lac (21 / Copy 17 initial cell coordinates to active. dac \tmp cfi, lio . / Get the next initial coordinate. cfo, dio . / Set the next active coordinate. lac \tmp sub (1 sza i / Is the value zero? jmp fr0 / Yes - Go to main loop. dac \tmp / No - Save counter. idx cfi / Increment table pointers. idx cfo jmp cfi / Next coordinate. fr0,
A couple of things about this. With the PDP-1, it is often the case that the only way to do a task efficiently is to use self modifying code. Since the PDP-1 did not have any indexed addressing modes for instance, the only way to "copy" these tables is to modify the addresses of the specific "load" (lio) and "save" (dio) instructions.
First the init macro gets the address at a specific label then inserts that address into an instruction at another label.
define init A,B law B dap A term
So the address of the initial coordinate table (fcx) is inserted into the lio instruction at cfi, and the address of the active coordinates (acx) is inserted into the dio instruction at cfo.
Furthermore, each time through the copy loop, the addresses at cfi and cfo are incremented by 1 via an idx instruction.
Easy peezy.
With the active fuel cell table updated a new subroutine was added to draw the fuel cells on the screen. It uses the same technique to step through the active cells.
/ Draw the fuel cells.
dfc, dap dfx
init in1,acx / Setup pointers to the fuel cell tables.
init in2,acy
init ex1,fcd
in1, lac . / Get the X center.
sub (000001 / Check for end of file marker.
sza i / Is the value zero?
jmp dfx / Yes - Done.
add (000001
dac tx / No - Set X center.
in2, lio . / Get the Y center.
dio ty / Set the Y center.
ex1, xct . / Show the triangle as left or right facing.
idx in1 / Advance to the next fuel cell.
idx in2
idx ex1
jmp in1 / Draw the next fuel cell.
dfx, jmp .
One more trick here that involves the "ex1, xct ." line of code. That line is initialized with the address of the following table ...
/ Fuel cells have either a left or right facing orientation. fcd, jsp dtl jsp dtl jsp dtr jsp dtl jsp dtr jsp dtl jsp dtr jsp dtr
... which contains a list of subroutine calls (jsp) to either the left or right facing drawing routines. The PDP-1 xct instruction executes the instruction that it's address points to as if it were "inline" at the point xct is executed.
So the fcd table's address is set into the xct instruction and for each fuel cell the appropriate drawing routine is called.
Ya this stuff makes my head hurt a little too, but it's really cool when it works.
Finally here is my main loop now with the call to draw the triangles.
fr0, load \ict, -4500 / Initial instruction budget (delay).
idx \frc / Increment frame counter.
jsp tnk / Draw and control the player's tank.
jsp dfc / Draw fuel cells.
jsp pop / Check to see if a shell has been fired.
jsp mov / Move any active shells.
count \ict, . / Use up rest of time of main loop.
jmp fr0 / Next frame.
Michael Gardi
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.