Jump to content

Pat Brady

+AtariAge Subscriber
  • Content Count

  • Joined

  • Last visited

Everything posted by Pat Brady

  1. Sounds great! So how does it work? Is that an RMT or LZSS player for the 7800? I thought RMT supported sub-frame timing, which I thought would be tricky on the 7800 due to the unpredictability of MARIA commandeering the bus, but I could be wrong on any of that.
  2. How do you do that? You may remember that I worked on a routine for per-pixel collision detection between two arbitrary sprites but it consumed a lot of SALLY cycles.
  3. It looks like using direct mode for everything solves your problem, so my apologies for complicating things. If you're curious about those terms: DMA is how MARIA, the 7800's graphics chip, reads the graphics headers and data from memory. DMA holes have to do with how MARIA reads objects that are not aligned to zones — a DMA hole is an area in the same zone as an object but above the top or below the bottom of the object.
  4. Check out Appendix 3 of the Software Guide, if you haven't already.
  5. I totally agree with this! I am sort of baffled by 320C's bad reputation. It is really very similar to overlaid 320A, but with more colors and less DMA cost.
  6. OK, I will continue with it, hope to find time tomorrow to finish it. EDIT: I got it to a point where it can be tested. One of the routines works correctly, the other doesn't. I will sort that out.
  7. Right, need to do those POKEY labels and also the code that uses them. I don't see any STIMER — is that the same as RANDOM? The real problem is that the .a78 header format does not currently support dual-POKEY. It supports [email protected] and [email protected], but even if we enable both, I doubt a7800 or Dragonfly will treat those as separate POKEY chips. I know some single-POKEY games blindly write to both sets of addresses for maximum compatibility. @RevEng any thoughts?
  8. Sounds great! I think the easiest way to merge the players is replace all of the labels (both definitions and references) with specialized labels and update the main loop to call both players. Not beautiful or space-efficient, but that's okay for a gameless audio player. I can take a stab at that if you want.
  9. Even aside from development effort, DMA time is already an issue, so I don't think 320 is in the cards without cutting back drastically on the number of objects on screen, and also reducing the colors. IMO Darryl has wrought a fantastic balance of sprite size, colors, and number of objects. His original sprites, if you study them pixel-by-pixel, are indeed pretty busy, but overall they convey the essence of the characters. The new one-eye Brutus is definitely cleaner, and makes it more clear what each pixel represents, but to me he looks less angry. Your 320 sprites do look great, though. These are overlaid 320A? When I experimented with overlaid 320A, drawn pixels in my upper layers obscured their "companion" pixels in lower layers. In other words, transparency only works when both pixels of a pair are 0, as described in the Software Guide, though that document is not clear whether that applies for 320A. (With this limitation, 320C is almost always preferable to overlaid 320A IMO.) But in your Brutus sprite, I see beige-brown-beige, and also beige-purple directly above purple-beige. How do you get per-pixel transparency?
  10. I've been enjoying your lists. Doesn't seem spammy to me at all.
  11. 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
  12. 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.
  13. 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.
  14. I agree, this is an improvement.
  15. 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.
  16. 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
  17. 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.
  18. 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.
  19. 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.
  20. 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.
  21. Ordered! I don't check facebook often so thanks for posting here.
  22. 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.
  23. 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.
  24. 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.
  25. MARIA's character width setting controls whether characters in indirect mode are 1 or 2 bytes wide. It does not do anything else. The number of pixels per byte varies among graphics modes, as SmittyB described in post #12. The character width setting has no effect in direct mode. I'm using the Software Guide terminology, so you may need to translate that into 7800basic jargon.
  • Create New...