NOTE: This blog series is obsolete. Head on over to the Harmony/Melody Club where you'll find information on the new Linaro compiler and the new CDFJ coprocessor/bankswitch scheme that has many improvements over DPC+.
NOTE: This is an advanced Atari 2600 programming series. It will not cover basic things like triggering a Vertical Sync, what a Kernel is, why a timer is used in Vertical Blank, etc. If you need to learn that, check out with the following:
- Collect - detailed development of a 2K game
- 2600 Programming for Newbies - use the Sorted Table of Contents topic that's pinned at the top in order to easily access the tutorial topics in order.
Beginnings of the Arena Kernel
Games normally use multiple Kernels - for Collect 2 we already have a Menu Kernel, a SpiceWare Logo Kernel, and a Score Kernel. We also have a simple kernel that generates the rainbow display. In this update we're replacing that with the beginnings of the Arena Kernel.
Collect 2 is just a simple example project to get you up to speed, so we're only going to use the 2 players and the playfield. As in Collect, the right side of the playfield will be repeated or reflected so we don't have to update PF0, PF1 and PF2 twice. Once you get the basics of DPC+ ARM down you can reference my other projects to see how to add an asymmetrical playfield, the missiles, and/or ball.
6507 Revision, Display Data
Seven new datastreams have been added in Display Data:
- ArenaPF0 - for PF0
- ArenaPF1 - for PF1
- ArenaPF2 - for PF2
- Player0DataStream - for GRP0
- Player1DataStream - for GRP1
- Color0DataStream - for COLUP0
- Color1DataStream - for COLUP1
We're using Fractional Data Fetchers for the playfields as this lets us save a lot of RAM & ROM by repeating a single value over multiple scanlines. In Collect2 each value will be repeated 8 times. There's 22 bytes of data in each of the ArenaPFx datastreams so our Arena will be 176 scanlines in height. This is a little smaller than the original rainbow display, so the ScoreKernel was modified to compensate.
The remaining datastreams will be read using the normal Data Fetchers. Each datastream is 176 bytes long and the first value in each will be used for the first scanline, the second value for the second scanline and so on.
6507 Revision, New Arena Kernel
The simple rainbow kernel has been replaced with this:
ldx #8*22 ; use X for KernelLoop counter... lda #<DS_GRP0 ; 2 11 sta GRP0 ; 3 14 - @any, for next scanline as VDELP0 is on ArenaLoop: sta WSYNC lda #<DS_GRP1 ; 2 2 sta GRP1 ; 3 5 - @0-22, also triggers update of GRP0 lda #<DS_COLUP0 ; 2 7 sta COLUP0 ; 3 10 - @0-22 lda #<DS_COLUP1 ; 2 12 sta COLUP1 ; 3 15 - @0-22 lda #<DS_PF0 ; 2 17 sta PF0 ; 3 20 - @0-22 lda #<DS_PF1 ; 2 22 sta PF1 ; 3 25 - @71-28 lda #<DS_PF2 ; 2 27 sta PF2 ; 3 30 - @0-39 lda #<DS_GRP0 ; 2 32 sta GRP0 ; 3 35 - @any, for next scanline as VDELP0 is on dex ; 2 37 bne ArenaLoop ; 2 39 - 3 40 if taken
For the lines that update TIA registers, the @ denotes acceptable cycles for which the registers can be updated. If they're updated at other times you run the risk of sheared graphics. I go into more detail about shearing in Step 4 of the Collect 2K series. For most of the registers you'll see @0-22 as these are the cycles that occur during Horizontal Blank.
PF1 and PF2 have a wider range of acceptable values as we know they can't move around onscreen. The limit of @0 for PF0 and PF2 are because we might have Arena layouts that use the reflected playfield and some that use the repeated playfield - you can see an example of that in Step 9 of Collect 2K. The @71-28 probably looks odd for PF1 - the range starts at cycles 71 of the prior scanline and ends with cycle 28 of the current scanline.
Normally updates to GRP0 would have the @0-22 requirement, but by turning on VDELP0 we eliminated that. Very handy as those cycles are already tight - and it will become tighter once we implement sprite reuse.
6507 Revision, Other Changes
- Constants - 7 new aliases defined for the Arena Kernel
- VerticalSync - initializes NUSIZ0, NUSIZ1, VDELP0 and VDELP1 for the ArenaKernel
- VerticalBlank - initializes the datastreams and positions the 2 players for the ArenaKernel
- echo statements - added defines for the Arena Kernel datastreams
C Revision, MenuVerticalBlank
Function MenuVerticalBlank() was modified to update the colors in Color0DataStream and Color1DataStream to match the current TV-TYPE setting.
So what's it look like?
The singe white lines in the 4 corners were used to confirm the vertical alignment of the players.
Since we're using the players to draw everything, there's no need to limit ourselves to collecting boxes. Instead, I thought we could collect objects found in classic Atari games.
The players are represented by espire8's Humanoid from Frantic, though the red was changed to either blue (left player) or green (right player).
Task for you
Modify the player/color datastreams to contain objects from other Atari games. Each datastream needs to be 176 bytes line. To help make sure they're the right size I've already added a few echo statements to the source code: