Jump to content

ZackAttack

Members
  • Content Count

    785
  • Joined

  • Last visited

Posts posted by ZackAttack


  1. Rather than having to manually move the maze I'd prefer it just scroll for me automatically. Personally I think it feels like difficulty via bad controls. The maze and scrolling looks good though. I think this could definitely lead to a fun game.


  2. True.

     

    But once you are running an ARM processor with megs of RAM in the cartridge and bus stuffing on every cycle, I have to ask "why?" - just to hijack a TIA?

     

    I suppose it would be to stretch the definition of what you could accomplish from the 24 pins on the cartridge port. Meh, if you make it, the demo crowd will probably make some really impressive demos.

     

    It's not possible to bus stuff every cycle due to the fact that the cartridge has no access to the CPU control signals. The best you can achieve is one TIA write every 3 CPU cycles. This can be achieved in a 2K game too, the big differences is that you can do it more often.

     

    None of this extra cart hardware removes the limitations set by the TIA. It just allows for more opportunities to be creative with how the TIA is used to draw each frame. If the end result is a normal looking cartridge that you can plug into any 2600 and it looks good and is fun to play, why wouldn't you want that?


  3. I think what happened is that the position alien routine has been broken, but since you only used it for the initial position in version 3 it went unnoticed. Now that you're using it every frame it's noticeable. The problem is that you can't write to any of the HMxx registers immediately after you strobe HMOVE. You must wait at least 24 cycles or it will interfere with the HMOVE process. (See stella programmer guide pg9)

     

    This may also explain the problems you're having with detecting which copy was hit. That's not going to work so well if the objects are not positioned where you think they are.

     

    You're routine is also a few cycles off for other reasons. Why don't you just use the code from the collect tutorial? No need to make your own unless you're trying to do something advanced like positioning objects while also drawing a playfield.

        sta WSYNC
       sta HMOVE
        lda #0
        sta HMP1 ;TOO SOON!!!
    
    

  4. perhaps you could give me a bit more of a hint on what you are envisioning with the table. I am not sure I can see it/ too dumb to see it.

     

     

    As for determining which copy was hit, here is an example of my logic for 3 active copies:

     

    1. determine missile x pos ( player x pos + 8 at time of fire , player is double wide) ( assuming player x position is left edge of player)

    2. if collision detected

    add 12 to enemy left copy x and store ( position half way between copy 1 and 2)

    add another 16 to enemy left copy x and store ( position half way between copy 2 and 3

    )

    3. if missile x pos> (left copy x +28) then copy 3 was hit

    else

    if missile xpos < (leftcopy x +12) then copy one was hit

    else copy 2 was hit.

     

    Seems like this should work but it is not......

     

    Your hit detection algorithm appears to be correct. You probably just have a bug in the implementation of it. Don't forget to post asm and bin files for problems like this. We can't help with debugging without them.

     

    Regarding the tables. Here's some more details.

     

    Variables:

    enemyHitIndex - Should be 0 for the left copy, 1 for the middle copy and 2 for the right copy

    enemyX - X position of enemy stored as distance between left side of screen and left side of left copy in pixels. This should always apply to the left copy regardless of it being active to keep hit detection simple.

    enemyXOffset - offset to be added to the enemyX position when calling the PostionObject routine.

    enemyState - 3 bit value indicating the state of the enemy. Spawn with state 7 for 3 active copies, and don't draw for state 0 because there are no copies left. Each bit corresponds to a single copy. 1 indicates the copy is active(visible), and 0 indicates it is inactive(hidden) I.E. %00000101 = X _ X and %00000110 = X X _

     

    Lookup Tables:

    EnemyXOffsetLooup - Use the same index as the EnemyStateTransitionLookup to determine what value to add to the current enemyX value. This compensates for deactivating the leftmost active copy of the enemy by moving it right to where the next copy starts.

    EnemyStateTransitionLookup - Index into this table with the hit detection result and enemyState to determine what the next state should be. Index is the concatenation of the 2 Hit bits (H) and 3 State bits (S) in the format %000HHSSS

    EnemyNusizLookup - Index into this table with the enemyState value to determine the correct NUSIZ1 value.

     

    Here's some sample code. It's untested, but should be close to what you need.

     

    ; Calculate state transition index
      enemyHitIndex
      asl
      asl
      asl
      ora enemyState
      tax
    
    ; update X offset
      ; assumes C flag is cleared by code above. If something else comes between this two sections add a CLC instruction here
      lda EnemyXOffsetLooup,x
      adc enemyXOffset
      sta enemyXOffset
    
    ; update current state
      ; x still has transition index
      lda EnemyStateTransitionLookup,x
      sta enemyState
    
    ; Set NUSIZ1.
      ; assumes A contains enemyState. If this is done late you must replace tax with ldx enemyState
      tax
      lda EnemyNusizLookup,x
      sta NUSIZ1
    

     

    The tables shouldn't be difficult to generate manually. The states are 3 bits, just visualize which copies are still active after a hit occurs. The offsets will be 0 except for a few cases where the left copy is hit, in those cases the value will be 16. The NUSIZ lookup is just mapping the state to the right count and spacing for the remaining active copies.

     

    EnemyXOffsetLooup

    00000 - 0 ; 
    ...
    00100 - 0 ; Left copy hit, but already inactive. No action required.
    00101 - 16 ; Left copy hit and middle is already gone So move over 32 because right copy is all that's left
    00111 - 16 ; Left copy hit which means the middle copy will be the new location. So move over 16
    ...
    01011 - 16 ; middle copy hit leaving only the right copy. So move over 16
    ...
    

     

    EnemyStateTransitionLookup​:

    00011 - 011 ; State unchanged because inactive enemy was hit, normal execution will never go here
    ...
    00111 - 011 ; Left copy hit and deactivated
    ...
    01111 - 101 ; Middle copy hit and deactivated
    ...
    10111 - 110 ; Right copy hit and deactivated
    

     

    EnemyNusizLookup:

    000 - 7 ; make it quad cause we should never draw this
    001 - 0 ; single copy for the right copy
    010 - 0 ; single copy for the middle copy
    011 - 1 ; 2 copies close for middle and right copies
    100 - 0 ; single copy for the left copy
    101 - 2 ; 2 copies med for left and right copies
    110 - 1 ; 2 copies close for left and middle
    111 - 3 ; 3 copies close for left, middle, right
    

  5. I don't know how existing games have chosen to implement this, but if I were to do it I'd view the three enemies as a single enemy. This aggregate enemy would have 8 states corresponding to which of the three copies is active. (3 copies, 2 states, 2^3=8 states total)

     

    The collision flag can tell you that the enemy was hit somewhere, then you have to compare missile position with enemy position and transition to a different state based on which copy was hit and which state you're currently in. Since there's only 8 states and 3 copies you could have a table to track which state to transition to. That should only be 24 bytes of ROM. Simply take copyHit, shift left 3, bitwise OR with currentState and you have the index into the table to update currentState with. You'll probably want some tables to lookup the NUSIZ1 value for each state (8 ROM bytes), and the horizontal offset for each transition (24 ROM bytes). Still it's only taking up 56 bytes of ROM total for the state management lookup tables.

     

    I wouldn't use hmoves to adjust the position when the left copy is removed. Instead I'd just add 16 to the variable which stores P1's horizontal position. You're going to have to keep track of it's position for the collision detection anyway so I'd use the PositionObject() routine each frame instead of using hmove to move around the enemies.

     

    Hope that helps.


  6. DirtyHairy is correct in that the disassembly is fully correct. But what I was referring to is that we will eventually add source-level debugging (https://github.com/stella-emu/stella/issues/237). Basically, if we already have the source file, lst file and sym file, we may as well use that fully, and not use the built-in disassembler at all. This is what we hope to add eventually.

     

    Until then it would be nice if stella at least handled variables that are larger than a single byte. Rather than ram_85 it should display the closest symbol prior to that location and an offset, Game_JumpInd+1.

    • Like 1

  7. It's hard to say without the full source, but it looks like dasm is working fine. I think what you're seeing is stella loading symbols from another bank. Essentially each location may have more than one name which is dependent on the current bank and I believe stella will display them all in the debugger regardless of which bank is currently selected.

    • Like 1

  8. The problem is that you never clear RESMP0. Per the stella programming guide, the missile will be hidden while D1 of RESMP0 is set.

     

     

    Missiles have an additional positioning command. Writing a “1” to D1 of the reset missile-to-player register (RESMP0, RESMP1) disables that missiles’ graphics (turns it off) and repositions it horizontally to the center of its’ associated player. Until a “0” is written to the register, the missiles’ horizontal position is locked to the center of its’ player in preparation to be fired again.


  9. You're using RESMP0 correctly. In fact everything looks correct except this line:

     

    cpx #Missileheight ; check if scanline is missile line

     

    You've included # so it's comparing X with the immediate value which is the location of the Missileheight variable instead of the value of the variable.


  10. Hmm. Version 2 crashes immediately for me and produces a video signal like as if the Atari were turned on without a cartridge.

    I suppose I'll clean the contacts and try loading the demo from a different SD card tomorrow.

     

    That's very surprising since the change from version 1 is so small. I don't really see anything that could have changed the timing enough to cause a crash. Sometimes I pull the SD card out of the computer too quickly without ejecting it and it corrupts the bin file and produces the same results. Could that have happened?


  11. I've been working on a new driver for the Harmony/Melody hardware that makes it possible to offload some of the processing in between servicing the 6507 bus. This extra processing power makes it possible to compensate for the systems that were not compatible with the BUS driver. It's still in the early phase of development, but eventually should make it easy to program the Atari in C/C++. The entire game including the display kernels can be written in C/C++. Currently I have a working prototype of the dev environment which enables source level debugging via visual studio. Then when it's working you simply build it for the Harmony hardware and copy it to an SD card for testing on real hardware. Once it's stable enough I'll be releasing the entire suite of dev tools including all the source code.

     

    I recently posted a working example of it using bus stuffing to scroll a PF and another example where JSR is misused to display 10 colored sprites while also playing an audio sample.

     

     

    • Like 3

  12.  

     

    Surely there will still be done (many) progress with the programming of the VCS (unfortunately no "Bus Stuff", however, apparently... I read that some CPUs were frying...), and this on is a great "experiment"... but what I had in mind is not really such a thing.
    When I talked to David Foster (from the Digital Leisure) we thought about a platformer, just like NES & / or SNES portings (I hate them, heavily !), but playable and beautiful like Pitfall ( II ).

     

     

    I know there have been some systems that did not work with the earlier attempts at bus stuffing, but this is the first I've heard of "CPUs were frying...". What exactly do you mean by this?


  13. Apart from the very first line, this is scrolling just like Scramble Arcade and Super Cobra Arcade.

    I thought with the power of BUS that I was going to see a 1/2 pixel scroll or 2 color clocks, instead of the usual 4 Color clock wide playfield pixel.

     

    Fine 1-pixel horizontal play field scrolling was shown to work, however only on normal CRT televisions.

    Ones like SONY WEGA that processed the signal a lot \would only scroll 3 or 2 of the 4 pixels.

     

    Further testing would be needed, but I think a 1/2 pixel scroll would work on most if not all displays.

    I tried to get 1/2 PF pixel scroll into Super Cobra Arcade and Mappy, but they are really pushing the display per scan line without having to worry about moving the screen a 1/2 playfield pixel by outputting an even more off-spec signal.

    Thanks for testing. Sorry there's not really anything visible to indicate the power of bus stuffing here. This is going to be an engine for a fighting game so fine scrolling wouldn't really benefit it much. The next step will be to add in the sprites, that's when we'll get to see something that's only possible with bus stuffing. What's really cool about this demo is how little resources are consumed to achieve the scrolling playfield. I use less than one scanline worth of vblank to precalculate a few offsets and the rest of the calculations are done while the screen is being drawn. The ARM is hard at work shifting bits around in between servicing the 6507 bus. All that remaining vblank and overscan time should make it possible to have more expensive audio, physics, and AI.

     

    No dice, and it didn't really improve after ~20 minutes of warmup.

    attachicon.gifcherry-00.jpg

    Funny story. After looking into this some I realized that the collision registers won't be set if vblank is enabled. So enabling vblank to hide the detection phase ended up completely breaking it. I disabled vblank and set the color of everything to black instead. Please give version 2 a try, it should work much better. Thanks!


  14. I think I've achieved horizontal playfield scrolling with via bus stuffing and the Strong-ARM driver. If you have a harmony cartridge please try it out.

     

    Current Version:

    Cherry-Tree-Scroll3.bin - 1/25/18 Optimized driver with lookup table and self modifying ARM code, fixed graphic data glitch

     

    Past Failures:

    Cherry-Tree-Scroll2.bin - 1/6/18 disables VBLANK during stuff detection because collision registers won't be set if VBLANK is enabled.

    Cherry-Tree-Scroll.bin

     

    Not supported in emulators yet. Here's what it looks like for those who don't have a harmony cart.

     

     

    post-40226-0-50034500-1515218906_thumb.png

     

     

    • Like 1

  15. What you already have working is already impressive. One other idea could be to use non numeric glyphs for the level indicator. Then it doesn't have to look the same as the score and they could be customized to work well with what's available. Perhaps it would add a little more charm to the game?

     

    Otherwise, unroll the loop, use a more powerful bank scheme such as 3E, use harmony hardware with ARM co processing, or just leave well enough alone.


  16. What I'm really try to point out is that you have to use Y as the index to load the value for Y into a non indexed location before loading it into Y.

     

    In other words you can't do ldy DigitY,y. The tay instruction is no good either, because then you've lost your value for A and you can't load it after you stomp on the index value in Y. Using the stack is even worse because now you've got to deal with the values for X and SP.

     

    Instead you must do this which costs 6 more cycles.

    ; TODO Restore Y with index
    lda DigitY,y
    sta DigitYTemp
    ; TODO Pre load A, X, SP, GRP0, GRP1 etc.
    ldy Digit0Temp
    

    Maybe someone has a clever solution for this, but I haven't thought of a good one yet.

     

    8 grp updates using ld? zp,y and sta zp is (4+3)*8= 56 cycles

    2 nusiz1 updates using lda # sta zp is (2+3)*2 = 10cycles

    restoring Y index is at least ldy ZP = 3 cycles

    branch taken for loop = 3 cycles

    Providing the above calculations are correct 72 cycles are already used leaving just 4 more to deal with the ldy zp,y problem.

    • Like 1
×
×
  • Create New...