Jump to content


+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

  • Days Won


SpiceWare last won the day on October 10 2017

SpiceWare had the most liked content!

Community Reputation

5,516 Excellent

About SpiceWare

  • Rank
  • Birthday 11/09/1966

Contact / Social Media

Profile Information

  • Custom Status
    Medieval Mayhem
  • Gender
  • Location
    Planet Houston

Recent Profile Visitors

83,450 profile views
  1. Possibly. The coprocessor* drivers we currently have don't support that, so a new one would need to be designed and written. Getting the right people together for that isn't easy. * BUS, CDFJ, DPC+
  2. The ARM has no access to the 2600 hardware, everything must be read by the 6507 and passed to the ARM. For a regular one player game the 6507 code might look something like this: MAC READ_PADDLE_1 lda INPT0 ; 3 - always 9 bpl .save ; 2 3 .byte $2d ; 4 0 .save sty Paddle1 ; 0 3 ENDM That routine would be run on every, or every other scanline, during the kernel. How often depends on range of movement needed for your game. The ARM could be used help a little bit by doing this: MAC READ_PADDLE_1 ldx INPT0 ; 3 stx DSWRITE ; 4 ENDM which would differ the bpl/sty paddle1 logic for the ARM to handle. That would saves 2 cycles per scanline. I'm not aware of anybody having done this yet.
  3. Saw something today that reminded me of my unfinished Kaboom! Deluxe! hack. There's not much left to do in it, so I think I'll take a brief break from CDFJ and see if I can't finish the hack this weekend.
  4. My tutorial covers animating the players in step 14. I use a 4 frame animation, if you want just 2 frames then change the and #3 to and #1.
  5. The jitter/roll is caused because Chess does not trigger the Vertical Sync signal, which is required every 262 scanlines for a stable display. Games are designed around 192 visible scanlines, give or take. There's 262 scanlines total, so about 73% of the CPU time is spent updating TIA to create the display. Everything in the 2600 is under programmer control so you could shrink the visible portion of the display to give more CPU time to logic. My tutorial includes all the source. For games from back in the day you can find disassemblies that people have created, such as these at MiniDig. @DEBRO's also been posting disassemblies here at AtariAge, such as these: I'm sure there's more, I stopped looking. Perhaps a repository should be done for the disassemblies to make it easier to find them - or maybe a new Club should be created.
  6. SpiceWare


    I did something similar while working on Stay Frosty 2. For space savings we compressed the levels, but even with the ARM it was taking too long to decompress so I came up with this idea: It worked great. Stella doesn't emulate ARM processing time, so I recorded some examples and stepped thru the video to see the time. Level 1: Level 11: Level 31:
  7. 1) pretty much - though as part of the visualization you have to generate a Vertical Sync signal in the middle of your game logic, and if you don't do it at the right time the screen will jitter/roll. 2) Sure, that's what Video Chess does when the computer makes its move. On older TVs this was a non-issue, on newer TVs you might encounter a blue NO SIGNAL screen which may, or may not, cause issues. One way to prevent this is to continue to generate the Vertical Sync at the appropriate time, the player would just see a black screen during the logic. You might like to check out my tutorial, it documents the creation of a 2K game.
  8. Added score & timer Source Code Download and unzip this in your shared directory. Collect3_20200211.zip ROM for reference collect3_20200211.bin Score & Timer I like to implement routines for displaying the score early on in a project - you can see that in these early builds of Collect, Frantic, Medieval Mayhem, and Space Rocks. Even though I'm not ready to show the score, the display is very useful for showing diagnostic information such as in this build of Frantic were I used the score to display the results of the software sprite collision1 routines. One of the challenges when developing DPC+ARM code is that Stella does not emulate how long ARM code takes to run. As far as it's concerned, all ARM code will finish executing in 0 cycles of 6507 time. Because of this it's very easy to write something that will run just fine in emulation, but will cause screen jitters and/or rolls, or even a fatal crash when run on a real Atari. We're already checking timers in our 6507 code, so we can easily save those values and display them in the score. For the game we need to display two scores and a timer. In the 2K version of Collect I used the playfield to show that information. For Collect 3 we're going to do this: players are set to 3 copies with medium spacing players are positioned so the middle copies occupy the middle 16 pixels of the display playfield pixels are turned on behind all copies of the players just like the ShowTwoColorGraphic routine used to display the menu, the players are colored black and used as stencils playfield color is changed on the fly so each group of 16 pixels has a different color use a 3 pixel font, and 1 pixel spacing, so we can display 4 digit scores for each player For diagnostic purposes the difficult switches are used to control what is displayed: Left B and Right B - Score and Timer for the game Left A and Right B - Test Pattern Left B and Right A - Timing Remaining in Vertical Blank and Overscan Left A and Right A - sprite X Y positions The test pattern shows an improvement over the prior version of the score & timer kernel that I used for the unfinished DPC+ tutorial: Previously the update of player1 for the right player's score was 1 pixel too late, resulting in bit 7 of the timer being shown. I worked around it then by designing the font to not use bit 7. PrepScoreDatastreams() A new function was added to prepare the datastreams for the score kernel. Since we're using a skinny font, each datastream will contain graphics for 2 digits. MergeCharacters() handles this: void MergeCharacters(int datastream, int left_character, int right_character) { int i; unsigned char *stream = RAM + datastream; unsigned char *left = ROM + _FONT + left_character * _FONT_HEIGHT; unsigned char *right = ROM + _FONT + right_character * _FONT_HEIGHT; for (i=0;i<_FONT_HEIGHT;i++) *stream++ = ((*left++) & 0xf0) + ((*right++) & 0x0f); } The character values of 0-15 correspond to graphics of 0-9 and A-F so that hex values can be shown using simple masking and/or bit shifting. These two calls prep the right score to show 4 hex digits of the frame counter: MergeCharacters(_BUF_SCORE1_A, (frame >> 12) & 0x0f, (frame >> 8) & 0x0f); MergeCharacters(_BUF_SCORE1_B, (frame >> 4) & 0x0f, frame & 0x0f); This also means we'll be using binary-coded decimal (BCD) for the score, which you should already be familiar with from writing 6507 code. Character values 16 and above are used for special characters, such as the colon used to show 2:00 in the timer display. MergeCharacters(_BUF_TIMERA, 2, 17); MergeCharacters(_BUF_TIMERB, 0, 0); Constants are defined for these to make the source code easier to understand: MergeCharacters(_BUF_TIMERA, 2, _FONT_COLON); MergeCharacters(_BUF_TIMERB, 0, 0); The 6507 does not support hardware multiplication, so score fonts tend to be designed to use 8 scanlines. This is because times 8 can be calculated using 3 ASL commands. The ARM does support hardware multiplication, so the font for Collect3 uses 7 scanlines to show we have that option. Do not the ARM in the Harmony/Melody does not support hardware division. 1 TIA's hardware collision registers are not very helpful when multiplexing a multitude of sprite images through TIA's two players, some of the images might never be drawn on the same frame, so collision detection must be handled in software.
  9. From Stella Programmer's Guide, which you can find at MiniDig: So player0(P0) will always have priority over player1(P1).
  10. I tweaked the playfield values for the menu to better show how the second color works. This will be in the source when I post Part 8. _MENU_CONTROL: .byte %00000000 ; PF0 .byte %01000000 ; PF1 .byte %00000000 ; PF2 .byte 100 ; ball X location .byte _MENU_LOGO_HEIGHT ; rows .byte MM_TITLE_GAP ; extra scanlines _MENU_FIRST_OPTION_ID = (* - _MENU_CONTROL) / 6 _MENU_PLAYERS_ID = (* - _MENU_CONTROL) / 6 .byte %00000000 ; PF0 .byte %01000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_OPTION_GAP ; extra scanlines _MENU_ARENA_ID = (* - _MENU_CONTROL) / 6 .byte %00000000 ; PF0 .byte %01000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_OPTION_GAP ; extra scanlines _MENU_OPTION1_ID = (* - _MENU_CONTROL) / 6 .byte %00000000 ; PF0 .byte %11000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_OPTION_GAP ; extra scanlines _MENU_OPTION2_ID = (* - _MENU_CONTROL) / 6 .byte %00000000 ; PF0 .byte %11000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_OPTION_GAP ; extra scanlines _MENU_TV_TYPE_ID = (* - _MENU_CONTROL) / 6 .byte %11100000 ; PF0 .byte %11000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_START_GAP ; extra scanlines _MENU_START_ID = (* - _MENU_CONTROL) / 6 .byte %00000000 ; PF0 .byte %00000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_END ; extra scanlines _MENU_CONTROL_SIZE = * - _MENU_CONTROL Players, Arena, Option 1 and Option 2 now use less playfield for the second color. TV Type was unchanged as SECAM needs that extra playfield pixel. Missiles disabled to better show playfield usage.
  11. Added menu Source Code Download and unzip this in your shared directory. Collect3_20200208.zip ROM for reference collect3_20200208.bin Menu Implemented a menu using the 2-color 48 pixel kernel. Menu is fully functional, though Option 1 and 2 don't affect anything except the display of a check or X. Selected values for Players and Arena will affect the display of the game screen. Players 1, Arena 1 Only 1 player in a black arena Players 2, Arena 2 2 players in a red arena When implementing this I had to move the layout of Display Data to the end of collect3.asm to prevent label mismatch errors: dasm collect3.asm -f3 -ocollect3.bin -lcollect3.lst -scollect3.sym collect3.asm (215): error: Label mismatch... --> _BUF_MENU_CONTROL 000c collect3.asm (216): error: Label mismatch... --> _BUF_MENU_COLORS 000c 48 pixel 2 color kernel The 48 pixel kernel was developed for Stay Frosty 2. It works by using the players as stencils: The players are colored the same as the background, so all the 1 bits will be black while all the 0 bits will show through the underlying colors of the background and playfield. The playfield and background colors is set to black for the left side of the screen, changed just before the 48 pixel display begins, then changed back to black for the right side of the screen. The color change doesn't happen at exactly the right time, so the missiles are used to hide the transition. You can see that by using Stella's Developer Keys to toggle both missiles (ALT + C and ALT + V for Linux or Windows, COMMAD + C and COMMAND + V for Mac): Toggling Fixed Debug Colors mode (ALT + COMMA or COMMAND + COMMA) will reveal the layout (be sure to toggle the missiles back on!): The playfield is limited to coloring 4 adjacent pixels at a time, but you can use the ball to fine-tune where the second color shows up - you can see it used for the 3 in COLLECT 3. The playfield can be changed for each entry. This menu doesn't show it off to great effect as just the game title uses a different playfield layout. Some new constants were added to control the spacing in the menu. Whenever you modify the menu make sure to also modify these constants to maintain the 262 scanline count. ; controls spacing in main menu MM_TITLE_GAP = 20 ; gap after game title MM_OPTION_GAP = 8 ; gap between options MM_START_GAP = 20 ; gab before START option MM_LOGO_GAP = 20 ; gap before company logo MM_END = $80 _MM_OPTION_HEIGHT = 7 Only the constant for Option Height is directly used by the C code, so it's prefixed with the _. There are 3 datastreams used by the menu. ; datastream usage for Menu _DS_MENU_GRAPHICS = DS0DATA _DS_MENU_CONTROL = DS1DATA _DS_MENU_COLORS = DS2DATA The graphics datastream contains the graphics as shown on the screen, with an initial value set for each option. The value will be overwritten if the value is different than the initial value. The control datastream holds the playfield pattern used for each entry, the position of the ball (set to 0 if not using it), the height of the option, and the number of extra scanlines to show after the option. Setting extra scanlines to $80 triggers the end of the menu. _MENU_CONTROL: .byte %00000000 ; PF0 .byte %01000000 ; PF1 .byte %00000000 ; PF2 .byte 100 ; ball X location .byte _MENU_LOGO_HEIGHT ; rows .byte MM_TITLE_GAP ; extra scanlines _MENU_FIRST_OPTION_ID = (* - _MENU_CONTROL) / 6 _MENU_PLAYERS_ID = (* - _MENU_CONTROL) / 6 .byte %11100000 ; PF0 .byte %11000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_OPTION_GAP ; extra scanlines ... _MENU_START_ID = (* - _MENU_CONTROL) / 6 .byte %00000000 ; PF0 .byte %00000000 ; PF1 .byte %00000000 ; PF2 .byte 0 ; ball X location .byte _MM_OPTION_HEIGHT ; rows .byte MM_END ; extra scanlines The SpiceWare logo is not part of menu control as it uses a different kernel to extend the lines left and right. In the C code MenuOverScan() has been updated to call new function ProcessMenuJoystick() - but only if the user hasn't pressed GAME RESET on the console. MenuVerticalBlank() has been updated to do a mass-copy that sets default values for the menu's graphics, control, and colors datastreams. The colors are then updated for NTSC/PAL/SECAM by using ColorConvert(). Next menu options are updated if they need to show a different graphic than the default one. Lastly one of the colors for the selected option will be flashed using the frame counter. C data in 6507 source For most of my projects I've only used a single 4K bank for 6507 code. It usually ends up quite full, so data that's not directly accessed by the 6507 is put either in the C code, or after the compiled ARM code. An example of data in the C code is the color table used to test the new Arena menu option: const unsigned char arena_color[4] = { _BLACK, _RED, _GREEN, _BLUE }; Graphic data can also be stored in the C code, though I had 2 conflicts with doing so. I already have tools that convert images for the format used by dasm. Lists of images use up twice as much ROM when stored in C code as it does when stored in the 6507 code. #1 is a minor issue. #2 can be a major issue, even with a 32K game. As an example Draconian has 136 images in the table which takes up 272 bytes in the 6507 code. If the table was in the C code it would have taken 544 bytes. Because of this I've taken to putting the graphics and related data (like the menu control) in the 6507 source file. It's located after the ARM code, and before the banks of 6507 code. There is something to be aware of when doing this - because the build process is this: assemble 6507 code to create defines_from_dasm_for_c.h compile C code to create ARM routines assemble 6507 to create final ROM Step 1 uses the previously compiled ARM code, which will likely change size in step 2. This can make things move in the ROM when step 3 is done. So the data is broken up into 2 groups, ARM Indirect Data and ARM Direct Data. ARM Indirect Data is data the C code doesn't directly access. You can tell it's not accessed because the labels are not prefixed with a _ character, so they don't end up in defines_from_dasm_for_c.h: ARM Direct Data is directly accessed by the C code. We use an ORG to prevent it from shifting around during the 3 steps of the build process. You'll notice the graphic images of PLAYER_LEFT and PLAYER_RIGHT seen above are in the table _IMAGE_GRAPHICS seen below. The C code uses this table to access the graphics. The ORG value will need to be adjusted as the project is developed.
  12. @AtariLeaf - I'm currently working on Collect 3 as part of the Harmony/Melody club. It's a simple game I'm using as a tutorial to teach others how to program games using CDFJ like @johnnywc and I have been doing. @Dionoid's using CDFJ for Fool's Gold - that's a public video on Facebook, be sure to check the replies to the comment by James O'Brien for some extra info. After that I plan to resume work on SpiceC, which will be similar to batari BASIC but the game logic written in C instead of BASIC. As test projects I'll be rebooting Frantic and Timmy! to use SpiceC.
  13. Hmm, don't remember anything said about life expectancy for the inverter. I have a Delta Solivia 7.6 TL. From the catalog it has a 10 year warranty. Like other things, I would expect it to last longer than the warranty period. Checking prices it looks like about a year of savings would cover replacing it. The box that connects to my network has SolarCity stamped on it.
  14. @Flojomojo - I bought it, Tesla did away with SolarCity's leasing. They brought it back in August, but it's only available in 6 states. 10 year units? My panels have a 25 year warranty. They'll still provide power after that, just not as much. Weird - the text is missing from reply 15... Added it back.
  • Create New...