Jump to content
Sign in to follow this  
TROGDOR

Arrrg. Problems with my Kernel.

Recommended Posts

Hi all,

 

I've just spent several days shoveling though the MiniDig and various posts about skipDraw, and found the incredibly helpful ATARI 2600 ADVANCED PROGRAMMING GUIDE.

 

The result is I've pieced together my first major kernel. It allows for 2 animated sprites, the ball, and both missiles all on the same scanline. It uses exactly 76 cycles each pass, so it has no WSYNC. It's squeezed so tight it doesn't even have a NOP.

 

I loaded it into my emu, and it worked! :D Sorta. :roll: There's some artifacts I can't figure out. :?

 

This kernel is for the game "The Battle of Midway". You'll find detailed specs for this game in this forum discussion.

 

The bottom of the screen displays a battleship, and the water. It isn't part of the main kernel, because I know there's no way I could do asymetric background graphics and all 5 MOBs in one scanline.

 

The upper 75% of the screen uses the main kernel. Right now it just has a demo of the GRP0 plane HMOVEing across the screen from left to right. The sprite graphics are updated every 4 seconds to rotate the plane in all 8 directions.

 

Here are the 3 problems I'm seeing:

 

1. The HMP0 setting isn't working the way I'd expect. I loaded #%00010000 into HMP0, expecting it to move my sprite one pixel for each movement (with one move every 16 frames). Instead it moves it 2 pixels. What's stranger is it moves it 2 pixels no matter what value I load into HMP0 :? I've checked for the obvious stuff: The HMOVE is right after a WSYNC, and there is only one HMOVE in all the code, and it's not in a loop. (Well, it technically is in a loop, but only once every 16 frames.)

 

2. The graphics in GPR0 are getting slightly garbled as the sprite moves across the screen. This problem I do understand, but I'm not sure how to fix. My original intention was to use VDELP0 to delay the plane 1 scanline, thinking that would free me up from the 23 cycle limit in horizontal blank, so I could calculate the GRP0 and GRP1 sprites and then display them the next line. But, VDEL appears to delay the display exactly one scanline, so the distorted graphics still appear regardless of whether I enable VDEL. Can anyone suggest a way around this? Is what I'm trying to do even possilbe?

 

To reassure myself, I went back and played some Combat. They're able to do 2 sprites, 2 missiles, and symmetric background on one scanline. But, looking closer, I see that they've got half vertical resolution. :( I want to keep the full vertical resolution unless it's absolutely necessary to chop it. I took another look at JoustPong, and I see that it is also using 50% vertical resolution, so my hopes are fading fast. :(

 

So it looks like I may be stuck with:

 

Scanline 1: Calculate everything.

 

Scanline 2: write out all the graphics based on those calculations using VDEL, so they'll start displaying on the next scanline 1. Do all 5 MOB's still have to be written in the first 23 cycles of the second scanline? I'm confused about VDEL. Is it a one time write, or do I have to strobe it every time I want the buffer to pass though?

 

3. The colors between Z26 and PCAE are very different! Yeah, I know, don't use PCAE. :roll:

 

Thanks for any help on this. I'm including the kernel code below, and below that a zip file with the bin and full code.

 

TROGDOR

 

;------------------------------------------------------------
;The Kernel!  The bowels of the beast!



       LDA #0                   ;Careful!  Set to 0 for 3 cycle load below.

       STA Temp1



       TSX                      ;Careful!  Need to initialize stack hack here.

       STX Temp2                ;Preserve the stack in Temp2.

       LDX #ENABL+1

       TXS



       LDX #150                 ;Initialize the scanline count down.



       JMP KernalStart          ;FIXME!  There's wasted ROM space here.



       align 256



SkipPlane0Draw

       LDA Temp1                ;3 Careful!  Temp1 must contain 0.

       BEQ ContinuePlane0Draw   ;3



SkipPlane1Draw

       LDA Temp1                ;3 Careful!  Temp1 must contain 0.

       BEQ ContinuePlane1Draw   ;3



KernalStart

       STA WSYNC



NextLine0

       CPX BombY                ;3

       PHP                      ;4 sets ENABL

       CPX Plane1BulletY        ;3

       PHP                      ;4 sets ENAM1

       CPX Plane0BulletY        ;3

       PHP                      ;4 sets ENAM0, Total 21





       TXA                      ;2 A now holds scanline.

       SEC                      ;2

       SBC Plane0Y              ;3

       ADC #PlaneHeight         ;2

       BCC SkipPlane0Draw       ;2 or 3



       TAY                      ;2

       LDA (Plane0GfxLo),Y      ;5



ContinuePlane0Draw

       STA GRP0                 ;3, Total 21





       TXA                      ;2 A now holds scanline.

       SEC                      ;2

       SBC Plane1Y              ;3

       ADC #PlaneHeight         ;2

       BCC SkipPlane1Draw       ;2 or 3



       TAY                      ;2

       LDA (Plane1GfxLo),Y      ;5



ContinuePlane1Draw

       STA GRP1                 ;3, Total 21



       TXA                      ;2 Reset the stack.

       LDX #ENABL+1             ;2

       TXS                      ;2

       TAX                      ;2



       DEX                      ;2

       BNE NextLine0            ;2 or 3, Total 13

                                ;Total: 21 + 21 + 21 + 13 = 76



       LDX Temp2                ;Restore the stack from the stack hack.

       TXS



tbom_v003.zip

Share this post


Link to post
Share on other sites

@1: It moves by 3 pixel, but I have no idea why. :ponder:

@2: PHP takes only 3 cycles! :idea:

Share this post


Link to post
Share on other sites

Got it! :)

 

:idea: You set the stack pointer wrong. Use ENABL instead of ENABL+1 (=HMP0!).

Share this post


Link to post
Share on other sites

BTW: You can save a lot of CPU time by using Y as scanline AND graphics pointer. I did (tried to) explain that at [stella] together with skipDraw.

 

And you can use the illegal opcode version of skipDraw (using DCP) and save even more CPU cycles.

 

Together that would gain you 14 cycles.

Share this post


Link to post
Share on other sites

Thanks for your help Thomas. Most of the trouble has been cleared up.

 

PHP takes only 3 cycles!

 

I burned these 3 extra cycles with a WSYNC at the start of the loop. This has cleared up most of the sprite distortions.

 

However, there is still a point on the screen where the sprites are rolling 1 scanline. I'm not sure what would cause that, since I've got VDEL enabled for both sprites, and it shouldn't be able to roll with that WSYNC in there. My understanding of VDEL is that it only needs to be enabled once. If you store a sprite value in the buffer, it should take affect at the beginning of the next scanline, correct? Or does it take effect exactly 76 cycles (i.e. one scanline) later? The display is similar regardless of whether I set the VDELs to 0 or 1. The only difference is that the VDEL enabled pushes my sprites down one scanline. Thomas, can you recommend a solution to prevent this problem, and can you clarify the behavior of VDEL as defined in the stella guide? Do I really have to squeeze all my graphics writes into the horizontal blank?

 

A control bit called vertical delay (VDEL0, VDEL1) selects which of these two registers is to be used for serial output. If this control bit is set by the microprocessor between picture frames, the object will be moved down (delayed) by one line during the next frame.

 

You set the stack pointer wrong. Use ENABL instead of ENABL+1 (=HMP0!).

 

Nice catch. I think there is a typo in the ATARI 2600 ADVANCED PROGRAMMING GUIDE. It says to use LDX #ENAM1+1 if you want to set up the stack trick for just the two missiles. That should just say LDX #ENAM1. Following the logic in the guide, I used LDX #ENABL+1, since I wanted to include the BALL.

 

I also found another typo. In the illegal opcode section, it says:

 

Decrement and Compare:

Decrements the memory location and compares it to the accumulator.

DCP Opcode:$C3 M <- (M)-1, (A-M) -> NZC (Ind,X) 2/8

 

I assume the 2/8 means 2 bytes, 8 cycles. But shouldn't this command be 5 cycles? If it is 8 cycles, you're not saving cycles, because DEC (zeropage) = 5 cycles, and CMP (zeropage) = 3 cycles.

 

I'm including V0.04 below, with a demo of 6 planes flying in formation. There is a screenshot, and a zip with the bin and source.

 

Thanks again,

TROGDOR

post-5668-1097916866_thumb.jpg

tbom_v004.zip

Share this post


Link to post
Share on other sites
My understanding of VDEL is that it only needs to be enabled once.

Right.

 

If you store a sprite value in the buffer, it should take affect at the beginning of the next scanline, correct?  Or does it take effect exactly 76 cycles (i.e. one scanline) later?

Nope, VDEL works comeptely different. By enabling e.g. VDELP0, all your writes to GRP0 go into a 2nd shadow register. This shadow register is copied into the visible register when you write something into GRP1. So VDEL only works if you use both GRPx registers.

 

Do I really have to squeeze all my graphics writes into the horizontal blank?

Nope, you can enable e.g. VDELP0 and write to GRP0 wherever you want as long as the write to GRP1 happens correctly.

 

And if your sprites don't go to the left and right corners, you can gain a few cycles there too.

 

But shouldn't this command be 5 cycles?  If it is 8 cycles, you're not saving cycles, because DEC (zeropage) = 5 cycles, and CMP (zeropage) = 3 cycles.

Yup, you are right, 5 cycles is correct. Write the author! :)

 

BTW: You should join the [stella] mailing list. There are many nice people who are waiting to help you.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...