Jump to content

Photo

"Sierra Maestra", an Early WIP


95 replies to this topic

#76 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • 122 posts
  • Location:Indiana, USA

Posted Thu Dec 21, 2017 1:31 AM

I believe you forgot to clear the HMP0 value to 0 after positioning Player 0.  Every time you strobe HMOVE, it moves all the objects that aren't set to 0.  Calling sta HMCLR resets all HMxx registers to 0.  If you do that after positioning Player 0, I think it will fix all the issues.  But be careful not to write to HMCLR right after HMOVE.  You need to wait 20+ cycles or so to keep from messing up the HMOVE operation.

 

When I submitted this post, I saw SpiceWare had covered this already.  :D

 

Another thing I learned is that if you are doing an HMOVE at cycle 73 rather than after WSYNC (to avoid the black "comb" lines, like in my Nyan Cat project), the HMxx values are different so that a zero actually moves the object.  You would have to set each non-moving object's HMxx to #$80 instead.

 

Here's a handy link to a table that shows how much HMOVE will move each object and in which direction, depending on when you strobe HMOVE during a scanline (the table is at the bottom).


Edited by JeremiahK, Thu Dec 21, 2017 11:05 AM.


#77 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Thu Dec 21, 2017 2:17 AM

I thought SpiceWare was saying I should do exactly what your crossed-out text said - what is SpiceWare suggesting if not that?



#78 DirtyHairy OFFLINE  

DirtyHairy

    Moonsweeper

  • 305 posts
  • Location:Germany

Posted Thu Dec 21, 2017 2:32 AM

Another thing I learned is that if you are doing an HMOVE at cycle 73 rather than after WSYNC (to avoid the black "comb" lines, like in my Nyan Cat project), the HMxx values are different so that a zero actually moves the object.  You would have to set each non-moving object's HMxx to #$80 instead.

 

 

Strobing HMOVE will raise a flag that causes horizontal blanking to be extended by 8 color clocks. Each sprite is essentially a counter that is not clocked during hblank, and so this will effectively move the sprite 8 pixels to the right (as it will take 8 more color clocks until the counter reaches the value that triggers rendering); the side effect are the black lines.

 

In order to facilitate other movement values, strobing HMOVE will trigger the TIA to start sending extra clock pulses that will drive the sprite counters. The amount of pulses that is sent to each sprite depends on the value of the high nibble of HMXX. The highest bit is internally inverted, so a value of 0 will cause 8 extra clocks, amounting to zero movement, 7 will cause 15 extra clocks, amounting to 7 pixels movement to the left.

 

During the visible part of the scanline, the extra clocks will interfere with the regular clock pulses. The details depend on the exact TIA revision; it is assumed that, on most chips, the extra clocks fall together with the regular ones and have no effect at all. Either way, this is the reason for the timing restrictions on HMOVE.

 

At the end of the scanline, the flag that prolongs hblank is cleared. If you strobe HMOVE before this, the extended blanking will not happen, and all extra clocks will cause a shift of one pixel to the left. This is the reason for the idiosyncrasies of late HMOVE. If you strobe HMOVE before the line ends **and** before the first extra clock is sent, you can achieve 15 pixels of movement to the left this way.

 

On a sidenote, this also explains most of the starfield effect: If you write HMxx while the extra pulses are sent, you can set it to a value below the extra pulse counter **before** the stop condition has been reached. This will cause the sprite to receive extra clocks until the next HMOVE and causes the starfield :)


Edited by DirtyHairy, Thu Dec 21, 2017 3:05 AM.


#79 RamrodHare OFFLINE  

RamrodHare

    Dragonstomper

  • 531 posts
  • Lost in Time.
  • Location:Greeneville TN, USA

Posted Thu Dec 21, 2017 3:12 AM

Vidak, 

Keep up the good work!  :thumbsup:  :)



#80 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Thu Dec 21, 2017 3:57 AM

Vidak, 
Keep up the good work!  :thumbsup:  :)


Thanks man : )

I really have to thank you all for helping me. I really love this community : )

#81 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • 122 posts
  • Location:Indiana, USA

Posted Thu Dec 21, 2017 9:57 AM

I didn't mean to confuse you with the crossed out text, it is correct. I had connection issues, and I hadn't seen Spice's post until after I posted mine.

 

Thanks for the very detailed explanation of HMOVE, DirtyHairy!


Edited by JeremiahK, Thu Dec 21, 2017 11:33 AM.


#82 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Thu Dec 21, 2017 12:01 PM

This forum is amazing, I really mean it.

#83 TheHoboInYourRoom ONLINE  

TheHoboInYourRoom

    Moonsweeper

  • 359 posts
  • Whackadoo thingamajig
  • Location:Illinois

Posted Thu Dec 21, 2017 4:05 PM


The highest bit is internally inverted, so a value of 0 will cause 8 extra clocks, amounting to zero movement, 7 will cause 15 extra clocks, amounting to 7 pixels movement to the left.

Another way of saying this is that the TIA automatically converts 4-bit two's complement into excess-8.



#84 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Tue Dec 26, 2017 2:36 AM

I'm a little stuck again.

 

I implemented the STA HMCLR like people suggested, and that fixed the erratic horizontal movement problems.

 

However I now have an issue with the kernel, and the graphics pointers.

 

In order to save time in the kernel, I store Player0's graphics to the Y register at the bottom of the kernel.

 

HOWEVER, the GRP1 calculation routine is starting too early, and is causing the index of the GRP1 graphics to be loaded into the Y register, which is what is causing the black band of artefacts in each band of the screen where GRP0 doesn't appear.

 

Could someone explain to me how my pointers and Y offset variables are working? I can't seem to understand how to line up the (a) Y offset; and (b) graphics pointer.

 

I think I am also running out of time in my kernel...

Anyway, if anyone could have a look, I'd be very grateful : )

Attached Thumbnails

  • guerrilla20.png

Attached Files



#85 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • 122 posts
  • Location:Indiana, USA

Posted Tue Dec 26, 2017 2:29 PM

I'm not sure where the problem is, but it looks like you are somehow storing your line counter value (instead of the graphics loaded from the offset) into GRP1.



#86 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 572 posts
  • Location:Orlando, FL US

Posted Tue Dec 26, 2017 6:46 PM

You have a branch that is skipping the code which loads the value for GRP0 into Y. This is why Y never contains the graphics data. The use of LDA (PTR),Y appears to be fine.

    lda #P0_HEIGHT      ; 2 47
    dcp Player0Offset   ; 5 52
    bcc .p0FlipDraw     ; 2 54 (3 54) <- Branch is taken, leaving Y with offset value
    ldy Player0Offset   ; 3 57

    lda (Player0Clr),y  ; 5 62
    sta COLUP0          ; 3 65 
    lda (Player0Ptr),y  ; 5 70
    tay                 ; 2 72

.p0FlipDraw             ;(3 54)


#87 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Thu Dec 28, 2017 3:21 AM

Thanks for both of your help!

I think I can fix this now!

#88 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Thu Dec 28, 2017 7:22 PM

Just in response to ZackAttack - the graphics code for GRP0 needs to be skipped until the correct Y position for Player0 is reached. If I remove that branch, then Player0 will be drawn at the earliest possible opportunity. That branch is a part of the FlipDraw routine.

 

I think this kernel will not work in the long run. I think I have three options:

 

1. Use SpiceWare's masking technique

 

2. Use some version of VDELxx in a 2 Line Kernel in order to try and get single line resolution

 

Option 2 would be considerably more difficult than Option 1. There could be an option 3:

 

3. Use DoDraw for GRP1, and use FlipDraw for GRP0.

 

This is just an idea, it will almost certainly not work because it will take too long. It would require decrementing the scanline counter in memory and reloading it into Y every time.

 

Overall my current kernel is too slow to draw 2 multi-coloured sprites. 8bitworkshop.com seems to be able to achieve 2 multicoloured sprites AND a playfield, so I will study that code and see what I can learn. 8bitworkshop uses VDELP0, so I think this may be the way forward.



#89 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 572 posts
  • Location:Orlando, FL US

Posted Thu Dec 28, 2017 8:47 PM

I'm not saying you should get rid of the branch. I'm saying that the branch prevents the P0 graphics from being preloaded for the next line. So instead of 0 you get a garbage value. Maybe in pseudo code it could be easier to see.

 

if(drawP0) then

   y = graphicForNextLine

end if

 

GRP0 = y <- y only is set if the if evaluates to true.

 

Instead what you want is this

 

 

if(drawP0) then

   y = graphicForNextLine

else

   y = 0

end if

 

GRP0 = y <- now y is 0 if it's not time to draw P0

 

Diff your previous posted asm file with this one to see the small change which makes all the difference. Attached File  guerrilla-fix-y.asm   34.58KB   3 downloads

 



#90 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Thu Dec 28, 2017 9:36 PM

Ah okay.

Is there still enough time in the kernel, though? That's mainly what I was worried about...

#91 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 572 posts
  • Location:Orlando, FL US

Posted Thu Dec 28, 2017 10:14 PM

Plenty of time since you only execute one code path or the other.

 

Speaking of time. Since you're using bands there's no need for flipdraw or any other overhead on P1. Just pad the graphics and color data with a few bytes if you want to allow a small amount of vertical movement. Then offset the pointer to effect the vertical position within each band. Another nice thing about the bands is that you can use mask draw for P0 with a mask that's 3 * band height. So a 32 line band would only need 96 bytes for the mask. Then you can do P0 with only 5 cycles of overhead. Just as important, this gets rid of all the branches and makes it a lot easier to make the kernel exactly 76 cycles.

; Updates both sprites in 37 cycles
lda (ptrgrp0),y
and (ptrmask),y
sta GRP0
lda (prtcol0),y
sta COLUP0
lda (ptrgrp1),y
sta GRP1
lda (prtcol1),y
sta COLUP1

One more thing to consider is how P1 is being positioned between bands. If you want to draw anything between the bands you may need to have different kernel fragments that all do the same thing, but with a RESP1 strobe at different times. Then before hand you figure out which fragment to jump to based on where P1 is to be positioned. Then have a few lines to use HMOVE for fine positioning. If you have one line for HMOVE you'd need 160/15 = 11 fragments, but with 3 lines of HMOVE you'd only need 160/45 = 4 different fragments. You'd be left with at least 4 lines between each P1, but you gain the potential for some playfield or other enhancements.



#92 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 572 posts
  • Location:Orlando, FL US

Posted Thu Dec 28, 2017 11:17 PM

I am about to develop a 2LK for the "Lock and Load" part of the game, the second part, which will feature:

  • 2 coloured sprites
  • 1 missile
  • a coloured asymmetrical playfield

A few questions about this.

 

  1. Will the playfield be drawn between bands?
  2. Is the missile going to be limited to just a few pixels per band?
  3. How tall did you plan on making the PF pixels?
  4. What's the largest/tallest PF pixel you'd accept?
  5. Will there be more than one PF image for this mode of the game?
  6. Can the PF be limited to the middle 32 PF pixels so that updating PF0 can be avoided?
  7. What are you trying to draw with the PF?


#93 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Fri Dec 29, 2017 3:07 AM

I don't think it's true that I'm only executing one code path or the other - I am executing both code paths when GRP0 and GRP1 are both drawn in the same band.

I will get back to you about the lock and load section! My short answer is that I will only be drawing the middle 32 pixels - I'd like to have as high a resolution as possible.

I am hoping to have at most three different backgrounds. One for the beach, one for the jungle, and another for the mountains.

This part of the game will not have bands of soldiers. It will only have 2 multicolored sprites on the screen. I will also use 8x width effects to create different objects.

#94 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Fri Dec 29, 2017 3:10 AM

The lock and load section of the game is kind of a small strategy game. You can move, block, load, or shoot. The idea is to chase down your opponent soldier and shoot them. If they block in the same turn as you shoot, they avoid any damage.

I will be drawing a beach background, a jungle background, and a mountain background.

#95 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • 122 posts
  • Location:Indiana, USA

Posted Fri Dec 29, 2017 9:19 AM

I don't think his point was that you were only executing one code path or the other, it's that you are only loading Y properly in one, but still writing it to graphics in both. This results in the leftover Y value from the counter being written to graphics when the branch is taken.

#96 vidak OFFLINE  

vidak

    Moonsweeper

  • Topic Starter
  • 289 posts
  • Location:Sydney, Australia

Posted Thu Jan 4, 2018 7:56 AM

Ah okay. I agree. That is the problem.

Anyway, I'm back from my enforced relaxation now, and I am going to attempt a new rewrite of the kernel using the masking method, which is undeniably faster.

Again, thank you for all your help :)




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users