Jump to content

Pat Brady

+AtariAge Subscriber
  • Posts

    487
  • Joined

  • Last visited

Everything posted by Pat Brady

  1. This seems to be the big area of disagreement now. I'm apparently falling on the end of being more permissive. It's mostly based on my observation that flashcart firmware does not get updated very often. If emulators are restrictive, no big deal: a7800 is open source, any developer can patch in whatever they need whenever they need it. But if flashcarts are restrictive then it is a big barrier. To be clear, I am talking about combinations of features that are already supported. I am not asking anybody to code up some fantasy mapper or sound chip. OK, point taken. Well, following your logic above, if you mirror the whatever-it-is, you can save some lines. For example POKEY@$0400 with 7 mirrors up to $047F would save 3 address lines. Is there anything between $0800 and $0FFF? Giving that entire chunk to a POKEY would save another 2 lines. (Since there is precedent for 2xPOKEY it might be best to split that area into two; that would still save 4 lines compared to $0450.) Anyway, I don't know if that's what @batari had in mind but he certainly seemed to have something in mind. I hope he proposes it.
  2. LOL And I had just looked at the list of bankset formats and specifically looked at which ones map POKEY where and still didn't notice that 2x48K put POKEY at $4000 and it has the words "write-only" protruding out the right hand side. Don't really need more projects but will keep this in mind. I know Verilog, but have never done PCB layout and lack expertise in components. I would hope that a programmer would not choose a strange combination unless there is a good reason for it. And IMO documentation (and ideally a warning in the header generator and/or an emulator) is sufficient for this issue. In my case, my format is unusual but not difficult (32K ROM+8K RAM). If it ever gets a cart release, it may be on a standard SuperCart board, maybe with a 128K ROM and a 16K RAM, just because that's more common in 2022. But for emulation and flashcarts, I believe the 32K image should work, even though that hardware doesn't currently exist. In the example @RevEng gave above, Bankset with Bank 6@$4000 and POKEY@$0450, just document that the currently available board can't do that. If a programmer chooses that combination anyway without actually needing that combination, to me that's a bad programming decision on par with "I refuse to turn DMA on." On the other hand if a programmer does need that combination, then it's best that emulators and flashcarts support it. That way programming can happen in parallel with hardware development. (FWIW my hunch is that Bankset will drastically reduce the need for Bank 6@$4000.) With all that said… Programmers use POKEY@$0450 because that's what's available, no other reason. POKEY@$4000 is fine, unless ROM or RAM is there. If you have a better idea, and it's supported in emulators and flashcarts, I expect programmers will be interested. And in particular, if possible and @RevEng and @mksmith are willing: move the bankset POKEY to somewhere better! Now is the time to do that. BTW — I don't think I've formally asked: please add support for 32K+RAM@$4000 to the next Concerto firmware.
  3. @TailChao: SUPER + EXRAM_A8: AFAIK this has not been used, but it seems both useful and easily implementable. I vote to handle it. SUPER (or no mapper) + POKEY@$4000 + anything else at $4000: AFAIK this has also not been used, and with the availability of POKEY@$0450, why would anybody do this? Especially EXRAM. IMO POKEY@$4000 should be mutually exclusive with anything else @$4000 in the same way that the various mappers are mutually exclusive. I appreciate this. It makes complete sense. I am surprised that the amount of logic required for other configurations affects the cost. Not questioning or doubting you at all. It's just not what I would have guessed. I predict the 4 128K options will be popular.
  4. A post about how to organize your RAM and build your DLs. I don't know whether this idea is novel, but I have not seen it described anywhere. I share it in the hopes that it is useful to some other 7800 developer. Z means number of zones, B means number of background (static) headers per zone, and S means number of logical sprites. Each logical sprite has one header if it fits in one zone, or two headers if it crosses zones using holey DMA. I believe the conventional approach is to reserve enough RAM for each DL to contain every sprite that might ever appear in the corresponding zone. Since most games have multiple sprites that may or may not be in the same zone, this requires Z*(B+S) headers. This can waste a lot of RAM! For 7iX, that wasn't feasible due to how much RAM is used for the playfield and enemy. Instead, I have one block of memory that stores all the headers contiguously. I only need space for Z*B+2*S headers, the same as the number of objects on-screen. The obvious way to do this is a nested loop of zones and objects, which is O(S*Z), unacceptably slow for many cases. I developed this algorithm which is O(S+Z). The algorithm is: Set aside Z+1 bytes of temp RAM. Call this space C. Loop over zones. Initialize C[z] to B. (CPU cost: 8 cycles per zone — a bit more if B is variable.) Loop over logical sprites. Calculate zone z based on the y position of sprite s, using a lookup table or power-of-2 division. Increment C[z]. If the sprite crosses zones using holey DMA, also increment C[z+1]. (CPU cost: ~40 cycles per logical sprite.) Loop over zones, keeping a running offset from the start of my header block. Emplace headers for static objects and 2-byte DL terminators. Update the DLL entry. Skip over enough space for sprite headers for zone z. Replace C[z] with the offset for zone z. (CPU cost: ~105 cycles per zone that can contain sprites, assuming 2 static objects per zone.) Loop over logical sprites. Calculate zone z as in step 3. Emplace headers for sprite s, using C[z]. Increment C[z] by header size. Do the same for zone z+1 if the sprite crosses zones. (CPU cost: ~200 cycles per logical sprite, less if it doesn't cross zones, should be about the same as for static allocation.) So suppose Z=12 and S=16 with 4 byte headers, keeping the assumption of 2 static objects per zone. This algorithm will take about 48 scanlines of CPU time, too slow to fit entirely in VBLANK, but fast enough to finish in the total offscreen with time to spare (unless you go way over 192 lines displayed). In this use case, the conventional approach needs 888 bytes for headers. This algorithm only needs 248, a savings of 640 bytes. I believe you could reduce the off-screen CPU time by doing steps 1-2 on-screen. They don't touch anything MARIA looks at. (I have not tried this.) Or, if you double buffer, then no need to finish the algorithm in off-screen time, and the RAM savings increase to 1280 bytes. In fact the double buffer with this algorithm uses significantly less RAM than single-buffered conventional allocation. (I have not tried this either.) If anybody finds this useful enough to use, I'd love to know!
  5. Not an emulator. Concerto. (According to @Trebor, it also fails in ProSystem, but I don't use that.)
  6. Interesting point. I still suggest *representing* them as I described (which is also the least error-prone for implementors, 2 small lists of possibilities instead of one huge one that then has to be decoded into those same 2 values). You can curate a list of combinations that work — or a list of combinations that do not, whichever is easiest. Good point. TBH that's pretty far down the list of niceties I'd like to see in a7800. But, it certainly wouldn't hurt to add that piece of information. With the structure I proposed, 8K EXRAM is just one entry in the "what's at $4000" enumeration. I didn't say it doesn't exist, I said it's not in the list of things that exist.
  7. It's been a while, but IIRC I tried that, and eventually gave up and started making ROMs padded out to 128k. Apparently even 64K+EXRAM does not work because that is also not in the list of things that exist. Another example would be a 48K ROM with POKEY@$0450. Or a 32K ROM with YM2151. Those are trivial to implement (assuming POKEY@$0450 and YM2151 are already supported) but are not in the list of things that currently exist. I just see no reason to actively prevent them from working. My updated proposal (bottom of post #82) differs from your proposal in only 2 ways: 1. Enhancements for SUPER also apply to 32K (and to bankset) 2. Enhancements for SUPER/32K/bankset are formulated in terms of what happens at $4000 and what happens at $04x0, and those are independent I've put a fair bit of effort into cutting my EXRAM usage down to 8K. My thinking was: this is an arcade game from 1981, and even 8K of RAM on the cart would have been lavish for such a game during the 7800's lifespan. Or more philosophically: use what I need, don't use what I don't need. But I do not need a bit in the header that says "this game uses 8K of RAM but not 16K." Even to me, who cares about this stuff, the purpose of the header is only to make the game work on emulators and flashcarts.
  8. For me it's hard to compare. It's just a very different challenge. Except for audio, where it's a very similar challenge.
  9. You list 16K-32K with EXRAM@$4000 as a possibility. Well, thank you for including that, and thankfully a7800 and apparently Dragonfly support it, but not everything does. AFAIK there's not much activity on Absolute and Activision bankswitching. So I don't particularly care what happens to those. SOUPER is currently used only for R&V, and from what you've described, it was sort of designed around what R&V needed. So it seems reasonable for it to remain as a single configuration too. We do know that bankset is coming and will likely use many of the same variations as SUPER. 48K can be seen as a 32K cart with EXROM @ $4000. So here's an updated proposal: have 2 bytes to specify mapping type (we already agreed on that). Have another 4 bytes for mapper-specific options. For 16-32K, SUPER, and bankset, the mapper-specific options will be divided into 2 fields as I described above (2 bytes for what's at $4000, 2 bytes for what's at $04x0), and these options will be consistent across those 3 mapper types. EDIT: this way I get what I want, which is to not have to worry about whether my combination of features that work together is in somebody else's list of blessed combinations, and you get what you want, which I think is to avoid the possibility of specifying combinations that don't make sense.
  10. So, for Activision+Mirror RAM — that's something that doesn't exist, and probably never will. But what I'm saying is: we don't need to even think in terms of the possible combinations. It's much easier to just think about each of the 3 aspects individually. Any list of combinations will ultimately map back to values for the 3 aspects anyway. My particular case is a 32K ROM that needs cart RAM. I believe that is a completely reasonable thing to do, 32K ROM is universally supported, cart RAM is universally supported, and the cart type bitmap even allows cart RAM to be specified independently. But this combination not universally supported, because some implementations apparently parse the cart type bitmap back to a list of known existing hardware, and the list of known existing hardware does not include 32K+RAM. So now any implementation that keeps such a list of known hardware combinations needs to be updated for this new combination, and meanwhile I distribute 2 different versions of my ROM. There's no need for the parser to ferret out stuff that can't be supported, or things that are not clearly defined (e.g. SOUPER RAM with anything other than SOUPER bankswitching). Just document that the behavior of Bank 6@$4000 is undefined unless paired with a bankswitching scheme that has a bank 6, and the behavior of SOUPER RAM is undefined unless paired with SOUPER bankswitching. On the other hand, if we go down the path of explicitly listing every allowed combination, then any time somebody uses any new combination, then every emulator and every flashcart will need to be updated. Even if they already support all of the features used. EDIT: I'm going to work up an in-between proposal.
  11. I felt like an entirely new format was a bigger sell but if you and @batari and @TailChao are on board, it is certainly fine with me. I think my main thing is I don't want us to crash into the 16-bit brick wall that is quickly approaching. I guess it won't be the end of the world if we do crash into it. But with a new mapper and a new sound chip being added, it feels like a good time to plot a course around it. I wrote most of this before @TailChao's comment #74. I propose the new format have 3 variables to replace the current cart type field: $40-$41: bankswitching scheme (current possibilities: none, Atari SuperGame, Activision, Absolute, SOUPER, bankset) $42-$43: behavior of $4000-$7FFF (current possibilities: none, POKEY, 16K of ROM, Bank 6, 16K of RAM, Fractalus-style mirrored RAM, SOUPER RAM) $44-$45: behavior of $04xx (current possibilities: none, POKEY@450, 2xPOKEY, YM2151, Covox, SN76489) Each of those to be indexed, not bitmapped. For existing capabilities there will be a clear map from the existing cart type bits to the new values. The important difference is that the new scheme provides a lot of headroom. New headers should continue to populate the existing cart type field where possible for compatibility. The number of combinations that don't make sense is much smaller but still non-zero (e.g. Absolute bankswitching with Bank 6 at $4000). I don't see this as a big problem. Just have the specification for Bank 6 at $4000 stipulate that its behavior is undefined unless paired with a bankswitching scheme that has a bank 6.
  12. James and Tanya @ZeroPage Homebrew, thank you for playing this game on your show. I had a lot of fun! I attached the current build. This is a bit newer than the main version you played, but the differences are mostly internal (I rearranged everything so that it only uses 8K of cartridge RAM). The 128k version is for any flash carts that don't support RAM without bankswitching. I was very pleased with how the version with lines looked on the show, but I am not posting it yet. It lacks collision detection, it draws some lines incorrectly, and it is highly unstable. Hopefully soon! I had forgotten about dark mode (from the initial screen, push down repeatedly until the walls disappear). I intended the color selection purely for testing colors, but dark mode turned out to be a fun variation. Glad you discovered it! The issue with narrow fill being drawn as a thick wall only occurs horizontally. A tall, skinny area looks like a thick wall, but a short, wide area appears correctly. In either case, it does not affect gameplay. It is possible to draw between segments of the 7iX. I do not consider that a bug — but it will be much harder to accomplish when the 7iX is made out of lines. Scoring, for anybody unfamiliar with the arcade game: blue fill is 100 points per 1% claimed, with individual points for fractions of a percentage (thanks to @johnnywc for sharing that). Orange fill scores double. After completing a level, 1000 bonus points per percentage claimed beyond the threshold. I am happy enough with the new TIA sound that I doubt I will use AtariVox for music in this project. It's an interesting idea that I hope to explore, but it will probably be in a different game. Plans: 7iX made out of lines, fuse, multiple sparx, double 7iX, bells and whistles. 7iX-2022-03-05.a78 7iX-2022-03-05-128k.a78
  13. Responded to both of these in the a78 header changes thread. I agree, @rj1307's SN76489 board and @Eagle's tunes are very cool.
  14. I totally agree with all of this, and I in turn want to clarify that while I used AY-3-8910 as an example of something that might be coming in the future, I am not proposing to actually define such a cart type until somebody actually uses it. It was just an example (admittedly, one that I would like to see) but the real point was that SN76489 is probably not going to be the last audio chip to ever be put in a 7800 cart. Especially since "audio chip," in this context, is fungible with "software running on a microcontroller that's already on the board." Compared to defining bit 13 as banksets and bit 14 for SN76489, what I'm proposing actually saves a bit in the cart-type field, and, I believe, will be compatible with all in-the-wild .a78 files. I don't know the implications of updating the version byte. Mapper indexes (and audio chip indexes) was what I had in mind, though I realize I didn't explicitly say so. Slightly swamped right now but I'll write it up more formally later this week. EDIT: I don't mean to be dismissive of the version byte idea. It wouldn't surprise me if you do know what all of the actively-supported flash carts do with it. I just feel like re-using bits that are already (or soon to be) allocated is less risky. I might be wrong of course.
  15. What has happened before? The current format has 16 bits for cart types. That probably seemed like plenty back when the header was being defined, but now 13 of those bits are defined in the header doc, and 2 more (bankset and SN76489) are on the way. That means the existing scheme only has one bit remaining. Unless people stop developing new hardware, something has to give. I am not proposing to define a bunch of new cart types for things that don't exist. I am proposing to create space so that new cart types can be defined as they are invented. Which can start with a couple of projects already underway but not yet finalized.
  16. There has definitely been an explosion of audio options, and if SN76489 is already on the table then it's probably only a matter of time until somebody does AY-3-8910, and who knows what else. My suggestion is: instead of continuously adding one bit for each new audio chip, add one bit now for "new audio option" and then encode the specific new chip somewhere else. For instance, use bit 14 for "new audio option" and then when bit 14 is set, decode the actual audio chip from, say, a byte (or even 2 bytes?) at $3B. This way we can use indexing for new types without breaking compatibility with existing images. Might want to do something similar for mappers. Instead of bit 12 = SOUPER, say bit 12 = "advanced mapper" with the mapper type encoded at $3D, SOUPER = 0, Banksets = 1… That will be compatible with existing R&V images as long as they have 0 at $3D.
  17. Indirect mode just means use the char map to select graphics data, nothing more. If you draw overlapping objects, and the last one has transparency, the other one(s) will show through, regardless of DMA mode. You may have gotten the holey stuff wrong. Maybe you did not offset the high byte? For example, if some graphics data start at $E0xx, and you want it to show up 3 lines below the top of the zone, set the high address byte to $E3: MARIA will read the top 3 lines for this object from $F2xx, $F1xx, and $F0xx, which holey DMA will treat as zeros. After that MARIA will read $EFxx (the top line of the actual graphics data) and so forth, all the way to $E3xx at the bottom of the zone. Then, typically, you draw the remaining 3 lines in the zone below, by setting the header's high address byte to $D3. For purposes of drawing backgrounds, the graphics are typically aligned to the zones. (To be clear, "background" is a use case, not a formal distinction to MARIA.) Yes (but only 7 colors, since background/transparency is shared across all palettes). 160B will probably be more efficient, and give you 13 colors instead of 7. But — assuming kangaroo mode is off — overlaying 160A objects will work, if that's your preference. I think people think of 2-byte chars as meaning only getting 128 chars. That's not quite right, since they can overlap, as you have discovered. The real limitation is 256 bytes. The data in your image uses only 128 bytes per page. No reason you can't use the other half for more chars (or other assets, if you'd prefer).
  18. Well, thank you. Your title screen rendition of When Johnny Comes Marching Home is excellent itself. I caught the end of your segment on ZPH and have only played the game for a few minutes but the whole thing looks great. The animated scores are a fantastic detail. EDIT: I forgot this was 4K. Very impressive!
  19. It's certainly possible I'm missing something, but since you have a relatively small number of zones and dynamic objects — meaning player, enemies, NPCs — I think you should be okay on RAM. By my quick calculation (8 zones, 11 160A tiles across, up to 4 160B dynamic objects per zone), doing everything in direct mode, the DLs will total 536 bytes. Going up to 10 zones increases it to 670 bytes. This is all of the headers. And, doing it this way you shouldn't need any RAM for playfield map translation. And, as RevEng mentioned, this way each tile can have its own palette. The DLL is another ~50 bytes. Obviously I don't know how much RAM you need for game logic and state. I believe so, though haven't tried it myself. Come to think of it, I may have done that by accident at some point.
  20. Wait! Before you do that: the 7800 doesn't have a limit on the number of sprites. In fact you will notice that the Software Guide never uses the word "sprite." When @RevEng and others say "sprite" they really mean any object drawn in direct mode. In your case, since your background tiles are 4 bytes wide, you can draw them in direct mode with almost no penalty. And if you go that route, you can make however many tiles you want.
  21. If you're looking for an existing TGI implementation on the 7800: I doubt that exists. If you're thinking about implementing TGI yourself: IMO a full-fledged TGI implementation will be a lot of effort, will be overkill for Wizzy, will require at least 8K of on-cart RAM for a frame buffer, and will probably run you out of CPU time when you start to use it. If your Wizzy Lynx code uses TGI (or pseudo-TGI) functions only to draw backgrounds, sprites, and text, and maybe a few shapes at fixed locations, then I think it is probably feasible to implement the functions you need and re-use a lot of your existing Wizzy code. (I'm assuming you don't use functions like tgi_settextscale() or tgi_ellipse() with variable parameters.) But in order to do implement those functions, you need to be able to do at least Hello World in low-level C (or assembly). How's it going with the Software Guide?
  22. Got all 3 controller types working. Thanks to @Trebor and @RevEng for your help. Here is my startup code: start sei ; disable maskable interrupts cld ; clear decimal mode lda #$07 sta INPTCTRL ; lock into 7800 mode (7800 Stds&Procs) ldy #$00 ; use Y: it will persist while A does other stuff sty VBLANK ; aka INPTCTRL; also enables HALT per enhanced 7800 SG sty OFFSET ; "for future expansion" (7800 SG, 7800 Stds&Procs) sty CTLSWA ; controllers are input-only ; do any other startup code here lda INPT1 bmi initgenesis ; b if pin 9 (7800 L or Genesis C) is 1 ; if Genesis not detected, assume 7800 2-button controller, can change ; to 2600 1-button later lda #$04 sta CTLSWB ; enable 2-button 7800 controller 1: set pin 6 to output sty SWCHB ; enable 2-button 7800 controller 2: pull pin 6 (INPT4) high sty ctrltype ; 0: 2-button 7800 controller bne reset ; based on lda #$04; always b initgenesis sty CTLSWB ; set all pins to input iny sty ctrltype ; any non-0 +ve: Genesis controller reset lda #$63 sta CTRL ; disable DMA (for now) (7800 Stds&Procs) ldy #$00 ; use Y: it will persist while A does other stuff ; turn off audio sty AUDV0 sty AUDV1 ldx #$FF txs ; initialize stack pointer And here is my button-read routine: subroutine ; jsr readbuttons ; read controller buttons ; return value: $00: no button, $80: left/B button, $40: right/A button ; preserves X,Y lda ctrltype bne .readgssor2600 bit INPT4 ; 2600 button (or Genesis B) bmi .read7800 ; disable 2-button 7800 controller lda #$04 sta SWCHB ; don't pull pin 6 (INPT4) high lda #$00 sta CTLSWB ; set pin 6 to input lda #$FF sta ctrltype ; any -ve number: send next read to .read2600 .lbuttonpressed lda #$80 ; bit 7 rts .readgssor2600 ; Genesis or 2600 controller bmi .read2600 bit INPT4 ; Genesis B bpl .lbuttonpressed bit INPT1 ; Genesis C bmi .nobutton .rbuttonpressed lda #$40 ; bit 6 rts .read7800 bit INPT4L ; L button bmi .lbuttonpressed bit INPT4R ; R button bmi .rbuttonpressed .nobutton lda #$00 ; no button rts .read2600 ; 2600 (1-button) controller ; separate from Genesis handler to prevent spurious Genesis C reads bit INPT4 bpl .lbuttonpressed bmi .nobutton ; always b Everyone feel free to use this in your project, with or without modifications. (Depending on your project, you might want to swap the button prioritization, or detect both buttons pressed…) EDIT: my game is one-player. For a two-player game (or a one-player game using two controllers), initialize CTLSWB to #$14 instead of #$04. You may also want to add code for mixed controllers.
  23. 1. Okay, that works for me. 2. It turned out my reset-switch debounce loop covered almost all of my initialization code. (I certainly don't remember why I ever thought that was a good idea.) Not sure why that matters, I wasn't holding down the reset switch, but after I reduced that loop to the minimum (lda SWCHB, lsr, bcc), the 2600 one-button controller works fine. So now just gotta make Genesis work. I think I have the polarity wrong on button C, not sure that completely explains what's happening, but hopefully I can figure it out from here. 3. I think I understand. INPTCTRL is a MARIA register, VBLANK is a TIA register, both are mapped to $01, and the idea is to enable and lock INPTCTRL, then write the desired VBLANK values.
×
×
  • Create New...