Jump to content

Bruce-Robert Pocock

+AtariAge Subscriber
  • Posts

    237
  • Joined

  • Last visited

Everything posted by Bruce-Robert Pocock

  1. Latest progress has been impeded by a crasher bug that I haven't hunted down — something something switch to the wrong memory bank executing graphics as code something something. Also, it's just been a busy week in general and I haven't gotten much time to work on it. In the same branch as the crasher bug, however, this week… tidied up some assembly code in general (names, whitespace, branch prediction) kinda fixed some bad color reference issues in the Animation Editor tool for graphics with variable colors (e.g. the player, & generic humans) first draft of save/load serialization definition. (more below) more informative headers in A78 file (includes build date, NTSC/PAL "N" or "P" flag) added a cheesy make remotely target to ssh in to my fast machine from my crappy laptop with great battery life so I can use it for development on the LAN Skyline Tool now accepts the game title and other metadata from a Project.json file, which is another step toward making it a stand-alone utility program. (This is what does all the neat tricks with PNG, MIDI, Fountain, & Tiled files.) Thinking about save game records The serialization routines are … troublesome … for passwords. Despite using some very light compression (RLE on all zeroes or all $ff-es), once converted into a 32-character-alphabet password, I'm seeing a worst-case-possible output of a 136-character password. That's almost enough for me to throw out the password entry system altogether, but I'm looking at the 2600+ over there with its physical inability to access a SaveKey and wondering if it's preferable to key in a 136-character password versus having to play a 20(?) hour game without turning off the power. I expect that the worst-case performance is likely far worse than it would ever be in reality, and I also could probably cut it down by about 20? characters if I did not save the player's name, gender, &c, but made you re-enter those every time. I'm not sure than a worst-case of 120-ish characters is much better than 140-ish, but it's something. The serialized data, in 8-bit form (versus 5-bit form for 32-character text entry) runs about 90 bytes or so — which, in SaveKey block terms, means 2 blocks (64 bytes each) per save record. We're thinking about having 3 save "slots" available for SaveKey/AtariVox. You might notice that that's a lot smaller than the save game records for Grizzards, but in this case, we're not trying to keep track of 30 different sets of stats! I'm not requesting allocations yet, there could be some unforeseen reason that it would fit in 1 block or balloon out to 3.
  2. Actually, now that I see your criteria, our mini bosses are mostly not story-blocking (criterion "C") but the four final bosses and a few mini bosses are. (the Grue in the caves by Mt Peshon, for example.) They're all life-or-death though (RUN AWAY is blocked) and are tougher than the non-boss version of the same creature (if there is such a thing). So yeah 😅 Thanks for adding us!
  3. You could try e.g. these old binaries, works for me but I doubt my configurations are typical.https://forums.atariage.com/topic/322957-grizzards-—-turn-based-rpg-completed/page/3/#comment-5019984
  4. Yesterday's progress: Uniform naming of scripting variables for my convenience Tweaking background tile animation frame rate Skeletal support for music, sound effects, and speech Rough implementation of speech (AtariVox) based upon Grizzards code. (Also, discovered a few bytes of dead code in the Grizzards implementation, but harmless.) Set construction (map editing in Tiled, tileset editing in Gimp) Initial stub support for weather system Yet more vocabulary added to SpeakJet dictionary Convenience feature for Skyline Tool to reload a map when a named nav point (from a script) can't be found (so you can edit the map and resume the build process) Increased the stack for scripts at the expense of the main stack. (Stack sizes are now: main $40, script $40, NMI $20, and Stagehand $20.) Initial support for animating full-screen graphics (e.g. title card) "Frame earthquake" cured (vertical jitter) Removed some unused consts and vars More reasonable timeouts for prelude screens before title Correct loop for setting palettes for full-screen graphics (ensure that all palette entries are initialized) Tweak to 7800GD "live push" support. (Ensure that the newly-pushed image will detect that it needs to reload) Tidied up arrangement of fixed ROM bank Sketched out some (more) ideas for the manual Re-arrange text on title card to support (eventual) main startup menu Remove duplicated efforts to compose characters (i.e. people and such) from the main loop unnecessarily Don't count down alarm timers when the game is paused Miscellaneous small tweaks
  5. Yesterday's progress: Substantially improved how smoothly background tile animations can occur — which reveals that a number of things were being asked to animate at silly-fast speeds, and only slowed down to reasonable frame rates because the animation process was not running fast enough to meet the demands. (Still manually entering the animation sequence data for background tiles; I need to work on accepting the speeds specified in Tiled.) Began work on animation and "physics" for particles Improved coöperative multithreading between scripts and main game thread so that particle updates aren't frozen while scripts run (it would look super dumb) Improved auto-generated labels in compiled scripts, rather than just garbage numbers, they now contain descriptive names, and dialogue/speech symbols now contain the first few words of the dialogue text to make the source code easier to read. The garbage at the end is a hash to ensure distinctive uniqueness, so e.g. two utterances with the same prelude don't get confused for one another, but two identical utterances can be merged into one if they occur in the same ROM bank. Ensured that a countdown timer used to wait for a moment in scripts is clamped to zero, so it won't ever wrap around and make you wait another 255 frames before it realizes it's done (race condition) Improved the Interworldly Adventuring, LLC logo screen graphics Better handling of different classes of boats/ships and re-organized how their graphics are arranged in ROM. Palette tweaks to ensure that characters stand out clearly against the background in some scenes Based on some info by @RevEng on his web site, taking advantage of the unreliability of accesses to the RIOT timer in order to increase the entropy of the pseudo-random number generator. Changed the thread labels around in the crash screen, so they now identify as M/ain, S/cript, Stage/H/and, and N/MI
  6. It's a bit difficult to "catch it" doing anything interesting, but you can get a little idea of how it runs from this, perhaps. Screencast from 2024-04-08 18-30-13.webm
  7. @Karl G "Thread" is being used a bit vaingloriously, but the intent is pretty much the same as one might expect from 1980s multiprogramming. There are 4 threads of control; at different times they either voluntarily hand off control between one another, or are pre-empted by NMI (DLI). Each has its own stack region (all within the $c0 bytes of stack available on page 1) and during context switches we swap the S pointer. The four threads are the main thread, the NMI thread, which takes control during display list interrupts and may pass it off elsewhere, the Stagehand thread, which does not access any bankable ROM but does read the controls, update sounds, and cycle background tile animations; and the Fountain thread, which runs compiled (from Fountain-formatted source files) scripts for NPC interactions, cut scenes, &c. For example, a cut scene script could wait for a certain number of seconds to elapse while simply spinning in place reading the clock value, and the NMI interrupts would be simultaneously driving the Stagehand thread, which updates the clock. Granted, this is basically just an elaboration on the usual 6502 interrupt service routine model, but it comes into play particularly because Sally and Maria bank switch at the same time. Since each screen is made up of graphics that may be in one of several ROM banks, we have to stay pinned in the appropriate bank while the display is being rendered. Stagehand is able to run and do some useful things in that context, but the main thread may want to do bank switching, and a running cut scene will be found in an arbitrary "data" ROM bank itself, so those things cannot happen while we're "locked in" for graphics, so they must compete for time slices during VBLANK. By keeping separate stacks for each one, it's a lot easier to reason about what's happening in that block of code. As an additional precaution, Stagehand is compiled separately with its own variables in RAM, so its symbols &c aren't accessible (except the communications "mailbox" region) from the main game, and likewise, nothing that the main game is using is accessible to Stagehand, so they are isolated in that way as well. I use a very tiny jump table at the top of Stagehand for its "on boot" and "on frame advance" entry points, and otherwise it is an opaque binary blob to the main game.
  8. As Phantasia creeps towards functionality, I thought maybe I'd start posting some quick blog posts about what progress is being made. If anyone has questions about what something particularly means, feel free to ask, but I may not answer things that would be too spoiler-y in public. This past week: Fixed serious scheduler problems caused by poor background tiles animation performance that actually hurt the frame rate a tonne. Major cleanups around the multi-threading support to ensure steady frame rate under most/all circumstances When a decal leaves the scene heading north, and there are more rows of the map off the top of the screen, sometimes other decals in the top zone would be overwritten with the art pointers of the sprite that had just left momentarily after it passed. Added some spacing above/below the dialogue lines. (Still needs some color fixes, as they're solid "white") corrected X positioning of decals moved some address constants so as to better sync things between banks re-sync DLI with regards to MSTAT so that we don't miss one interrupt and have the screen "permanently" jammed up (e.g. text font where the map tiles belong & vice-versa) correct handling of finding human heads — when putting together NPC's fixed bug: humans' heads face east when walking south Broke up ComposeCharacter into a number of smaller files for manageability; current line counts … ⇒ wc -l Source/Routines/ComposeCharacter.s Source/Routines/ComposeCharacter/*.s 129 Source/Routines/ComposeCharacter.s 145 Source/Routines/ComposeCharacter/ColorizeByte.s 56 Source/Routines/ComposeCharacter/DecalKindSearch.s 83 Source/Routines/ComposeCharacter/DecorateFrame.s 31 Source/Routines/ComposeCharacter/FindAction.s 60 Source/Routines/ComposeCharacter/FindAnimationFrame.s 32 Source/Routines/ComposeCharacter/FindFrameRateScalar.s 101 Source/Routines/ComposeCharacter/FlipBuffer.s 52 Source/Routines/ComposeCharacter/GetFacings.s 43 Source/Routines/ComposeCharacter/PaintVarColors.s 45 Source/Routines/ComposeCharacter/PrepareWorkVars.s 41 Source/Routines/ComposeCharacter/StencilOverUnder.s 48 Source/Routines/ComposeCharacter/UpdateDecalArt.s 866 total Adjusted handling of personal pronouns for the player (gendered words) — so e.g. he/him/his/&c appear with correct lengths and spacing. Peephole optimizations using the "undocumented" lax instruction Early exit could occur when a one-byte "word" was next-to-last and a one-byte "word" ended a paragraph/utterance. Any word starting on the last byte of an utterance would be omitted. This was visible when the player's name (a one-byte variable code representing a word) was followed by ending punctuation (essentially a one-byte "word" also) Fixed alignment of, and spacing around, the dialogue speaker's name First draft of a new scene for the initial demo video sequence Fixed handling of pauses in speech (for SpeakJet): better combining adjacent pauses, and proper elimination of trailing pauses Fixed handling of a final pause before an exclamation mark or question mark, e.g. ...? at the end of a sentence Tonnes of new SpeakJet phonetic spellings added to support the ever-growing vocabulary of the game's dialogue Reading SpeakJet.dic file … Done, 2,402 words Overall, about 78% of the way to the First Light Demo (which is the cut-scenes-only one), with about 30 bugs & enhancements still in the queue for it. Currently: I'm working on the script compiler and getting the engine sufficiently stable to play through the entire demo cut scene sequence properly, and trying not to distract myself with shiny things @Zephyr Salz is working on some more art, and scripts, for the demo sequence
  9. It seems that the last known owners were probably Washington's Mean Hamster, CEO John Swiderski — so licensing would probably mean hunting him down to see who has the current rights to the Exidy catalogue. He's personally written some 5200 homebrews, so it's not unreasonable. ref: https://atariage.com/programmer_page.php?SystemID=5200&ProgrammerID=273 ref: https://www.linkedin.com/in/johnswiderski/details/experience/ Technology-wise, something like that could surely be done, to some degree.
  10. It's trivial to imagine a 256MiB (2¹⁶ × 4kiB) cartridge, although I don't know why you would want to do it. Current 2600 games from AtariAge already break 128kiB. Space constraints don't really apply in the presence of bank switching. Also, nobody's claiming that you need to store entire rooms or screens in ROM at all — generative algorithms and such are very applicable, e.g. games like Rogue or NetHack as well as Pitfall.
  11. What I might do, in your place, would be to create a text file on a modern system, convert it to a SEQ file, and provide a simple BASIC program to read that SEQ file and print it to the display one page at a time … e.g. from https://www.c64-wiki.com/wiki/STATUS 10 REM READ FILE 20 OPEN 1,8,2,"0:TEXT FILE,S,R": REM OPEN FILE FILE 20 FOR S=0 TO 1: REM INFINITE LOOP, WHILE S = 0 30 GET#1,A$: REM READ A BYTE 40 PRINT A$;: REM VIEW THE BYTE ON THE SCREEN 50 S=255 AND ST: REM I NOT EQUAL TO 0 WHEN BIT 6 IS SET (END OF FILE) 60 NEXT S : REM LEAVE IF S > 0 70 CLOSE 1: REM CLOSE FILE 80 IF S AND 64 THEN PRINT "OK" You could augment that with breaking on each screen, &c. Converting via command-line would be something like this: petcat -w2 -o read,prg read-file.bas petcat -w2 -text -o text-file,seq text-file.txt c1541 format "read stuff",r0 d64 read-stuff.d64 8 write read,prg "read file",prg write text-file,seq "text file",seq list
  12. The maximum length of a BASIC command line entered at the prompt is 80 characters (two lines)
  13. I use Gimp. To do double-wide pixels, you have to jump through a couple of steps. Create the image with the pixel resolution correctly set … Then, pick Image / Print Resolution … and unlink the chain link between the X and Y resolution, and set the X resolution to half the Y … Finally, turn off the setting View / Dot for Dot to see the "print" resolution on the screen, and you have double-wide pixels now.
  14. I have an utility to produce the drawing lists and such, although the drawing routines I have are a bit embedded in Phantasia. The way it works: I produce the source art with a 4×16px grid in Gimp, and manually ensure that each of the cells have colors from only one palette. The palettes are encoded in the last row of pixels. The source file is then 160px wide and a multiple of 16px high (plus one for the palette row) This, I export as a flattened PNG (still at 24bpp RGB or RGBA mode) from this, Skyline-Tool writes out a source file that contains: — the closest-match colors in the NTSC and PAL palettes — the zone definitions for each zone, as pointers to the span table with palette, x position, and run-lengths — the labels into the actual span data — and the binary span data, in Maria inverted page-per-line format The playback routines basically just have to populate the DLL with the zone pointers and set the palette. If you're interested I can get you set up, it's not exactly packaged yet (these Phantasia tools are all in flux) — and at some point in future I'll have these things massaged into being more generally-useful.
  15. Honestly, you could certainly have 2 cards per row, and four rows for seven total cards, and only show the top card suit and number, and there you go.
  16. We just were able to update to the 1.1-REV2-Beta firmware and can confirm that it does work with a 7800 controller. (I used a RetroGameBoyz 7800 gamepad.) When we had a Joy2b+ gamepad plugged in, it did not seem to recognize it for input (unable to navigate the menu or anything).
  17. I know this is very late reply, but: The save-to-cartridge circuit on the Grizzards (AtariAge) carts is more than a gimmick, it's actually required for the game to play. I haven't had the time to provide a Stella patch yet to support that circuit (it's similar to, but distinct from, the kind of chip in the SaveKey/AtariVox), so the best possible outcome for the 2600+ would be to possibly start the game, but then crash when the save/load operations are attempted. (I just fired it up in Stella and one tell-tale sign was, enter the Depot on the first screen and press up or down to try to switch your Grizzard companion; it will hang on a blank green screen). Unfortunately, the "dumper" not being able to interact with the cartridge means that it will never work fully with the 2600+, but perhaps a future Stella update can make it usable. (I have not been able to try the firmware updates yet as I don't have access to a Windows machine and the updater seems to fail to work in Wine on Linux so far. Hopefully when "1.1" is out of Beta a better updater will be available.)
  18. I'm not sure what you mean by, "fixed bank" in this context. The usual Atari (brand) -style bankswitching does not have a "fixed" bank. Each bank completely replaces the memory at $f000 (and mirrors) with a different 4kiB bank. To swap between 2 4kiB banks using Atari F8 bankswitching, you strobe the address at $fff8 or $fff9 (thus the name). The usual way to do this is `nop $fff8`, which uses an "undocumented" nop mode; you can instead use `bit` or any other read operation if you want to avoid "undocumented" instructions for some reason, but it's quite reliable on the 6507. (Write operations like `sta` can work too, but they will stroke the register twice, since every write is preceded by a read also.) Basically you're turning the page on the cartridge, but the CPU has no idea, so the Program Counter is just going to roll up to the next address in line after the bank switch. If the bank switch occurs at $f120, and takes a 3 byte instruction, then the next instruction is fetched from $f123 in whatever bank it happens to have switched into. The trickiest thing is to make sure that the next line of code, in that other bank, is where you need it to be. For example: At startup, any bank might be active (depending on a lot of things). Usually, your Cold Start code will be something that triggers a bank switch to a certain bank (e.g. bank 0) and then jumps to your startup sequence. RES vector $fffd => .word ColdStart In Bank 1: ColdStart: nop $fff8 ; switch to bank 0 ;; the next line will never be reached, ;; the CPU will fetch its next instruction from Bank 0 In Bank 0: ColdStart: nop ; skip over the bank switch code in bank 1 nop nop ;; OK, this is where Bank 1 joins us, now do actual start up work sei ; whatever It's important that ColdStartVector must be the same address in each bank. eg, $ff00 or so. What I personally do with these sort of "all or nothing" bank switching schemes is to create a small region in high ROM that is included into each bank (I call mine EndBank.s, e.g. this one in Grizzards) which always starts at a known, fixed address and has functions that are aligned between all the banks. For example, the above ColdStart routine could be at $ff00 in each bank. The $fffd RES vector could point to $ff00. the $fffe BRK vector could also point to something in the shared region, if you use it. You then can add other routines to pass control between one bank and the next. Each of these routines needs to have at least a tiny stub in the common area, so that when the bank switch occurs, the Program Counter is pointing to the next instruction. e.g. again: Suppose your DrawScore routine is in Bank 1. ;;; in Bank 0 GoDrawScore: nop $fff9 ; switch to bank 1 nop ; never reached, padding nop brk ;;; in Bank 1 GoDrawScore: nop ; no need to switch banks, but nop ; we do need to align the next jmp nop ; with the PC when the bank is switched jmp DrawScore Of course there are lots of ways to arrange something like this, but perhaps that helps shed a little light on things.
  19. Perhaps I'm not the intended audience (I have basically no skills at action-type games like this), but it took me 5 or 6 Game Overs before I was able to catch a fly, and wasn't able to get a second after a few attempts. A bit brutally hard for “level 1.” That aside, looks and seems to run quite well.
  20. I've reposted and I'll update the first post as well. Thanks for bringing that to my attention!
  21. Totally un-intentional, I'll have that back up shortly. Looks like I accidentally removed the latest binaries whilst updating the site (which, by the way, is also reachable via https://grizzards.com/ now)
  22. I'm sure @Ryan Witmer will get 'round to speaking for himself but he's been rather present on the Discord, and I don't think I'm talking out of school to say that he's had a few projects in the air and a new day job started recently, but he's doing OK I think.
  23. did you meant 6509 (1 megabyte large memory edition of the 6502) or 6507 (small footprint cost reduced version of the 6502 used in the 2600)?
×
×
  • Create New...