Jump to content
IGNORED

Need More Time


Roy

Recommended Posts

I have been looking at my program structure, and it seems with how I am currently doing things, I guess I'm running out of cycles? The time it takes the engine to calculate changes, setup the DLLs, and play music, seems to spill into drawing time creating difficult to debug glitches. (And God knows what else my buggy engine is creating ;) )

 

I'm starting on a smaller project from scratch, this time taking care of when I begin to calculate changes. Hopefully by doing this, I can make my SHMUP better/actually work. Before, I would wait for MSTAT at the beginning and end of my infinite loop with all changes being calculated between those two points. The article HERE brings up a really good point that a NMI should be triggered after visible display. This sounds good, so do you guys think the best way to get the most out of the 7800 is to wait for this Display List Interrupt, calculate game changes immediately, then process the DLLs, then finally wait for the start of visible display? I'm assuming without the wait at the end of the program, everything would run too fast? Also the wiki states game logic should be separate from display logic. Does display logic constitute only building the DLLs?

 

Here's a stripped snippet of my main loop:

;End of setting up DL, clearing ram, etc...
;====================================================================================================
;MAIN LOOP

loop:
        ;Before, I had almost all of my changes happening here. Everything except some background drawing logic...
        ;How should I use this section if the game logic is calculated at the end of 
        ;visible display? What should go here? 
	jmp loop
	
;====================================================================================================
	
NMI:

        ;This section is triggered by the DLI at the end of visible display.
	rti 

Frame timing and sound are my two weakest areas, so I'm hoping the vets here could show me the best way to get the most cycles out of the console and how I should wait for the next frame... Thanks for your time! :thumbsup:

Link to comment
Share on other sites

If you're not double-buffering your screen then it's probably better to calculate the game changes prior to the end of the visible screen so that during the non-display time you're focusing on just building the display lists to maximize the odds it'll be finished by the time the visible screen starts again.

  • Like 2
Link to comment
Share on other sites

Games on the 2600 tend to be written around the display kernel. i.e. structuring game data to minimize the number of cycles required in the display kernel. Similarly, on the 7800 there is value in ensuring game data is structured so the display lists may be created as efficiently as possible. So look at your display list builder code and ask yourself "how can i make this faster?".

 

I'd also order the code as:

1. Wait for end of screen (via DLI)

2. Reset end-of screen flag, read controllers, update sound registers (to minimize jitter)

3. Build display lists (assuming everything can be done in one screen time you don't need to double buffer)

4. Execute game & music logic

5. Test MSTAT, if still in VLBANK then set debug indicator to green and goto 1. If not but end-of-screen flag is cleared set debug indicator to yellow and goto 1. Otherwise set debug indicator to red, goto 2 (but skip step 3)

  • Like 2
Link to comment
Share on other sites

Look at it this way. You have 2 kinds of code. One that can run during the visible display without causing glitches (game logic), and one that can't. (DL building code).

 

Your goal is to stuff all of the game logic into the visible screen because otherwise it eats your precious non-visible time and reduces the number of DL updates you can make.

 

Flagging the visible screen end (ie. after the last DL you actively update) with an interrupt is an optimization based on the above. It increases the effective non-visible time at the expense of visible time... if your game is logic heavy then it may not make a difference. If you game logic is light, it will allow you to display more objects.

  • Like 1
Link to comment
Share on other sites

One more question! Is it possible to flip sprites vertically? Or will I need to have both a left and a right graphic set for every single sprite in my game? If that's the case, I'm not sure I can fit all my graphics into the game.

 

Edit: Doing a bit of digging, it seems the 7800 can't flip sprites. But I wonder, via XM, if it's possible to copy and mirror the the sprites in ROM to XMRAM? Anyone thought of doing anything like this?

Edited by Roy
Link to comment
Share on other sites

It's possible to copy and mirror, but a bit complicated. Bear in mind you'll need to mirror based on sprite width and also preserve the color indexes. Ie. 1010000 isn't the mirror for 00000101 in 160A. 01010000 is.

 

If I was in your shoes and I wasn't targeting XM anyway, I'd prefer to just use a larger cart format

  • Like 1
Link to comment
Share on other sites

There's no hardware mirroring or scaling of sprites on the 7800, so you'll need to create separate graphics for each. Yes, you could do it programmatically, but that would burn CPU time and some RAM. Better / easier to simply make multiple sprites. (Palette tricks, however, can be used.).

  • Like 1
Link to comment
Share on other sites

Well, I did have XM in mind with this project. Thing is I have so many sprites, plus needed background graphics, that I don't think I can fit everything if I did both a left and right. I also want to stick to a normal 48K rom size.

I did get a routine working that can properly flip the graphics, but I can't find much documentation for accessing the XM features. No clue how to write to external ram! I found something for the xboard, but initial tests crashed the program the second I wrote to $0470 to enable ram.
At it's core, without looping through the entire graphics, this is one byte being flipped for 160A mode:
	lda oldByte
	and #%00000011
	ror
	ror
	sta var1
	lda oldByte
	and #%00001100
	rol
	rol
	sta var2
	lda oldByte
	and #%00110000
	ror
	ror
	sta var3
	lda oldByte
	and #%11000000
	rol
	rol
	sta var4
	
	lda newByte
	clc
	adc var1
	sta newByte
	lda newByte
	clc
	adc var2
	sta newByte
	lda newByte
	clc
	adc var3
	sta newByte
	lda newByte
	clc
	adc var4
	sta newByte

I figure something like this, plus additional looping, can be run before the game even starts as to not get in the way. I guess the idea is to sacrifice ram for more rom. (levels!)

Edited by Roy
Link to comment
Share on other sites

Your 48K ROM occupies address space from $4000 to $FFFF. The XM/XBoard RAM is mapped at $4000.

 

Assuming your crash was due to the ROM at $4000 being replace by RAM. Even if you work around this in emulation, e.g. by ensuring the PC is past $8000 when you switch RAM on, I'd expect bus contention to give you whacky results on real hardware.

  • Like 1
Link to comment
Share on other sites

Heh, that would make sense! Unless that segment of rom were all graphics, bank swapping $4000 - $7FFF sounds like it will give me more headache than anything.

 

I may just bite the bullet and sacrifice some rom for more graphics and make some cuts here and there. Thanks for your help, guys.

Edited by Roy
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

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...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...