Jump to content

cd-w

Members
  • Content Count

    2,433
  • Joined

  • Last visited

  • Days Won

    2

Blog Comments posted by cd-w


  1. I think it is sometimes best to keep a bit of distance between your hobby and your career. Having to work 9 to 5 on something can really suck the life out of it, and having management dictate the direction of something that you really care about can be soul destroying. I worked as a programmer in the games industry for a short time and didn't enjoy it. I now work as a web developer and program games in my spare time, which works much better for me.

     

    Chris

    • Like 2

  2. Very nice work - I think it is now done!

     

    Using the ARM in this way is very interesting - it makes some things easier, but you still have to worry about every byte and cycle just as with normal Atari 2600 programming. I always find the game logic to be a pain to program in 6502, so it is cool to be able to do that in C, while still doing the tricky kernel programming in 6502.


  3. The game looks and sounds great. I think the heartbeat sound could be more noticeably faster towards the end of each wave, but otherwise I think the sounds are perfect.

     

    There is a possible bug with killer satellite. In one game the left half was missing entirely as it moved around the screen (before it had been shot). In another game there seemed to be a column of pixels missing from the right half of the satellite, so that there was a noticeable gap between the halves. In both cases the satellite appeared on the left of the screen moving right. Unfortunately I couldn't find the pause button quickly enough to take a screenshot.

     

    Chris


  4. I have to admit I didn't do much work on Star Castle lately, but with the darker days coming, I am sure this will change. I will post the progress in my own blog.

    Thanks - I appreciate your efforts to make the game as close to the arcade version as possible.

    A demo version of Star Castle is going to be available on the AA stand at PRGE, but it will be the older version before your changes.

     

    Chris


  5. One small feature request - can you add a "blip" sound when an option is changed on the menu screen. Sometimes it can be difficult to be sure the option has actually changed, particularly the color options. I think AUDC=5, AUDF=24, AUDV=8 for a few frames makes a reasonably nice sound.

     

    Chris


  6. Good point - I keep forgetting that the ARM in the Harmony doesn't have a divide unit.

     

    How about:

     

    1) Dropping the "bonus life" option from the menu and just hard-wiring it to 10K, or making it a feature of the level type (kids=2K, easy=5K, normal=10K, hard=20K).

     

    2) Storing the easter-egg text as non-ASCII? If you have less than 64 letters you could pack 4 characters into every 3 bytes, i.e: AAAAAABB BBBBCCCC CCDDDDDD

     

    Chris


  7. I'm glad you could save a few more bytes. I can't see any more optimisations without rewriting the code.

     

    The main area for optimisation is probably still the menu, as it is taking up a lot of space. It feels like it should be possible to replace most of the menu code with a function like this:

     

    void set_menu_option(char *datastream, char *options, int case)

    {

    my_memcpy(datastream, options + (case << 4), 4*sizeof(short));

    }

     

    And you would just call it for each section of the menu:

     

    set_menu_option(gMenuOptionsDatastream[MENU_LEVEL_ID], &menu_level_options, MM_LEVEL);

     

    However, I'm not sure if this could be made to work for all the different options ...

     

    Chris


  8. Some more very small optimisations:

     

    1) saucer_respawn_time could be done as 240-(x*40)

     

    2) Use loops for this code:

     

    // make sure we don't conflict with a reposition of Player 1, which takes 2 scanlines

    if ((gEventBallDataStream[y-1] & 0xA1) == 0xA1) position = -3;

    if ((gEventBallDataStream[y-2] & 0xA1) == 0xA1) position = -4;

    if ((gEventBallDataStream[y-3] & 0xA1) == 0xA1) position = -5;

     

    // make sure we don't conflict with a reposition of Player 0, which takes 2 scanlines

    if ((gEventBallDataStream[y-1] & 0xC1) == 0xC1) position = -3;

    if ((gEventBallDataStream[y-2] & 0xC1) == 0xC1) position = -4;

    if ((gEventBallDataStream[y-3] & 0xC1) == 0xC1) position = -5;

     

    e.g:

     

    for (i = 0; i < 3; ++i) {

    if ((gEventBallDataStream[y-(i+1)] & 0xA1) == 0xA1) position = -(i+3);

    }

     

    3) Use an inner loop:

     

    for(i=0;i<3;i++)

    {

    SCORE_PF0L[2+i] = SCORE_PF0L[1];

    SCORE_PF0L[7+i] = SCORE_PF0L[6];

    SCORE_PF1L[2+i] = SCORE_PF1L[1];

    SCORE_PF1L[7+i] = SCORE_PF1L[6];

    SCORE_PF2L[2+i] = SCORE_PF2L[1];

    SCORE_PF2L[7+i] = SCORE_PF2L[6];

    SCORE_PF0R[2+i] = SCORE_PF0R[1];

    SCORE_PF0R[7+i] = SCORE_PF0R[6];

    SCORE_PF1R[2+i] = SCORE_PF1R[1];

    SCORE_PF1R[7+i] = SCORE_PF1R[6];

    SCORE_PF2R[2+i] = SCORE_PF2R[1];

    SCORE_PF2R[7+i] = SCORE_PF2R[6];

    }

     

    becomes:

     

    for(i=0;i<3;++i) {

    for (j = 7; j >0; j-=5) {

    SCORE_PF0L[j+i] = SCORE_PF0L[j-1];

    SCORE_PF1L[j+i] = SCORE_PF1L[j-1];

    ...

    }

    }

     

    4) PF_1_DIGIT_MASK and PF_02_DIGIT_MASK are basically the same values but with 2->1 and 1->2. There must be an optimisation in there but I'm not sure exactly how! Alternatively you could use the upper 4 bits for PF_1_DIGIT_MASK and the lower 4 bits for PF_02_DIGIT_MASK and mask/shift depending on which value you need. Since you are already shifting, the compiler can hopefully optimise without needing more instructions, e.g:

     

    (PF_1_DIGIT_MASK[display[1] + i] >> 4) << 5; // compiler optimises to << 1


  9. I couldn't find any large wins this time, but I think you may be able to save some bytes by doing:

     

    1) Moving the shift operation inside the random function, so you would call it like Random32(15):

    unsigned int Random32( unsigned int mask)
    {
    static unsigned int random = 0x02468ace;
    random = (random >> 1) ^ (unsigned int)(-(random & 1u) & 0xd0000001u);
    return (random & mask);
    }
    

    2) Packing the arrays to save bytes, e.g. the values in PF_1_DIGIT_MASK only require 2 bits each to store, so you could pack 16 of them into a single 32-bit integer:

     

    2<<30 | 0 <<28 | 3<<26 .... 1<<4 | 2<<2 | 1<<0

     

    You can then extract the value using a small function, e.g:

     

    unsigned char extract_pf1_data(int[] packed, int position)
    {
    return (packed[position/16] >> ((position%16) * 2)) & 0x3;
    }
    

     

    Hopefully the bytes needed to call this function will be less than the number originally used!

     

    3) The vector_three_on array could be calculated (2^(x+3))-(2^x) I think.

     

    4) In the InitSpriteShotDatastreams function - if the queues are contiguous then a single memset could be used to zero all of them?

     

    5) When calling InitShip, the x & y values are always shifted by FRACTION_BITS. You could move this shift inside the function:

     

    gSpriteX[player] = x << FRACTION_BITS;
    gSpriteY[player] = (y- << FRACTION_BITS;
    

     

    6) In the PrepSpeedRange function, the SPEED_RANGE and SPEED_BASE calculations could be moved inside the loop:

     

    for (i=0;i<3;++i)
    {
    SPEED_RANGE[i] = (level >> (2-i)) + 4;
    SPEED_BASE[i] = (level >> (6-i) + base_adjust;
    ...
    }
    


  10. Some space optimization suggestions:

     

    1) Make ship_shot_x and ship_shot_y unsigned char arrays, and shift by FRACTION_BITS after loading the value, i.e. (ship_shot_x[direction] << FRACTION_BITS)

     

    2) In the menu, replace the cases with memcpy, e.g:

     

    case 1:

    gMenuOptionsDatastream[MENU_PLAYERS_ID*10 + 0] = OPTION_2PLAYER_1;

    gMenuOptionsDatastream[MENU_PLAYERS_ID*10 + 1] = OPTION_2PLAYER_B;

    gMenuOptionsDatastream[MENU_PLAYERS_ID*10 + 2] = OPTION_2PLAYER_A;

     

    becomes:

     

    static const unsigned short player_options[][3] =

    {{OPTION_2PLAYER_1, OPTION_2PLAYER_B, OPTION_2PLAYER_A},

    {OPTION_2PLAYER_2, OPTION_2PLAYER_B, OPTION_2PLAYER_A},

    ...};

    my_memcpy(gMenuOptionsDatastream[MENU_PLAYERS_ID*10], player_options[MM_PLAYERS], 3*sizeof(unsigned short));

     

    3) When loading PF data use a loop instead of expanding every case, e.g:

     

    SCORE_PF1L[0] = (PF_1_DIGIT_MASK[display[1] + 0] << 5) +

    (PF_1_DIGIT_MASK[display[2] + 0] << 3) +

    (PF_1_DIGIT_MASK[display[3] + 0] << 1) +

    (PF_1_DIGIT_MASK[display[4] + 0] >> 1);

     

    becomes:

     

    static const char position[] = {0, 1, 5, 6, 10};

    for (i = 0; i < 5; ++i) {

    SCORE_PF1L[position] = (PF_1_DIGIT_MASK[display[1] + i] << 5) +

    (PF_1_DIGIT_MASK[display[2] + i] << 3) +

    (PF_1_DIGIT_MASK[display[3] + i] << 1) +

    (PF_1_DIGIT_MASK[display[4] + i] >> 1);

    SCORE_PF2L[position] = (PF_02_DIGIT_MASK[display[4] + i] >> 1) +

    (PF_02_DIGIT_MASK[display[5] + i] << 1) +

    (PF_02_DIGIT_MASK[display[6] + i] << 3);

    SCORE_PF0R[position] = (PF_02_DIGIT_MASK[display[7] + i] << 7);

    SCORE_PF1R[position] = (PF_1_DIGIT_MASK[display[7] + i] << 7) +

    (PF_1_DIGIT_MASK[display[8] + i] << 5) +

    (PF_1_DIGIT_MASK[display[9] + i] << 3) +

    (PF_1_DIGIT_MASK[display[10] + i] << 1) +

    (PF_1_DIGIT_MASK[display[11] + i] >> 1);

    ...

    }

     

    4) The vector_one_on array is just ^2, i.e. vector_one_on[x] -> (x+1)^2;


  11. The warp-in looks good, but I think it needs to be offset slightly as the ship appears to the right of the effect?

     

    The fast asteroid explosions look great, but I preferred the slower animation on the ship explosion. Perhaps you could start the ship explosion quickly and have the final frames a bit slower?

     

    I can't wait for the arcade sound effects and then this game will be close to a perfect port.

     

    Chris


  12. Just played the Gameboy version again on the Harmony today, and this is great. Can't wait for the full-color version on cart. I know this won't be cost-effective, but wouldn't it be cool to do a cart release in grey plastic, to mimic the GB?

     

    Than would be nice, but I don't think anyone has produced new Atari cases for some time. Curt said something about considering it, and I think Fred (batari) has had managed to make one using Makerbot ...


  13. The ship acceleration feels perfect now. The game looks really nice - the large high-rez rotating sprites are very different for the 2600 (even with ARM assistance).

     

    My only complaint now is that the ship explosion looks a bit weak - is there any space for a better effect?

     

    I really hope you finish this one and don't get distracted :)

     

    Cheers,

    Chris

×
×
  • Create New...