Jump to content

Pat Brady

+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

Community Reputation

297 Excellent

1 Follower

About Pat Brady

  • Rank
    Chopper Commander

Profile Information

  • Custom Status
    formerly bizarrostormy
  • Location
    Madison, WI, USA

Recent Profile Visitors

3,599 profile views
  1. I've been enjoying your lists. Doesn't seem spammy to me at all.
  2. Here is a routine that works on 2 objects of the same size, either both 1 byte or both 2 bytes. It's mostly useful for checking 2 sprites (as opposed to playfield; it does not care what DMA mode is used to draw either object). This turns out to be less processing work, because it only needs to compare 1 sprite to 1 other sprite, whereas checking a sprite against an indirect-mode playfield usually requires comparing the sprite to 2 playfield characters per line, plus logic at the zone crossing. I calculate this takes about 1500 cycles worst case for objects 8 pixels wide and 16 pixels tall. Still totally untested. My next task is to write up a small demo. But I wanted to go ahead and share the code. collisioncheckeachpixelsprites.s
  3. No. Update: The code I posted recalculated the vertical offset every line and used a very slow shift loop. Better to just decrement addresses and use a lookup table. I have a version that is under 3000 cycles, but think I can get it faster still.
  4. OK, the code I posted earlier had some massive inefficiencies. I think I can get it down to below 3000 cycles for a 16-pixel-tall, 2-byte-wide sprite, regardless of alignment. That's still expensive but possibly usable in some games. I'm ironing out the kinks, but probably finished for the night.
  5. I agree, this is an improvement.
  6. Indeed, although I think real games can achieve perfection more affordably than this fully general routine. (And looking back over the code, it can definitely be made faster.) Overkill for your needs, and also for everyone else's. When I started I knew it would be expensive, but I didn't know it would be that expensive. Another thought: many objects are solid, and for most that do have gaps, the gaps don't matter for collision detection. So we could store (or calculate) the boundaries per line, then check collisions on those. I think this would be general but much faster than comparing pixels. I'll take a stab at that tonight.
  7. Okay, this caught my interest and I spent a while on it tonight. I worked up a routine that does per-pixel comparison between two objects. I attached it in case anyone is interested. It works on one 1-byte character and one 1-byte sprite, but could probably be modified to work on a 2-byte character, or on 2 sprites. It is totally untested, and I'm not sure it's worth spending any more time on. To use with a sprite that crosses zones, call it twice. To use with wider sprites, call it twice again. Worst-case performance, by my calculation, is about 200 cycles per non-DMA-hole line, 20 cycles per DMA-hole line, plus about 100 cycles of per-call overhead. So if you have 16-line zones, and you call it 4 times (2 zones and 2 bytes wide, with half the lines in DMA holes), it takes about 7500 cycles. That is a big big chunk of SALLY time. I don't know whether it's useful. Adding wide-sprite support within a single call would help. Maybe I'll look into that later. It's still going to be expensive. I reckon calling EmptyPixel with brute force on all those pixels would take somewhere around 10000 cycles in the worst case (40 cycles per call, 16*8=128 calls per object, 2 objects). And that doesn't include the calling loop. But in many cases, you have knowledge about your sprites and how they move. In particular, you might know that a sprite only moved 1 or 2 pixels since the last check, and you might know which pixels along its leading edge are solid. If you exploit that knowledge, you may only need to call EmptyPixel a few times, and you could do pixel-perfect collision detection in maybe 1000 cycles for an arbitrary 16-line sprite. Maybe much less if one of your objects is small and non-animated, like a projectile. This is probably a lot better for most games than any generalized routine. collision.s
  8. More micro-optimizations: it's possible I'm missing something, but it seems to me you can move lda #0 sta CSPtrLo into global initialization code (or omit it altogether if you initialize all memory to 0). And replace lda (CSPtr),y with lda CSPtrLo,y and get rid of CSPtr. EDIT: on second thought, it seems like you need lda (CSPtrLo),y /EDIT EDIT 2: This gets into how 7800basic allocates dims, which I am not familiar with. Regardless, I think you only need 2 bytes to store the address, and the low byte is always 0. In the bigger picture, I think it would be more efficient to check multiple pixels at once. I'll try to work up a routine for that.
  9. I understand what you mean. Making a game is work. But I like the look of your 7800 version, and the 7800 only has a few platformers. I hope the motivation to make it continues.
  10. Excellent idea! You will need to align the data, both vertically (by selecting the correct page for the object's vertical position, as described by RevEng) and horizontally (by bit-shifting data). Like RevEng said, the B-D modes are more complicated, but mostly not too bad. Here are the pixel numbers for each bit position: 160A: 33221100 160B: 1100xxxx 320A: 76543210 320B: 32103210 320C: 3210xxxx 320D: 32103210 In case it's not clear, pixel 0 refers to the right side, which is counter-intuitive to me but consistent with the Software Guide. In all cases, 0 in the bit (320A, 320C, 320D) or pair of bits (160A, 160B, 320B) for whichever pixel means that pixel is background or transparent. In 160B and 320C, the bits marked x select a palette and are irrelevant to checking whether a pixel is background or transparent. I am confident about 160A, 320A, 320B, and 320C, less so about 160B and 320D. To check whether a certain pixel is background, mask off all the other bits. For example, to check whether pixel 2 is background in 160A, bitwise-AND the byte with %00110000. Iff the result is 0, then that pixel is background. But for collision detection, you need to compare multiple objects. Comparing in 320A is straightforward, just bitwise-AND the objects' data. Iff the result is non-zero then they collide. In 320C, you can bitwise-AND the data, then bitwise-AND with $F0. For other modes, you probably need a 256-entry table to map each possible graphics byte for one object to a mask for the other object. For example, in 160A, %10001101 means pixel 2 is background and the others are not, so the mask would be %11001111. Then bitwise-AND that mask with the corresponding data byte for the other object, and iff the result is non-zero then they collide. Please let us know how this goes.
  11. The undocumented restrictions of C1 in 320B are a real bummer. But like Muddyfunster, I think you have used 320B well here and look forward to seeing what you create next.
  12. Ordered! I don't check facebook often so thanks for posting here.
  13. Very nice! I have been planning something similar, and was also surprised that nobody else had done it, but haven't gotten around to it yet. My idea is to use a use a DPDT switch, one pole selecting whether button 1 goes to pin 5 or 6, the other pole selecting the active level of the buttons, and an inversion circuit (off of the active-level signal) to pull pins 5 and 9 inactive. More complicated than yours but doesn't need that 6-pole switch.
  14. This is correct. From the Software Guide: "Another factor concerning 320 modes is that the horizontal positioning still happens like 160 mode. This means that in 320 modes, objects can only be positioned in 2 pixel increments." It makes sense: allowing 320 horizontal positions would require 2 bytes. If you really need 320 positions, you can use two bitmaps, one for even columns and one for odd columns. I'm doing that for the player sprite in 7ix because it helps with transparency artifacts, but in many cases it's probably fine to just move 2 pixels at a time.
  15. First of all, nice work so far. Turning corners works well. When you say AxB, what are A and B? Even within a single graphics mode, the limits are somewhat complicated. I've heard generalizations, but the optimum MARIA configuration really depends on what you're trying to do. For your Binary Land game, I'd recommend 16-line zones, indirect mode with 2-byte characters for the playfield (maze) blocks, and everything else in direct mode (sprites), including the side borders. By my calculations that should leave time to draw up to 16 sprites per zone (assuming each sprite is also 2 bytes wide). There are a few different ways to do the top and bottom borders, but that won't affect how many objects MARIA can draw in your playfield. The rationale for using indirect mode for the blocks is that they are often repeated within a zone and are evenly spaced. 2-byte characters are somewhat more efficient than twice as many 1-byte characters, and the drawbacks of 2-byte characters are unimportant here. You might be tempted to also use indirect mode for the side borders, but they can't go in the same character map as the blocks due to different palettes, and a dedicated character map for them would be inefficient. LMK if you want more or less detail.
  • Create New...