-
Content Count
208 -
Joined
-
Last visited
Posts posted by AkashicRecord
-
-
Here's the first .bin I can share...it doesn't do much, but it sort of illustrates the fine motion of moving something 1 scanline each frame. After some number of frames the scanline with which to start (and stop) drawing is reset back to a starting point, and the playfield color is decremented.
As for the sprite drawing, this example is really just setting the color to NOT black. Actually, this isn't *entirely* true, because there is a bug, and I am still resetting the sprite position even though I don't need to. As I mentioned in an earlier post, if I am going to just reset the sprite color, then I can reset its horizontal position *much* earlier (like at the start of the frame during VBLANK) and forget about it until the next frame...if it moved.
Not sure if this will execute on real hardware...
-
2
-
-
While working out the game's playfield I realized that one of my 2P game modes will be easiest to implement, and should be the first place to start.
This mode has 2P with separate game fields, but the fields are replicated...both players contribute to clearing a shared field, but on separate sides. Piece-swapping in this mode is also shared, but that's going too far right now.

What makes this mode easy to code is because the VCS playfield works exactly in the way I need it to work in order to implement this functionality.
-
So now I have to make a fairly large decision as to how smooth the game's animation will be. For now I'm mostly referring to the vertical animation.
Since the game field has 20 vertical positions, this breaks down into small chunks of scanlines per game field location. I'll call the vertical field position as Y, and this will be convenient since I'll generally be using the Y register as a scanline counter. I'll have the option of drawing the games pieces and inching them down the screen "in-between the grid" so to speak. This would give a much smoother and more fluid animation. The more basic and naive approach would have each piece drawn in only their fixed grid locations, but this might be considered "jerky" animation...
Applying this to horizontal positioning (in between the grid, again) would have some impact on ROM size since I'll have to use more coarse and fine position table data.
One other thing about the game's playfield is that I may want to literally turn it upside-down (or at least think about it upside-down) because this type of code shaping will make good sense given the idiomatic decrement-and-branch nature of assembly.
If I approach my game logic in the same fashion, then everything will translate into code without much issue. Remember, when we decrement a value, we get a "free" comparison against zero that we can always use.
-
I'm taking a quick JuMP over to timers, timing, and frame counting.
I threw together a boring .bin which cycles the playfield color every few frames. The reason for this silly test is that frame-level timing like this is what will essentially determine the game's maximum difficulty as far as how fast a player's piece will advance at later stages. This is also where I need to look at the granularity of input polling, and so on. This has a huge effect on how the game will play and feel, so it has to be perfect...some things will probably benefit from use of the built-in timers.
Later I'll have a look at converting the color cycling into a sprite drawing routine that will draw the sprite on specific scanlines, incrementing every so many frames, simulating the game's piece advancement.
-
As for music (if I have the ROM and CPU for it) I was thinking of either writing my own music, or at least borrowing from one of the greats:
...it's certainly not possible for any sort of full rendition of Rachmaninoff; Hell, it's impossible for most people to even physically play his music...

That said, I've done game music in the past, since I'm also (unofficially, and not commercially) a DJ and electronic music composer. My past projects however, afforded me much more freedom, although this is most certainly off-topic:
-
2
-
-
Nice! I certainly haven't seen that. Thanks for sharing!
(I can imagine that you have all by now noticed that something like the Tengen Tetris was what I had in mind. In my opinion, that is by far the superior Tetris...)
-
Has anyone ever heard an Atari 2600 rendition of Bradinsky?

(it might not be possible...)
-
Earlier, I had an idea regarding the game's 10x20 playfield bitmap (times two, for 2P.) Since I overestimated the RAM usage by a decent amount, I may be able to use 2 bytes per "line", for a total of 40 bytes for a single player. This is obviously 80 bytes for two players, and I need at least a few variables for the nice things...but all is not lost. I may have to ditch my self-mogrifying kernel idea, but at the same time I will be gaining 6 bits on each "line" of the 10x20 field that I can potentially use as some sort of "status" flag which I can test on a line-by-line basis (again, this is the game's "lines," NOT scanlines that I'm referring to.) By doing so, I could drive some of the kernel's decision-making logic by using these extra bits to signal specific sprite-drawing scenarios or strategies...such as when the 1P and 2P sprites "overlap" on some scanlines, as this drastically changes the kernel logic when both player sprites need to change.
-
I made an error (on the good side, thankfully) in my previous calculations of RAM usage for the playfield, especially for two players. Luckily, I overestimated the RAM usage by double! Which leads me to my next concern:
My more advanced plans for kernel design is to use some "self-mogrifying" code executed directly from RAM. This means that I would be dynamically rewriting operands and opcodes in memory prior to their execution. I'm not going to start here however. My next actual concern must be the playfield bitmap, since this is essentially what is going to drive my kernel (especially in regard to horizontal and vertical positioning) based on scanline and frame numbers...
-
And here's a quick example of what I was briefly mentioning. This is the same image of the Square block being rendered, but with it's sprite color being changed to BLACK on the remaining scanlines, while also enabling DEBUG colors in Stella. Setting the playfield priority eliminates a little black "hole" on the floor where the piece would be drawn in black over the playfield floor at the bottom. You can easily see the "striping" of the sprite going down the screen, but this is not visible:
-
....there may be a way for me to kind of "cheat" at drawing some of the game pieces...
In an effort to minimize data and updates, and thus CPU, I could simply set sprite colors to BLACK (while still leaving them ON) and drawing the playfield with priority over the sprites. This could allow me to set the coarse and fine sprite position very early (once per frame) and simply set and decrement the color gradient on the appropriate scanlines. On the scanlines below the piece, set the sprite color to black and ignore everything until next frame, and rinse / repeat. Plus, once the color is set to black, it will stay that way until I change it on the next frame.
-
I spent a few hours experimenting with various settings of the NUSIZ0 register, and it does indeed look like most pieces will be covered by just modifying a single bit in that register, as I expected; the sprite data is hardly required to change (and this is a good thing.)
A lot of pieces can also be drawn by smearing quad and octuple-sized missiles over a few scanlines. The "T" "L" and "J" blocks (when rotated flat) need to cover 12 pixels across, so this can be accomplished by setting 3 bits of a quad-sized sprite, or 6 bits of a double-sized sprite...another option is a full 8-bit single-sized sprite with a quad-sized missile, but that might be overdoing it a bit... the "T" block is probably going to be the most finicky piece to render.
Here is the output of a naive drawing routine with hardcoded positioning to get an idea of how the flat Line piece might look on screen. I've simplified the playfield for testing...
...and here's something close to the square piece on the 2P side of the field:
-
I'm attaching individual image mockups of the seven game pieces to work from. The sprite data should be pathetically simple for these. There are a total of 19 orientations that need to be accounted for. There are some constraints regarding positioning depending on the piece and it's current rotation...for instance, a Line piece rotated flat can only move left or right 6 ways, when it is rotated vertically, it can assume 10 different horizontal locations.
As for the drawing and positioning, it is probably best to precalculate everything in tables, indexed by the piece's current position. Horizontal movement and positioning will require delays of a certain number of CPU cycles; we should only need a granularity of about 12 TIA color clocks to hit each position for our game grid as it translates to the screen (easier said than done). For vertical positioning, we just need to skip a few scanlines...
-
2
-
-
Cool project and coding background, looking forward to seeing this!

Anyone know where the ROM for Chetiry is? I thought they used to be linked.
It appears that the Internet Tetris Gods (see YouTube video above) have once again graced me with their benevolent presence; this time in the form of lost source code:
Searching the Internet Wayback Machine for one of my old expired domains revealed a strange little Easter Egg from exactly this day, October 13th, almost 20 years ago... Somehow I let a code listing slip through just long enough for it to be archived. Damn.
https://web.archive.org/web/19991013125024/http://pknet.com:80/xtrix/HTML/S/main.C.html
-
3
-
-
Here's what a single-player field might look like with (glitches) and a cycling of the level progression... I'm kind of debating on whether or not just to use the 2-player layout even for 1-player....possibly with just using the empty space for the number of lines or what have you, as well as reserving some black lines at the top.
I usually liked to use a small "staging" area for the next incoming piece that was slightly above the game board so that you could have an actual chance toward the end of your game...
Later on I should have some drawing tests for the basic game pieces...
-
In the worst cases, an entire frame (or more) can be consumed processing anything "hard" or CPU-intensive. At best, this gives the player a small break (while still hopefully hitting on input polling in good fashion) on fast-paced levels, but I don't feel that I'lll need to go that route...yet.
A standard 10x20 "Well" requires about 25 bytes at best for the simplest possible bitmap representation of possible playfield states, and this breaks down into two 5-bit halves of two reflected TIA registers. There is a 160 scanline "resolution" which breaks down into "chunks" of 8 scanlines for drawing game pieces and playfield blocks. (Can we use a quad-sized player and octuple-sized missile to fill 40 solid pixels???)
This is where I can imagine using indexed permutations of 5 (which is essentially...120 states.) Using a lookup table could shave some bytes off of each player's RAM usage, while still leaving 1 bit available for some other use...such as a "line clear" flag(?) with the permutation tables still possibly fitting within a single page boundary... (I hope I got that right...) The processor status flags might be more useful for signaling the "line clear" state, however. -
There's just something exciting about a cat and rainbow pop-tart pushing the envelope...
-
1
-
-
Awesome, sounds like you have really thought this out and understand the constraints of the system. I wasn't sure, since you are new on here. Many times when people (like myself) first start out, they don't realize that a particular idea they may have isn't actually possible.
In the kernel I am working on right now, I am writing to 12 TIA registers and 1 byte of RAM in a single 76-cycle stretch. As you can imagine, there isn't any space left in this kernel big enough to fit a burnt match in. I recently discovered that one of my VCS systems won't display this kernel correctly, which unfortunately sometimes happens when you push the system to the limits.
That's very impressive...basically pushing the envelope there.
I've put some brainpower into this one, and it helps having five other game versions under my belt. I was even looking at hardcoded indexed permutation tables in ROM to represent the game state since RAM is at a premium especially with 2 players.
-
Is it considered bad form to steal Battlezone's positioning code?

-
-
I'm not sure how you are planning to implement drawing the bricks. I don't know if it's best to use the players and missiles for a 10-wide grid. Each player gives you 8 "pixels", plus one more with the missile, giving you only 9 pixels. You could stretch/move/disable the missile row-by-row to "simulate" 2 pixels, but I think it might be easier to use just the playfield for drawing the bricks, using the players and missiles to draw thin borders around the play area. You could use "score mode" on the playfield, to draw the left side in Player0's color (COLUP0), and the right side in Player1's color (COLUP1).
Those are good ideas, and almost in line with what I was tinkering with. For a single player well, it would make sense to draw the borders using the second player and associated missile...it would look nice. Also writing #%00000001 to CTRLPF fixes the playfield and it fits very nicely, I had certainly overlooked that.
I only need about 16 pixels at most for a piece, so I was imagining that most pieces could be drawn by just modifying NUSIZx (and a color) a couple of times. Some pieces might be able to reuse the existing data from other previous pieces since they are so simple...4, 8, 12 or 16 pixels changing every four scanlines at most is the general case.
I would certainly have a competitive mode which has the associated players playfield in the color of their current "level" (100 lines cleared.) I was aiming for a 2-player coop within a shared well of at least 12x20, as well as some other modes like alternating 1P/2P or modes where one player rotates the piece, while the other moves it...possibly with the paddle, for instance.
-
1
-
-
I'm not sure how you are planning to implement drawing the bricks. I don't know if it's best to use the players and missiles for a 10-wide grid. Each player gives you 8 "pixels", plus one more with the missile, giving you only 9 pixels. You could stretch/move/disable the missile row-by-row to "simulate" 2 pixels, but I think it might be easier to use just the playfield for drawing the bricks, using the players and missiles to draw thin borders around the play area. You could use "score mode" on the playfield, to draw the left side in Player0's color (COLUP0), and the right side in Player1's color (COLUP1).
I know that might not be quite what you have in mind, I'm just thinking out loud. Are you wanting it to be like actual Tetris, where each shape in the grid keeps its original color? I'm not sure if that is possible with 2 screens, even if you were using a DPC+ chip to cheat with register-stuffing.
(I have never done this, SpiceWare or Thomas Jentzsch would know way more about this, but as simply as possible, that's when you have a second program running in the background on a separate faster CPU built into the cartridge with access to the 6507's registers. The HarmonyCart has support for this. This way, for example, you can keep executing sta COLUBK over and over. Normally, this would just keep writing the accumulator to the background color, which wouldn't ever change. Your background code would be changing the contents of the accumulator at the right times, so that the color could be precisely changed every 3 cycles. This would give you a maximum number of 18 color changes per line, which isn't enough room to fit two 10-wide grids.)
Thanks a lot for the information and suggestions.
I didn't have any plans to retain the piece colors once they are placed. I didn't think there was much capacity (even with external hardware) for that kind of bookkeeping. I don't even hardly want to change the playfield color (with a constant black background) except maybe a few times. The above tests with colored bars are just to measure screen real estate and to get a visual overview. The idea of a cart with an ARM processor is tempting though...ARM and Thumb assembly was my all-time favorite, especially the barrel shifter...
I'm still working out the logistics and to see what is actually possible with 76 clock cycles and preloading as much state change as possible before the target scanlines, because if this game was easy to write while still looking good, it would have already been done many times. Abusing the processor status flags will probably go a long way. In my testing late last night, I can change 11 values in RAM across a single scanline...but it was sometimes dropping Stella's FPS on my netbook from 60 to 15fps!

-
2
-
-
You might want to use a mirrored playfield for 2-player mode to make the screen look symmetrical. You would 5 bits of PF1 and PF2 for player 1, and 5 bits of PF2 and PF1 for player 2.
/salute
Sounds like a good idea, and it wouldn't impede the game logic in any way.
-
My next step is to flesh out the game pieces into some code. I'm envisioning judicious use of the sprite sizing register and the missile objects, if my understanding of the mechanisms are sound. Color changes might be hardcoded into each kernel, but I may investigate using the DCP/DCM illegal opcode to decrement the value in RAM.












A Two-Player Competitive and Co-Op "Tetris" for the Atari 2600 VCS
in Atari 2600 Programming
Posted · Edited by AkashicRecord
made a few minor changes to the first .bin to illustrate the more "jerky" animation method that I was talking about. After looking at this for a few minutes, it doesn't actually seem too bad to me... Tell me what you think! (The graphics are still in "super simple mode" to keep things simple at first.)
new-anim-test.bin