Jump to content
IGNORED

Too many cycles


Propane13

Recommended Posts

Hello!

 

So, I was working on a project, and then a situation hit me that I think could be a real tripping hazard for 7800 programmers.

If I remember right, if you have more cycles of calculations than the space between VBlank starting and MARIA's next screen drawing routine, then on real hardware, you'll have some issues. I think (correct me if I'm wrong) that MARIA will go ahead and start drawing the next frame, interrupting whatever calculation you're on, but when she returns, you may have some register corruption. I think I remember running into something like this a few years ago.

 

Since this seems to be a valid situation that emulation does not trap (maybe it indicates that an issue is present with some subtle graphics glitches), I was wondering:

1) How many cycles are there between when VBLank starts (let's assume a worst-case scenario, when MARIA's last DLL is full of data), and when MARIA starts drawing the next frame? Is that an easy number to derive or estimate?

2) Is there any way in emulation or with a tool to see how many cycles some code is using in order to make sure you end up under that threshold?

What would be perfect is if I could press a button in prosystem and have it give a count of the cycles between MSTAT reads/writes/BIT commands. If it was over the cycle threshold in 1, put the color in red, if under, put it in green.

 

I know the 7800 community is limited, but I wonder how other programmers deal with this issue.

Optimization is the solution, sure, but how do you know when you've surpassed the threshold, or how close you are?

I guess the other possibility is to disable MARIA drawing when calculations take longer than expected, but I'm thinking that's more of a workaround than a correct solution.

 

Thoughts?

-John

Link to comment
Share on other sites

Maria doesn't corrupt anything the CPU is doing, it just steals cycles which is transparent but can affect anything time-critical.

 

There's 114 CPU cycles per scanline, but that drops if Maria is doing DMA or you want to access TIA or RIOT.

 

There's a maximum of 242 "active" scanlines NTSC or 292 with PAL from a total of 262 or 312.

 

Generally the "vital stuff" that must be done before active display starts is things like setting pointers or changing colour registers. So the trick is to do that kind of thing early in VBlank processing.

 

In theory you could use a DLI near the bottom of your screen and start VBlank processing early to gain more cycles. Of course the trick there would be to not do anything that would cause screen glitches while the display's still active.

 

Another thing is to try and keep the VBlank processing tight - if something can execute in the mainline code then put it there. Sometimes the only reason for doing something at a particular time is because some variables might need to be tested before being updated, e.g. object positions. But an alternative method could be to make copies of certain data before updating it, then do that processing later.

Link to comment
Share on other sites

Whoa, wait a sec-- that is an interesting idea for a trick.

So, are you suggesting that when you start drawing the "blank lines" of the screen (i.e. overscan), you can do the following:

- disable MARIA output

- adjust the stack, since you ain't coming back from this DLI

- start your calculations

 

And then, when you're complete, wait for vblank, and then re-enable MARIA?

 

That's a slick idea. But, would it work? I wonder if anyone's tried it.

 

-John

Link to comment
Share on other sites

Taking an example from the Ms. Pac-Man source code, I do something very similar in all of my games.

I mark the last zone (the blank lines) in a display list with a DLI, and start doing sound processing, sprite positioning, and sometimes other things during VBLANK.

 

Using the example from Meteor Shower:

;  THIS IS THE DISPLAY LIST LIST.  THIS WILL BE DROPPED INTO RAM.
DLLIST
;PAL
;PAL	 .byte    $0F,>(NULDLST),<(NULDLST)			    ;25 ADDITIONAL BLANK LINES FOR PAL
;PAL	 .byte    $08,>(NULDLST),<(NULDLST)
;PAL
	 .byte    $0F,>(NULDLST),<(NULDLST)			    ;16 BLANK LINES
	 .byte    $04,>(NULDLST),<(NULDLST)			    ;5 BLANK LINES

	 .byte    $C7,>(SCDLIST),<(SCDLIST)			    ;SCORE ZONE -  8 LINES - WITH INTERRUPT
	 .byte    $4F,>(DLIST00),<(DLIST00)			    ;PF ZONE 00 - 16 LINES
	 .byte    $4F,>(DLIST01),<(DLIST01)			    ;PF ZONE 01 - 16 LINES
	 .byte    $4F,>(DLIST02),<(DLIST02)			    ;PF ZONE 02 - 16 LINES
	 .byte    $4F,>(DLIST03),<(DLIST03)			    ;PF ZONE 03 - 16 LINES
	 .byte    $4F,>(DLIST04),<(DLIST04)			    ;PF ZONE 04 - 16 LINES
	 .byte    $4F,>(DLIST05),<(DLIST05)			    ;PF ZONE 05 - 16 LINES
	 .byte    $4F,>(DLIST06),<(DLIST06)			    ;PF ZONE 06 - 16 LINES
	 .byte    $4F,>(DLIST07),<(DLIST07)			    ;PF ZONE 07 - 16 LINES
	 .byte    $4F,>(DLIST08),<(DLIST08)			    ;PF ZONE 08 - 16 LINES
	 .byte    $4F,>(DLIST09),<(DLIST09)			    ;PF ZONE 09 - 16 LINES
	 .byte    $4F,>(DLIST10),<(DLIST10)			    ;PF ZONE 10 - 16 LINES
	 .byte    $4F,>(DLIST11),<(DLIST11)			    ;PF ZONE 11 - 16 LINES
	 .byte    $8F,>(NULDLST),<(NULDLST)			    ;16 BLANK LINES - THIS IS THE INTERRUPT THAT STARTS VBLANK PROCESSING
	 .byte    $05,>(NULDLST),<(NULDLST)			    ;6 BLANK LINES
;PAL
;PAL	 .byte    $0F,>(NULDLST),<(NULDLST)			    ;25 ADDITIONAL BLANK LINES FOR PAL
;PAL	 .byte    $08,>(NULDLST),<(NULDLST)
;PAL
	 .byte    $00,$00,$00
DLLEND
DLSTLNG   EQU	 DLISTEND-DLIST
DLLLNG    EQU	 DLLEND-DLLIST

 

Then, in the DLI code:

;  KERNAL - MAINTAIN THE ON-SCREEN DISPLAY
DLI	  
	  PHA						    ;STACK REGISTERS
	  TXA
	  PHA
	  TYA
	  PHA
	  CLD
	  LDA	 DLIFLG			    ;MARKS WHICH DLI WE ARE AT ($00 = TOP, $01 = BOTTOM
	  BEQ	 DLITOP
	  JMP	 DLIBOTTOM
DLITOP
	  LDA	 #$01				    ;FOR NOW, WE DO NOTHING AT THE TOP DLI BUT UPDATE THE FLAG
	  STA	 DLIFLG
	  JMP	 DLIOUT			 
;  THIS ROUTINE TAKES CARE OF THE LAST DLI ON THE SCREEN, THE 'VERTICAL BLANK
;  ROUTINE'.
DLIBOTTOM
	  LDA	 #$00
	  STA	 DLIFLG				 ;RESET FOR TOP DLI
	  INC	 RTLOCAL+1			  ;INCREMENT CLOCK
	  BNE	 DLICONT
	  INC	 RTLOCAL
DLICONT
	  JSR	 LOADER				 ;LOAD UP NEXT FRAME (UPDATE SPRITE POSITIONS)
DLIWAIT
	  BIT	 MSTAT				  ;WAIT FOR VBLANK
	  BPL	 DLIWAIT
DLIOTHER
	  JSR	 TUNER				  ;DO TUNES
	  JSR	 RAND				   ;UPDATE RANDOM NUMBER
DLIOUT
	  PLA						    ;UNSTACK AND LEAVE
	  TAY
	  PLA						    ;THIS IS WHERE MOST DLI'S LEAVE
	  TAX
	  PLA
NULLRTI
	  RTI

 

 

Does this help at all?

Bob

Link to comment
Share on other sites

Why would you have too many lines? You control what's onscreen and when the display terminates via the sets of DLLs.

 

Having an interrupt and not returning isn't really a good idea, in theory the whole program could be done that way but it could become a nightmare to debug. If the int ever happened before all the previous required processing was complete then you could get data corruption.

 

Bob's idea is another good one - you can just set a flag that means "OK, the display is about to finish" which the main program can check, then clear the flag once you begin VBlank processing.

 

If you're worried about an interrupt taking way too long, you can also use a flag such that if another interrupt occurs, it will know that it's interrupted the previous interrupt, ie test and set the flag on entry, clear it just before exit.

 

A good technique to see how long stuff is taking is to use colour bars. Just alternating the background between 2 similar luma values is usually enough.

Link to comment
Share on other sites

Everything I have done i have put a dli on the last line and essentially use it like a vbi on the 8-bit computers. the vbi builds/updates the dl's and dll's, plays sounds, etc. Game logic is done outside of interrupts. If anything needs syncd it can always be done with a timer updated in the vbi that you can wait for to increment. It obviously has to finish building the dlist structures before the Maria starts drawing the next frame. You can even start your vbi a little earlier if you don't need dli's at the bottom of the screen and Maria doesn't catch up to you but I have never had any problems completing building what I need to in the vbi.

 

There was one of the 7800 games (ms pacman maybe) that had two dlist buffers, and had a dli for each zone build the dli for the next zone and alternated between the two buffers. The calcs were done in the vbi i think, but the actual building was done in a dli. I often wonder if that was more a quick an dirty conversion from Maria1 to Maria2 although it probably saved a little RAM.

Link to comment
Share on other sites

I know that in the past emulators didn't track how many cycles MARIA used, I don't know whether current emulators track CPU cycles versus MARIA cycles. The only way MARIA could corrupt registers is via a DLI which doesn't properly preserve them.

 

I remember in SpaceWar! 7800 I had a DLI in the first inactive zone which would just set a flag then RTI. The main code would loop on that flag instead of MSTAT. I guess you could do away with that and pop the SR & PC off the stack and make the ISR the start of the routine. Wouldn't be a bad idea to have the ISR check a flag to see if the previous frame had completed first.

 

https://sites.google.com/site/atari7800wiki/ has some info on cycle counts and DLIs.

Link to comment
Share on other sites

  • 1 month later...

Ok, just to close out this thread-- there was an issue with too many cycles, but that wasn't my main issue.

The main corruption issue seems to have stemmed from not initializing RAM on the 7800 properly.

 

I'm guessing that emulation sometimes defaults certain memory areas to $00, whereas in a real hardware situation, such RAM locations could have any random value on power-up.

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...