kamakazi, on Wed Nov 3, 2010 3:58 PM, said:
Nope...this game is for the 2600 without any accessory help. No SC, no Harmony...just the 2600. On a side note, I've also started this project on the XE computers as well with the hopes of being able to port it to the 5200. I'm currently using Atari BASIC for the code work until I can find the assembly cartridge. So far, this version of my game idea allows for 180 blocks on the screen. The XE version is more complete than the 2600 version with a working block logic, player controls, and a routine for placing 20 randomly placed and randomly colored blocks on the screen. I still have to work out the logic for matching and getting the blocks to drop one line at a time.
Well, that might rule out the feasibility of your mockup screen, in which you show 13 rows of 10 blocks-- unless the 13th row is empty except for the block you're getting ready to "fire" into the grid. You might be able to pull off 12 rows of 10 blocks using 120 bytes of RAM, but that would leave you only 8 bytes of RAM for everything else-- including the stack. That's assuming you use 1 byte of RAM for each block, which would allow the greatest flexibility-- any color in any block. If you use indexed colors for the blocks, you could squeeze more blocks into less RAM by storing 2 or more indexes in each byte-- but that would also make it more troublesome to draw the colors on the screen, because you'll need to extract the index for each block, which would involve bit masking and bit shifting. As it is, drawing 10 blocks of color on a line, where each block can randomly be any of several colors, takes up all or most of the time on each line, leaving almost no time for anything else, so 1 byte per block would be the way to go, in my opinion.
Here's what I was thinking: If you set up the two players and the two missiles just right-- giving them fixed positions on the screen, and fixed graphics (all pixels on)-- then you can draw 10 blocks of random colors using just the background, players, and missiles, with each block being 16 clocks wide. The black border around the screen (or blanking) would form the walls of the grid. The players and missiles could be positioned as follows:
BK BK P0 M0 BK BK P0 M0 BK BK P1 M1 BK BK P1 M1 BK BK P0 M0
Legend:
BK = Background
P0 = Player 0 (3 copies, medium spacing)
M0 = Missile 0 (3 copies, medium spacing, octuple sizing)
P1 = Player 1 (2 copies, medium spacing)
M1 = Missile 1 (2 copies, medium spacing, octuple sizing)
Each BK, P0, M0, P1, and M1 element that's listed above is 8 clocks wide, but each block or grid cell is 16 clocks wide, so I listed the elements as "half blocks" to clarify the positioning and spacing of the players and missiles. For simplicity, I'll number the half blocks from left to right as HB1 ("half block 1") through HB20 ("half block 20"), as follows:
HB1 = Background
HB2 = Background
HB3 = Player 0 (medium copy)
HB4 = Missile 0 (medium copy)
HB5 = Background
HB6 = Background
HB7 = Player 0 (far copy)
HB8 = Missile 0 (far copy)
HB9 = Background
HB10 = Background
HB11 = Player 1 (main copy)
HB12 = Missile 1 (main copy)
HB13 = Background
HB14 = Background
HB15 = Player 1 (medium copy)
HB16 = Missile 1 (medium copy)
HB17 = Background
HB18 = Background
HB19 = Player 0 (main copy)
HB20 = Missile 0 (main copy)
The ball (drawn with the playfield color) can be bouncing around the screen to provide an obstacle, as you described, with its position being updated between frames.
You can start loading the colors for each line before the end of the previous line if you load them in this order: COLUP1 (just after HB16 has finished being drawn), then COLUBK (just after HB18 has finished being drawn), then COLUP0 (just after HB20 has finished being drawn, or at the beginning of the horizontal blank). That gives you the colors for HB1 and HB2 (COLUBK), HB3 and HB4 (COLUP0), and HB11 and HB12 (COLUP1). Then you have time to draw the ball, preload the X and Y registers for when you need to store some colors more quickly, and load/store the accumulator for the colors that don't need to be stored as quickly. As I was envisioning it, the entire sequence would be as follows:
LDA abs : STA COLUP1 -- 7 cycles (21 clocks) -- STA after HB16 has been drawn -- Takes care of HB11 and HB12
LDA zpg : STA COLUBK -- 6 cycles (18 clocks) -- STA after HB18 has been drawn -- Takes care of HB1 and HB2
LDA zpg : STA COLUP0 -- 6 cycles (18 clocks) -- STA after HB20 has been drawn -- Takes care of HB3 and HB4
LDX zpg -- 3 cycles (9 clocks) -- An index for the ball's graphics
LDA abs,X : STA ENABL -- 7 cycles (21 clocks) -- Turn the ball on or off for the current line
LDX abs -- 4 cycles (12 clocks) -- Preload the color for HB19 and HB20 (to be stored later)
LDY abs -- 4 cycles (12 clocks) -- Preload the color for HB15 and HB16 (to be stored later)
LDA zpg : STA COLUBK -- 6 cycles (18 clocks) -- STA after HB2 has been drawn -- Takes care of HB5 and HB6
LDA zpg : STA COLUP0 -- 6 cycles (18 clocks) -- STA after HB4 has been drawn -- Takes care of HB7 and HB8
LDA abs : STA COLUBK -- 7 cycles (21 clocks) -- STA after HB6 has been drawn -- Takes care of HB9 and HB10
STX COLUP0 -- 3 cycles (9 clocks) -- STX after HB8 has been drawn -- Takes care of HB19 and HB20
LDA abs : STA COLUBK -- 7 cycles (21 clocks) -- STA after HB10 has been drawn -- Takes care of HB13 and HB14
STY COLUP1 -- 3 cycles (9 clocks) -- STY after HB12 has been drawn -- Takes care of HB15 and HB16
LDA abs : STA COLUBK -- 7 cycles (21 clocks) -- STA after HB14 has been drawn -- Takes care of HB17 and HB18
Total time used = 76 cycles
Of course, this scheme was based on using expansion RAM for some of the blocks/colors, and zero-page RAM for some of them. In this scheme, 4 bytes of zero-page RAM are used for 4 blocks on each row, and 6 bytes of expansion RAM are used for the other 6 blocks on each row. The ball's index would be stored in zero-page RAM, with its value being constant for the entire frame, and updated between frames. Since there are only 76 cycles on a line, and this scheme takes up all 76 cycles, the entire kernel would have to be unrolled, with the load address for each block-- as well as the ball's graphics-- being hard-coded for each line. The ball's graphics can be stored as a ROM table that would cover the entire height of the screen, and the index would point to the spot inside the ROM table where you want to load the ball's graphics from. (Remember, the addresses are hard-coded for each line, so the value of the index can remain fixed for a given frame, with each line having a different address that the index would be added to.)
I was thinking you could have 24 rows of blocks in the grid, so that would be 4x24=96 bytes of zero-page RAM for some of the blocks, and 6x24=144 bytes of expansion RAM for the rest of the blocks, which would require using at least 256 bytes of expansion RAM (i.e., at minimum, the CBS RAM+ bankswitching scheme).
If you go with no expansion RAM, and store everything in page zero, you would free up 6 cycles on each line-- although they might not do you much good, because you wouldn't have enough time to use indexed addressing to load all the colors, so you'd still need to unroll the entire kernel. But if you have 12 rows of blocks, you could use 120 bytes of RAM for the blocks, 1 byte for the ball's index, 1 byte for the block in row 13 (that's waiting to be fired), 1 byte for the column that the player is in (i.e., the "firing mechanism," as well as the unfired block), and 1 byte for a "game state" flag. That's 124 bytes, leaving 4 bytes for other things-- including the stack, so at most you could have 2 nested subroutine calls. If you squeeze the column and game state flag together into 1 byte, and have no more than 1 active subroutine call at a time, then you could use 3 bytes for a score. But that doesn't leave any room for any temporary working storage RAM, so you might want to go with 11 rows of blocks instead, which would free up 10 more bytes of RAM. And you'll probably want to use 1 byte for the position of the moving block, to make it easier/quicker to update its position and check for collisions.
The unfired block can be drawn with the playfield-- but once the block has been fired into the grid, it would be drawn with the normal grid blocks, because you won't have any time during the grid lines to draw the playfield. Since the blocks inside the grid-- including the moving/fired block-- will be drawn with the background, players, and missiles, you won't be able to use the 2600's collision detection. Fortunately, there are only 128 color values, so you can use bit 0 to indicate which block is the moving/fired block, and which blocks are stationary. In other words, the color value of each block in the grid will either be even or odd, with even values (bit 0 off) indicating a stationary block, and an odd value (bit 0 on) indicating the moving/fired block. Once the fired block hits either the top border of the grid or a stationary block, bit 0 would be turned off to indicate that it's now become a stationary block.
As you're moving the fired block, you can check the color of the grid cell immediately above it to see if that cell is empty-- presumably a dark gray color, since the border around the grid will be black (blanking). And as the ball is bouncing around you can check its position against the colors in the grid's cells to see if it needs to bounce off of a block. If the ball hits the block that has bit 0 turned on, that means the ball hit the fired block, so you can make that block disappear (if I understood you correctly when you described how the bouncing ball would provide an "obstacle").
Anyway, that's a rundown of how I was thinking you could do it. If my ideas don't "work" for your vision of the game, then at least I had fun puzzling out how it *might* be done!

I actually had to force myself to stop thinking about it, because I was having so much fun trying to solve the challenge that I was ready to start writing it myself.

I was even thinking about the kinds of sounds you can use. And since it's *your* game idea, I didn't want to steal it!
Michael