Jump to content
  • entries
    40
  • comments
    39
  • views
    28,036

timings and map tile cursor

Sign in to follow this  
brpocock

331 views

Timings on the first row are perfect, and the HMP0/1 bugs are basically flushed out finally, so that's all good. There's still some crap involving line (7,2) on each row, but there should be sufficient SLEEP cycles now that I don't use WSYNC to make up for it. A new bug that crept in somewhere there, though, is that the cursor pointing into the map data seems to be drifting.

 

Here's the lowdown. There's a big macro that draws a line. Lines are grouped into triples, and odds & evens. So, the main drawing loop for one row then just calls that macro 24 times:

row_start:
 DRAW_LINE(0,0,0)  ; Triplet 0, first line, this line is even
 DRAW_LINE(0,1,1)
 DRAW_LINE(0,2,0)  ; Triplet 0, third line, this line is even
 DRAW_LINE(1,0,1)
 DRAW_LINE(1,1,0)
...
 DRAW_LINE(7,2,0)

OK, so far so good, right? Line (7,2) -- which currently bears the lovely debugger breakpoint convenience label of "seven2" -- is a "no draw" line which prepares for the next row. So, really, I'm drawing 23 lines.

 

Depending on which line I'm on, I precache various data like the tile pointers for the next row or the bitmaps for the next line triplet. Even and odd lines alternate updating decorative tiles (P1) or the player (P0) as appropriate. There are tile ID pointers in RAM for "this row" and "next row" (copied over in (7,2) after being decoded during the row), and the triplets precache bitmap data for the next triplet, and alternate between an "odd triplet#" and "even triplet#" bitmap buffer for drawing PF1/2 left/right. (e.g. during line triplet 1 I precache the bitmaps into the "even" buffer while drawing from the "odd," then in line 2, precache "odd" while drawing "even").

 

During this maddening mass of multiply-indirect lookups, I have to hit PF2 exactly at the middle of every scanline and HMOVE exactly at the end. (I can't spare any screen lines to use RESP1 to position decorative tiles -- other than the top row -- so I have to use HMP1 to move the P1 position if there's a decorative tile on a lower line not in the same column.)

 

The important thing I have working, now, is that the PF2 and HMOVE always hit at the right time. It's a tiny thing to have no HMOVE bars, and in fact, I'd probably be just as happy to have them all the way down, but once you're into that kind of cycle-exact timing mess to do reflected asymmetric playfield, you might as well go full monty.

 

"seven2" however is not always exiting at precisely the right cycle. Also, I advance the pointer into the map at various times in the loop, basically every time I pull a tile ID out of the map I "inc" the map cursor, and at the end of a row I have to skip over some colour and decorative tile data to start the next row. Well, somehow in all that mess, I'm getting the map cursor off by one (and I haven't looked at it closely enough to figure out just how), so it'll start pulling colour data in as though it were tile ID's, thus looking up garbage data in ROM instead of valid bitmaps, and likewise getting decorative tile bitmap pointers instead of colours, and so on. Basically the whole "wild pointers are bad" "well, no shit" story.

 

So, that's the last real hold-up on the tile-draw, although i've got an open "RFE" to try the cleaner (pixel-based rather than tile-plus-pixel-offset based) joystick code out and see if it's reliable. I expect it actually will be.

 

Combat kernel is due for some pretty significant overhauls and then the connections between them all have to be stitched back in. The next time I test on the hardware I should be seeing the pieces working together. A public alpha test is not far in the future.

 

Given the amount of time I'm actually hacking on this, though (a couple of hours a week... I spend more time in the forums here probably, at 10 minutes a spell) "not far in the future" probably means early August for a real playable demo with all the major pieces intact. Some of that depends on Mayday's equally mad schedule, though. It would help to have some map data or graphics or scripts to all this :)

 

And, to that end, I need to write a new map coimpiler to handle the changes I made going to the "24lk" format.

 

Kernel size has actually grown a bit from the timing fixups, but there are a lot of NOP's that I can probably compress some work from (7,2) into them now. If so, I may even be able to update some of the graphics during (7,2) as well. It does annoy me to have "dead lines" all over the screen, even if they should blend in with the background nicely in the real world, I guess.

Sign in to follow this  


4 Comments


Recommended Comments

Have you remembered about page boundary crossings? They can add one cycle to your carefully timed code and are a real pain to avoid in unrolled kernels like this.

 

Chris

Share this comment


Link to comment
Have you remembered about page boundary crossings? They can add one cycle to your carefully timed code and are a real pain to avoid in unrolled kernels like this.

 

My suggestion for avoiding page-crossing nastiness is to arrange the kernel so that each bunch of stuff is page-aligned. If I have two groups of eight pieces of code, each about 120 bytes long, I'll put one group in the first half of each of eight pages, and the other group in the second half of those same eight pages. Wastes a little space, but not too much.

Share this comment


Link to comment
Have you remembered about page boundary crossings? They can add one cycle to your carefully timed code and are a real pain to avoid in unrolled kernels like this.

 

Chris

That one bit me while I was working on MM last weekend. I wasted about 4 hours trying to track down why the dragon's body started to fly faster than his wings :)

Share this comment


Link to comment
Have you remembered about page boundary crossings? They can add one cycle to your carefully timed code and are a real pain to avoid in unrolled kernels like this.

 

Chris

 

Thanks to the wonders of M4, and my total inability to perform long strings of arithmetic, and the joys of Stella, ... no ;)

 

I was worried about it at first. In fact, you'll see an earlier blog screenshot where I was having problems on I think it was line (4,1) because of boundary crossings. There's only exactly one branch in the kernel -- on every second line -- and it's always taken (i.e. one of two branches are taken, so there's always a branch). The thing is, I set all my timings experimentally, running in Stella and deciding to add (n) cycles to each line with a bunch of special-case code like

if [ $1 == 7 && $2 == 0 ]
   SLEEP 8
endif

When M4 unrolls the loop, it does so with the variables $1, $2, and $3 set to the triplet, the offset within the triplet, and odds-or-evens (I have an example in one of past couple days' blog entries)

 

To make sure that minor code tweaks never do "nudget" where the boundary falls, though, I did put in this monstrosity:

jmp draw_rows
align 256
draw_rows:

 

Thus guaranteeing that whatever I do to the prior code, the kernel will always start on a page boundary. That's fine for now (development); once I declare a "code freeze" I could probably compress out that gap and deal with the consequences once, but right now the rest of the kernel's in a state of flux, too, and I'm not as pressed for space now as I shall be, shortly.

 

Incidentally, the kernel (unrolled) for tile drawing is weighing in around 1K, which is terrible because it constantly accesses map data, thus preventing me from sharing it across memory banks. (I can't do mad amounts of bankswitching within the kernel).

 

Here's the frightening but plausible thing I thought of ... splitting map data such that the data referenced during the first 6 scanlines was found always in bank 1, the next 6 in bank 2, the next 6 in bank 3, the last 6 in bank 4. But even with Perl compiling my data and M4 composing my code, I'm not insane enough to want to split the data up like that. It'd be a logistical nightmare, more so than it is already. So i've to bite the bullet and duplicate about 1kiB of "identical" (or nearly so) code in each memory bank that's to display tile-based data. Including support stuff, that's really closed to 6 pages, possibly more, of the 16 pages banked in. 10 pages isn't a lot of space, especially given that there are alignments needed for several data :)

Share this comment


Link to comment
Guest
Add a comment...

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