Jump to content

Bruce-Robert Pocock

+AtariAge Subscriber
  • Posts

    207
  • Joined

  • Last visited

Everything posted by Bruce-Robert Pocock

  1. Lessons learned: How SaveKey's EEPROM works really, and how the 2k on-board EEPROM differs: SaveKey “blocks” are 64 bytes long, and game allocations are designed to align to those 64-byte boundaries. (You'll notice that on the great allocation list, Grizzards's relatively giant save files take up 12 blocks, 4 blocks for each of the 3 save game slots. Just based on having up to 30 Grizzards with 5 main stats each, that right there is over 150 bytes, plus the game progress data, game clock, score, potions, & other global data.) The 2k EEPROM, rather, uses a 16 byte block size. I had misinterpreted the documentation: this does not mean that you have only a 16-byte buffer to write from, it also means that any write will wrap around if you try to save more than 16 bytes or across a 16-byte boundary. For example, suppose you've set the pointer to $453 and wrote 16 bytes: Save16Bytes: lda #$04 jsr i2cStartWrite lda #$53 jsr i2cTxByte ldx # 0 - lda Buffer, x jsr i2cTxByte inx cpx #$10 bne - jsr i2cStopWrite jsr i2cWaitForAck rts Buffer: .byte 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 Let's assume that the area of the EEPROM was initialized to $ff (you can't guarantee that, but it's the usual value of a blanked EEPROM). What you probably intended was this: 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. a. b. c. d. e. f. $450. ff ff ff 00 01 02 03 04 05 06 07 08 09 0a 0b 0c $460. 0d 0e 0f ff ff ff ff ff ff ff ff ff ff ff ff ff What will actually happen is, the write “cursor” will wrap around on the same 16-byte page: 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. a. b. c. d. e. f. $450. 0d 0e 0f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c $460. ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff Note that you can write fewer bytes if you want (although, as the datasheet charmingly describes it, this will cause the entire block to “endure” a write cycle), but you can't write more than 16 bytes, and you can't write across a $10 boundary. So, one further remediation step that may be required to use the on-cartridge EEPROM is that you may need to audit your save records structure/write patterns to ensure that this does not bite you. It did bite me, both in saving global game data and in the arrangement of Grizzard stats in the save file – causing an “after the last minute” rework to the record layout for Grizzard stats.
  2. Here's a list of the changes from the last major release, to the final AtariAge version. Note that some of these features, like more save game slots and recording high scores, are particular to the AtariAge cartridge and will not be in the SaveKey version at all. Packaging design, as you've seen above Bug fix: music playing over the “Atari Today” jingle on Reset Added another Depot to the final area Score resets properly on New Game Plus Changed XP required to metamorphose Starting a new game must blank out Grizzards from a previous (erased) game in that slot Players using a specific cheat code cannot set the High Score Grizzards whose Max HP reached 255 would vanish from your party Ensured that an erased game is not overwritten until you confirm your name & Starter on the new game Reduced the code size of several things to make room Pinned top score at 999,999 points (no wrap-around) Support for saving to the AtariAge cartridge's internal 2kiB EEPROM Attract sequence always shows all 3 starters with equal time Current Grizzard's stats could be wiped out on New Game Plus Gary said something in early conversation that could not have happened yet at that point in the story, a.k.a. Gary sees the future Bug fix: AtariVox voices turned off after sailing Bug fix: Three Starter Grizzards appeared in party “You won” screen gives correct count of Grizzards caught (or metamorphosed into) Bug fix: New Game Plus copying current Grizzard's stats over a new Starter Speech on boarding ships was trying to speak garbage Procedure for encoding fake save games into EEPROMs to test game scenarios on the hardware Bug fix: Switching Grizzards could cause all Grizzards' Attack and Defend abilities to go to 255 Bug fix: Not creating a valid progress record when you visited a Depot Bug fix: Smaller buffer caused overwriting game slot signature Text sprites aligned properly for displaying the high score Bug fix: Game drops you in directly after the publisher screen Tested 7800 detection on the actual circuit board All of the monsters found in the manual (except, obviously, the Grue) can appear in the Attract sequence You can set the high score (when you win) Peter was missing … from the place to which he went when he went missing Manual regression testing across about a dozen test scripts Ensured that you couldn't load Grizzards that had not been caught You can erase the high score record by holding both Game Select and Game Reset while you power on Bug fix: same Grizzard repeating in the Attract sequence forever Bug fix: speech from memory bank 8 causing AtariVox to cough and sputter Bug fix: the beloved in Treble Village did not speak (via AtariVox) or the speech was from a future conversation compared to their text Bug fix: A first quest win saying “won again” Bug fix: The number of Grizzards caught on the “you won” screen would increase to include the new Starters being added to your party in New Game Plus if you read all of the credits and looped back around. Bug fix: HP could “wrap around” back to zero when healing massive amounts Adjusted Grizzards' colors Aligned all combat Moves or monster names to the same style Bug fix: Being able to re-catch a wild Grizzard after having metamorphosed one before Bug fix: Score wiped to 000,000 on defeating the final boss Secret room added in which to catch the Starter Grizzards you did not catch Bug fix: New games inherited unused potions from erased games in same slot Position in “your house" was not being set on New Game Plus Adapted SaveKey code for 24LC16B interface Added bosses to Attract sequence Attack results are moved lower on the screen When using the “cheat” code to start in New Game Plus mode, you can now enter your name on the save game slot NoSave build was broken Portable build was — and remains — broken Pressing Game Reset at any time during end credits starts New Game Plus Bug fix: After winning, if you cut power, your save game slot was ruined When unpausing, make music resume immediately Fixed colors of Uber Slimes Make NPCs in west Port Lion distinguishable by position Fisherman's conversation tree was broken Allow player names to start with a zero General level around end-of-game bosses Speech for “Hard Tackle” Move was the wrong phrase Added a secret dancing signpost with the build date information as an Easter Egg to be found Button III can be used to reset from the error screen (but hopefully you'll never see it) Adjusted wave motion for Aquax title/chooser screens Fixed giving out points for certain role-playing events Fixed some Fat Tony dialogue where he knew more than he should at that point in the story …and miscellaneous other, smaller changes. With the press onwards to PRGE, the web site has not yet been updated and I have not put up proper links yet for a 1.0 public release, but I will get to it sooner than later. In other news, Zephyr and I will be at PRGE (all three days), so do say “howdy” at the Expo if you're there!
  3. Exactly so, it's optional, but we make a lot of use of it for voice synthesis.
  4. Yes, but only for voice synthesis. As you're probably aware, we have full narration of combat as well as all NPC interactions and a lot more, so it can be quite chatty. You can tell if the AtariVox is detected immediately upon start up as it'll start talking during the Attract sequence. You won't miss much if you don't have one, although there are a few subtle bits that are only in the speech track.
  5. That's appreciated! While it's not as super fancy as some games, perhaps, the AtariAge boxed edition will have the box & cartridge, a 20-page manual (rather similar to the ones posted here over the past year, but edited and refined quite a bit) and a card with a map of Syrex. On the AtariAge release version, the AtariVox (which is optional) is just for voice; the “save game” and high score functions are totally routed to the internal EEPROM only. With eight slots to work with, I hope there's plenty of room for the whole family to have their own games going. (There will eventually be a final build of the SaveKey version as well, but it may be a little while before I put together a proper release build for that — definitely after PRGE, for starters.)
  6. A few little features have probably made it in at the last moment, and will be primarily in the AtariAge release at PRGE. High Score Registration. When — and only when — you defeat the final boss, you have a chance to set the High Score. Your player name and score will automatically be entered, and will appear in the Attract Sequence, unless someone unseats you. High Scores will only work on the AtariAge cartridge version (due to no room for the extra code on the SaveKey build), and if nobody has won the game yet, you won't see the high score screen appear at all. There's “only” around 40 major changes since the last release, and I will package up a SaveKey version of something very much like the final build later. Of course, that build will continue to require a memory device, and may be missing a few little details (like high scores) due to lack of room in the ROM. If you're at PRGE, be sure to check it out in person … and say “hi!” … and see if you can spot the changes 😃. There have been visual and even auditory tweaks in the attract/title sequence, the map screens, the combat engine, even the end-of-game sequence. One thing that has not changed are the four Easter eggs in the game. As far as I know, nobody seems to have found any of them, yet. Here's some hints. I'm not counting there the secret way to clear the High Scores table, which will also be revealed in due time. How big is it? While it's a whole 64kiB ROM, Grizzards does use almost all of it. In fact, we use over 98% of the available ROM space, with only about 170 bytes (2.6%) of duplicated code and data shared between banks. Also in future, for players, I've developed a partially-complete “Complete Guide” with the details of every monster, every Grizzard companion, and maps of every area of the game — not quite a walkthrough, but very close. I'll be finishing that up and making it available to anyone who wants to cheat look under the hood at how the game world is put together (from a designer's or player's, not programmer's, perspective) at some time in future. About that Save To Cartridge … how does it work? (For developers) As far as I know, aside from high scores and settings on Star Castle Arcade, Grizzards is one of the first (if not the first?) 2600 games to save your game progress directly on the cartridge, but I doubt it will be the last. The technique used for Grizzards is not ARM-based (there are apparently other techniques that could be employed there), but some very clever address-bus-based logic. batari has designed a "conventional" (non-ARM) board with a Programmable Logic Device that handles bank switching based on the usual “EF” style banking, which is the 64k version of “F4” banking. However, it does a bit more than that, as well. The PLD also presents four special i²c hotspots, and uses two other addresses from which to read. We've taken the SaveKey i²c library (based on the original by Alex Herbert) and created an API-compatible version that uses these new hotspots ratther than interacting with the control port, so the usual “higher level” i²c operations will all work more-or-less as you expect: i.e. i2cStartWrite, i2cStopWrite, i2cStartRead, i2cStopRead, i2cTxByte, and i2cRxByte. As such, there are six ROM addresses in high memory that can't be used in any ROM bank. Four of these are “don't care” values, like the banking hotspots, while the others must contain (for this driver to work) precisely a zero and a one. There is one major difference between addressing the SaveKey and addressing the on-cartridge EEPROM, and that's addressing. The SaveKey addresses you use are assigned from some certain “prefix,” for example, the SaveKey version of Grizzards uses memory starting at SaveKey address $1100. The Save-to-cart version starts at address $000. (Actually, $n00 where n = save game slot index.) Also, the SaveKey is a 32kiB EEPROM, divided into 64 byte pages, with an address range $0000 - $7fff; the Grizzards cartridge will have a 2kiB EEPROM in it, so the total address space is only $000 - $7ff. In order to keep life interesting, the 2k EEPROM uses the “i²c bus attention” byte to contain the upper 3 bits of the address. Look at it this way; in a SaveKey program, you might do something like this: SaveHighScore: jsr i2cStartWrite ; Sends i²c attention byte $a0 bcs NoSaveKey ; complain or ignore the lack of SaveKey lda #>SaveKeyStartAddress jsr i2cTxByte ; Sends upper byte of address, $00 - $7f lda #<SaveKeyStartAddress jsr i2cTxByte ; Sends lower byte of address ;; save data, &c. With the 2k EEPROM, that same code changes a little, to look instead like the following. Also, note that the i²c attention byte is also ORA'ed with the upper address bits when calling i2cStartRead, so you'll need to know the address's upper bits twice when reading data. SaveHighScore: lda #>EEPROMStartAddress ; 0 - 7 jsr i2cStartWrite ; Sends i²c attention byte ( $a0 | (A << 1) ) lda #<EEPROMStartAddress jsr i2cTxByte ; Sends lower byte of address ;; save data, &c. ;; … the same as above After PRGE, I'll rework the i²c library file into a more generally-useful form (as a drop-in file others could use) and also convert a copy to dasm format as that seems to be quite popular here. Kudos to batari for making this technique possible. And … keep an eye on the usual places this fall for the first previews of my next project, which is already in-the-works. It's very early, and many critical components simply don't work properly yet, but I think there's a good chance that some Grizzards fans might be excited about that game, as well. (No, it is not a Grizzards sequel nor port … it's something new and different.)
  7. For what it's worth, any of the games like this which are Genesis-gamepad-compatible, the Joy2b+ controllers will work on the 2600 or 7800 (Mapping button I ⇒ B ⇒ Fire, II ⇒ C), they just won't listen for Button III. I believe the Stelladaptor may not be compatible with the Genesis or Joy2b+ controllers, as per: I don't know if perhaps that has changed since 2005, due to either the various hardware revisions or firmware updates, though.
  8. The manuals look generally very good! A couple of small notes: Any progress since this save point will be post, however. (p. 10 of tech) shoppes (p. 2 of Queen's, and a couple of additional places) … seems to be the only word that's spelled in a kind of Elizabethan way? Insofar as the game itself … I did personally at first find the controls a little fiddley, but I think they grew on me. I don't have a concrete suggestion on how to "improve" them, so it may just be a necessary learning curve thing. The "G" for "Good" status seems a little redundant and I kinda wonder if it might be better to only show a Status Effect indicator when the status is not "good" or "normal." In general it plays really well, and looks "better than makes sense" on the TIA. Bravo.
  9. A few updates … we may have been quiet here on the forum, but we've been busily hacking behind the scenes. We've been working with @Albert to nail down manual, packaging, and such details, who has been long-suffering to get everything in place. Grizzards will be one of the games you can play at the AtariAge booth at PRGE! The AtariAge official Grizzards cartridges will include a save-to-cartridge capability thanks to @batari, so you will not need a SaveKey (or AtariVox) to save your progress. Each cartridge will have eight save slots available, which you can (if you RTFM) erase if you need to, but you can continue with New Game Plus in each slot as well. Of course, if you do have an AtariVox, you'll get the advantage of full narration of all NPC interactions and combat encounters, as well as various other bits. If you saw the trailer video posted previously, or have seen the game on @ZeroPage Homebrew, you should know it can be quite chatty. There have been a few other changes, most of which you should not be able to notice, but that will include some late-game edits for playability (leveling) as I mentioned before.
  10. I've discovered a bug — which has been patched in the latest daily builds on the web site. However, the work-around is very simple: If you're using the latest packaged beta build of the game, please do not try to register a character with a name containing the digit zero. There was a bug in which the code would not allow you to resume from a slot whose player name contained a zero. There are a few other changes in the daily builds since the previous release, mostly to do with near-end-of-game leveling.
  11. We're on board (Zephyr and I) — we actually had that on our "list of places to check out in Portland" already. Side note: Aside from a Dave's and Buster's, which perhaps doesn't count, I've never lived anywhere that had an actual videogame arcade so this will be a first for me!
  12. Just to "brag" a little, Zephyr (who does not have a forum account) seems to have just set the reigning high score tonight with 40,449 points, 17/30 Grizzards, and only 4 hours (game clock time). That's on the “first quest” (before New Game Plus kicks in), standard difficulty (“B”).
  13. They're just text files, you can create them in any plain text editor or IDE. (Atari Dev Studio, Emacs, Visual Studio Code, Gvim, Notepad++, whatever.)
  14. Most IDEs have a mode for assembly (not necessarily 6502, but that doesn't matter too much) and a way to plug in the name of the assembler you want to use. Looks like the first error is the one you should address first, Warning: Unable to open 'vcs.h' … you probably want to get those files (vcs.h, macro.h) and put them somewhere where dasm can find them. I don't use dasm myself, but I suspect you need to pass like -I /path/to/includes (usually -I which is capital i but I don't know for sure). I'm sure the dasm manual explains it in some detail.
  15. My understanding is that the original Atari devs in 1976-77 were using a timesharing minicomputer that they had terminal access into. So, if you really want the "Back In The Day" experience, your best bet would be to boot a teletype (or at least a terminal emulator) on a Unix or Linux system and get cracking with ed … but that would be an awful experience. (ed is designed for teletypes, not screens, so it works line-by-line. DOS's EDLIN.COM is similar, if you've had the misfortune of encountering it.) *Edit* ~ see eg this 2016 post for more details: If you fast-forward to the early 80s, you could instead fire up an Apple ][ or Commodore 64 with a 6502-series assembler and use that; e.g. Turbo Assembler on the C=64 could absolutely build Atari 2600 games, and it at least has a nice full-screen text editor. … but I for one don't see the benefit of that; you may as well enjoy the benefits of a modern editor or IDE. As for cross-development, 8G is a huge amount of space. dasm, which many folks on AtariAge use, weighs in at about 250kiB on disk, and even 64tass that I use (which is, yes, the descendant of the venerable Turbo Assembler on the Commodore 64) is only around 2MiB. Add a reasonable text editor or IDE, and you're probably up to 150MiB, maybe 200MiB disk space, and can absolutely work in less than 1GiB of RAM if you're not doing much else at the time. I'll leave it to others to point out various books, but the pinned thread at the top of this forum has a lot of resources listed.
  16. Ref: "some assemblers" 64tass (Turbo Assembler) you'd do basically the same thing as what you wrote: PhysicalAddress: .logical $02 DestinationAddress: Loop: jmp Loop .here where PhysicalAddress might be $f500 and DestinationAddress would be $0002, and jmp Loop would be jmp $0002
  17. Looks like the RetroN doesn't expose its save function, and it only saves what's currently in RAM, so you can't fit a whole Grizzards game in there (it's bigger than RAM) … but thanks to @Muddyfunster for testing, if you upload the a26 file with the matching pro file it should work as it you had a SaveKey.
  18. This is a bit convoluted, but it's been helpful so far. TL;DR: You can set up A7800 and some shell scripting / Makefile recipes to perform unit tests on your 6502 code, in context of the virtual machine that A7800 provides. I've set up a conditional build in which I include a power-on self-test file (POST.s) that unit-tests some "suspicious" functions that I'm working-on. In order to streamline running those unit tests, I now have the following in my Makefile: A7800=a7800 a7800dev -debug -debugger_font 'Source Code Pro' test: Dist/ROM.POST.NTSC.a78 @-rm -f /tmp/break.dump $(A7800) -cart $$(pwd)/$< -debugscript $$(pwd)/Tools/CrashOnBreak.mame @if [ -f /tmp/break.dump ]; then \ echo 'POST failure:' >&2 ; \ STACK=$$(od -tx2 -Ax1 /tmp/break.dump | cut -d\ -f2) ; \ fgrep $$(echo $$STACK | \ perl -ne 'chomp; printf "%x" => (oct("0x$$_") - 2)' ) \ Object/ROM.POST.NTSC.list.txt \ < /dev/null >&2 2> /dev/null || \ echo 'Not finding label '$$STACK; \ else \ echo 'POST seems to have passed'; \ fi This in turn relies upon this Tools/CrashOnBreak.mame script: bpset cccc,,{save /tmp/break.dump,sp+2,2;quit} bpset dddd,,{quit} go The exact addresses for $cccc and $dddd are "exit" points in the POST routine for failure or success, respectively. In fact, the address for $cccc I'm using is the BRK handler routine for the normal case, which displays a crash screen, so I can also run A7800 interactively and see the address of the failing test, whereas $dddd is just a success-hang point. The od output will usually have the address + 2 of the brk from failing a certain test in the first two bytes, in the usual low-byte, high-byte order, so by having each unit test fail with its own unique brk instruction, I can pretty easily look up the address in the assembler's listing file, and resolve it back to a nice label. In one case, the output was: Debug Build: Disabling input grab for -debug OPTIONAL 7800.u7 NOT FOUND (tried in a7800dev a7800 a7800dev) WARNING: the machine might not run correctly. This cart supports external NVRAM using SaveKey. This is not supported in MAME currently. Exited via the debugger POST failure: .8a75 ca75 ErrorRemovingStamp: .8a75 ca75 00 brk It's not going to get perfect test coverage, but it's providing a safety net of some regression tests for various cases that is turning out to be quite helpful to me.
  19. The disassembly is where someone takes the binary (ROM image) and reverses it back to assembly-language code, usually commenting and adding labels to make it human-legible. DASM is one assembler program that's popular with many AtariAge users. For instance, if I wrote: UpdateDisplayedArrows: lda Arrows cmp ArrowsDisplayed beq DoneArrows bge IncreaseArrowsDisplayed DecreaseArrowsDisplayed: dec ArrowsDisplayed jmp ChangedArrows IncreaseArrowsDisplayed: inc ArrowsDisplayed ;; fall through ChangedArrows: I'm going to compile it with my assembler and produce a binary. My listing file will look something like: .94dc d4dc UpdateDisplayedArrows: .94dc d4dc ad 36 21 lda Arrows .94df d4df cd 37 21 cmp ArrowsDisplayed .94e2 d4e2 f0 19 beq DoneArrows .94e4 d4e4 b0 06 bge IncreaseArrowsDisplayed .94e6 d4e6 DecreaseArrowsDisplayed: .94e6 d4e6 ce 37 21 dec ArrowsDisplayed .94e9 d4e9 4c ef d4 jmp ChangedArrows .94ec d4ec IncreaseArrowsDisplayed: .94ec d4ec ee 37 21 inc ArrowsDisplayed ;; fall through .94ef d4ef ChangedArrows: When I put that together into a ROM file, though, it'll just be the binary data: ad 36 21 cd 37 21 f0 19 b0 06 ce 37 21 4c ef d4 ee 37 21 A disassembler program, like the one is A7800, can reverse that to figure out the opcodes, but not what they “mean” precisely: Now, someone could make a disassembly by taking the raw output from a disassembler, like that, and adding their own labels, once they determine what the various addresses are used for. So a disassembly listing for the same code might read lda ARROWCNT cmp ARROWCPY beq Ld4ef bcs Ld4ec dec ARROWCPY jmp Ld4ef Ld4ec inc ARROWCPY Ld4ef The person doing the disassembly might come up with different names for things (like ARROWCPY for what I had called DisplayedArrows) or not at all (the Ld4ec is just a junk label created by the disassembler based on the address, and doesn't actually provide any information about what's happening at that address), and it can take quite a bit of work to discover what the various addresses are used for — RAM addresses used as variables, ROM code labels, ROM data tables, and so forth. But it's far easier to refer to a disassembly that someone's taken the time to annotate than the raw disassembly provided by the debugger. Naturally, the original source code is the preferred form, but if you don't have that available, a good disassembly is nearly as good. What others were suggesting was: it would be easier to make small alterations if you already have the disassembly written for you. For example, if you wanted to change how many arrows you started the game with, you could look at a disassembly and see somewhere something like ARROWCNT = $2136 ; How many arrows you actually have You could then go into the debugger in A7800 and do something like wpset 2136,1,w … which will set a watch point looking at $2136, for 1 byte only, for writes. When you start a new game, perhaps you get something like this You see the last line in the debugger window says that the code at (PC=) $82b3 wrote the value (data=) $64 (decimal 100) to $2136 (Arrows/ARROWCNT). If you know that you start the game with 100 arrows, then you've found the place you want to alter. Looking back a little … … we see that the A register was loaded with $64 on the line above, so you can just alter the #$64 in that line and probably starting a new game would give you a different number of arrows. In a similar way, as @Atarius Maximus was saying, if you look at the MARIA palette registers in the debugger: … you might be wanting to change something that is currently color $88 (light blue) to another color, say $0f (white) perhaps. From this debugger window, I can see that is in palette register P2C2, which is written at $2A. So you could maybe trap writes to $2a, looking for a write of $88. Hitting F5 after false positives, I run into: In this case, again, the color happens to be a simple hard-coded value from lda #$88, so you can probably edit the ROM to change that value as well. If it were being calculated, or pulled from a data table, it would be more complicated to change it. At that point, you'd need to (going back to the arrows example) alter the original source code corresponding to lda #$64 and recompile it, or alter a disassembly listing in the same way, and recompile it, or open a hex editor, find correct offset in the ROM for the a9 64 you're after (within the sequence 8d 32 21 a9 64 8c 36 21) and save it In the hex editor case, since the ROM can consist of multiple memory banks and they wont start at 0000, you'll find that the offset probably will end in b6 like 82b6 but it will probably not be $82b6, it could e.g. be $0236 offset or something. (It'll also be easier to do this if you strip off any .a78 header with 7800header -b romfile.a78 and use the .bin it produces for hex editing, but then you'll also have to add the header back on later. Finally, after editing a ROM, if you want to be able to play it on real hardware, you have to re-sign it with your changes using the 7800sign utility to get it to run.
  20. I'm not sure I follow the question 100%, but the 7800 does not have hardware pixel-based “sprites” per se, and MARIA doesn't provide any collision-detection assistance. So … you would have to implement your own, and you could do so in whatever way is convenient to you.
  21. Note, after typing all the below, I realized it is much more relevant to bigger (16kiB+) ROMs and maybe not so much for 8k projects, but just to show a little different way of looking at things. Consider this (by Atari 2600 standards) the “programming In The Large” version … Myself, I try to map a very small section of code at the tail end of ROM (keeping in mind that you might start up in any bank, so the IRQ/NMI/RES vectors are part of this file) that I think of like "wired memory" in Unix terms (un-swappable). In each bank, I include the same file (EndBank.s) that starts at the same fixed location in each bank. However, it can be compiled slightly differently in each bank. So eg. ;;; Perform a far call to a memory bank with a specific local ;;; service routine to perform; eg, this is how we handle sounds, ;;; text displays, and the common map header and footer code; ;;; anything that does not need data from the local ROM bank. FarCall: lda #BANK pha sta BankSwitch0, x jsr DoLocal ;; fall through after rts ;;; Return from a FarCall. FarReturn: pla tax sta BankSwitch0, x rts That label DoLocal has a different definition in each ROM bank. So e.g. in bank 0 it might be $f2b4 and in bank 4 it might be $f090. In each bank's source I just define a DoLocal label wherever I like, and include EndBank.s at the tail. In Grizzards I usually use the y register to select a service routine that the destination bank provides. EG: ldy # ServiceDoSomething ldx # RelevantBankNumber jsr FarCall ;; and then somewhere in that other bank DoLocal: cpy # ServiceDoSomething beq DoSomething cpy # ServiceDoSomethingElse beq DoSomethingElse brk ; crash if Y is not on our list. In addition there are a couple of hard routine pointers there, that are used for jumping to a specific bank, like the cold start (RES) vector and the break (IRQ) vector point to, or like: GoCombat: ldx #$ff ; smash the stack txs sta BankSwitch0 + CombatBank jmp DoLocal I've arranged certain types of data into certain banks to avoid duplication as much as possible; e.g. the font for text is only present in a couple of banks, so anything that displays text has to go through one of them; so eg. my Combat screen is made up of calls to any number of different ROM banks, for showing the name of monsters, displaying the group of monsters opposing you, showing the name of the Move you're selecting to use next, &c. Or: for the various banks that handle drawing the Map screens and such, the map data is in each bank, but a lot of the VBlank activity is common to all of them (and does not actually refer to the map data itself), eg. drawing the score at the top of the screen, scanning the joystick & switches, &c. So there is a call from the “map kernel” to ldy #ServiceTopOfScreen ldx #MapServicesBank jsr FarCall The full source for my “wired memory” is at https://github.com/brpocock/grizzards/blob/main/Source/Common/EndBank.s and a relatively typical Bank file is eg. https://github.com/brpocock/grizzards/blob/main/Source/Banks/Bank02/Bank02.s which, as you can see, is largely just the DoLocal dispatch code followed by .includes for the various subroutines and data files it uses.
  22. The Javatari script calls to https://webmsx.herokuapp.com/proxy-remote-download?url=https://atariage.com/forums/applications/core/interface/file/attachment.php?id=611057 (for example) to fetch a binary. This in turn is being actively blocked by CloudFront. From the console I see this being returned by Heroku: 403 ERROR The request could not be satisfied. Request blocked. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner. If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation. Generated by cloudfront (CloudFront) Request ID: WC5TRK7lMA85JauG5D9K4FvtTsQ5PnjOi7PeI-12g_UYPnUatdMumA==
  23. One gimmick is to break up how you gather the seed value a bit more than just addition. Like, looking at it in 2D, you have y + x | 00 | 01 | 02 | 03 00 | 00 | 01 | 02 | 03 01 | 01 | 02 | 03 | 04 02 | 02 | 03 | 04 | 05 03 | 03 | 04 | 05 | 06 which is a pretty obvious (diagonal) pattern, but if you do something with a little bit shifting and such, you can get more complexity In the below table, I tried doing some bit shifts and an xor (eor). Note that the magic of $5a and $a5 (which is not much magic) is that they're %01011010 and %10100101, and $55 and $aa would work equally well, but you can try whatever magic constants you like of course. (Tables truncated for example purposes; all numbers are hex.) seed = x + y + $5a + (z ^ $a5) + ( (x << 4) | (y << 2) ) yields: z = 00 y/x | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 00 | FF | 10 | 21 | 32 | 43 | 54 | 65 | 76 01 | 04 | 15 | 26 | 37 | 48 | 59 | 6A | 7B 02 | 09 | 1A | 2B | 3C | 4D | 5E | 6F | 80 03 | 0E | 1F | 30 | 41 | 52 | 63 | 74 | 85 04 | 13 | 14 | 35 | 36 | 57 | 58 | 79 | 7A 05 | 18 | 19 | 3A | 3B | 5C | 5D | 7E | 7F 06 | 1D | 1E | 3F | 40 | 61 | 62 | 83 | 84 07 | 22 | 23 | 44 | 45 | 66 | 67 | 88 | 89 z = 01 y/x | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 00 | FE | 0F | 20 | 31 | 42 | 53 | 64 | 75 01 | 03 | 14 | 25 | 36 | 47 | 58 | 69 | 7A 02 | 08 | 19 | 2A | 3B | 4C | 5D | 6E | 7F 03 | 0D | 1E | 2F | 40 | 51 | 62 | 73 | 84 04 | 12 | 13 | 34 | 35 | 56 | 57 | 78 | 79 05 | 17 | 18 | 39 | 3A | 5B | 5C | 7D | 7E 06 | 1C | 1D | 3E | 3F | 60 | 61 | 82 | 83 07 | 21 | 22 | 43 | 44 | 65 | 66 | 87 | 88 z = 02 y/x | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 00 | 01 | 12 | 23 | 34 | 45 | 56 | 67 | 78 01 | 06 | 17 | 28 | 39 | 4A | 5B | 6C | 7D 02 | 0B | 1C | 2D | 3E | 4F | 60 | 71 | 82 03 | 10 | 21 | 32 | 43 | 54 | 65 | 76 | 87 04 | 15 | 16 | 37 | 38 | 59 | 5A | 7B | 7C 05 | 1A | 1B | 3C | 3D | 5E | 5F | 80 | 81 06 | 1F | 20 | 41 | 42 | 63 | 64 | 85 | 86 07 | 24 | 25 | 46 | 47 | 68 | 69 | 8A | 8B z = 03 y/x | 00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 00 | 00 | 11 | 22 | 33 | 44 | 55 | 66 | 77 01 | 05 | 16 | 27 | 38 | 49 | 5A | 6B | 7C 02 | 0A | 1B | 2C | 3D | 4E | 5F | 70 | 81 03 | 0F | 20 | 31 | 42 | 53 | 64 | 75 | 86 04 | 14 | 15 | 36 | 37 | 58 | 59 | 7A | 7B 05 | 19 | 1A | 3B | 3C | 5D | 5E | 7F | 80 06 | 1E | 1F | 40 | 41 | 62 | 63 | 84 | 85 07 | 23 | 24 | 45 | 46 | 67 | 68 | 89 | 8A There are definitely some repeated room seeds in there, but they don't seem to be any (humanly) identifiable pattern like the diagonals that you get from simple addition. I don't really know bB but in assembly that's lda WorldX asl a asl a asl a asl a sta Temp lda WorldY asl a asl a ora Temp clc adc WorldX clc adc WorldY clc adc #$5a sta Temp lda WorldZ eor #$a5 clc adc Temp sta Seed Which back-of-envelope arithmetic puts at around 60 cycles, more or less. On checking, if each of x, y, and z vary from $00 to $ff, then each seed value (also from $00 to $ff) will occur precisely $10000 (65,536) times, so the distribution is pretty even.
×
×
  • Create New...