Jump to content
IGNORED

The Upward Spiral - modularity and paranoia


RSS Bot

Recommended Posts

In redoing some "far call" text subroutines I suddenly realized I was waay over-engineering things. (C=128 users will recall how bad the KERNAL ROM far call routine was? Yeah. That bad.)

 

So, I needed to crib together my module organization anyways, so here it is for posterity.

 

Most of the modules are major game modes/screens. They're modal, and basically "jump/goto" one another, so I don't need "subroutine" semantics. Their communications are entirely through the player's persistent data (i.e. "game data" v. "temp data") or the "linkage area," which is a static area (currently 8 bytes) which follows the player data in every module.

 

Each module arranges the rest of ZP above a "certain" mark to its own liking, so we zero it on bank switch.

 

Shared ROM

 

The bank-switching code is very stupid and lives near the top of every ROM (duplicated). It basically just switches to bank (.x) and then jumps to that bank's "entry" label. (Currently those are all at $f000, but that's not necessary since the bankswitch is recompiled for each bank.)

 

Some modules share memory banks. In that case, I use a flag in .y to indicate which module routine I want to invoke, and the "entry" routine dispatches accordingly.

 

The only currently-used "far subroutines" are for text decoding, and the Ursa interpreter, and they're special-cased with entry vectors in the shared ROM area.

 

Finally, wedged in before the main bank-switching code is the RES vector routine, which forces a bankswitch to bank 0, module 0 (CLEAN_START and attraction)

 

Major Modules

 

The major modules of the program are:

  • The Tile Drawing aka Transit, Travel, Map kernel
  • The Combat kernel
  • Attraction/Winner mode
  • Conversation mode
  • The Stats displays
  • Save/Restore game routines

Tile Drawing basically takes "player_map" and "tile_xy" values to decide (a) whether the data for "player_map" is in the current bank (if not, guess whether to bankswitch "up" or "down" and try again); and (b) where to place the player. It then runs full-tilt, calling Ursa ocassionally to handle script events. SELECT jumps to Stats, RESET jumps to Save Game.

 

Combat has a fairly involved set of timers and "turn-taking" - basically each of the player and each monster get a turn broken down into an idle period (the monster is "thinking") or menu selections; then, the attack animation; then, the results of the attack. Like the Tile kernel it just needs to know how many monsters and what type, and then "searches" for the bank capable of handling that type of monster. The background artwork is tied to "player_map."

 

Attraction mode is a series of "mini kernels" for doing various bits of the animation. If someone wins the game there will be some animations there, as well.

 

Conversation mode is basically just a scrolling text display or an interactive menu display. They're mostly the same, except when they're not. Because of ROM limits there may be multiple conversation banks to handle the quantity of text.

 

Stats display is broken down into several "subscreens." Interestingly, we can call Stats from any bank, so it tries to work from within a limited size stack space and some linkage area temporary variables, so as to not corrupt the "caller's" data.

 

The Save/Restore routines are bit more -- strange. Some of it triggers Ursa menus (Conversation views), but the main screens are:

  • View Code ("Save" Code)
  • Enter Code ("Load" Code)
  • Enter filename for new file (nickname for new player)
  • Choose filename from list of those on the MemCard

Rule #1. You can't save using a code unless you're on the map. (Too much is happening to save the state using a code.)

Rule #2. You need a filename to save to MemCard (or AVox). Since this would smash the combat variables, you can't save to a MemCard during combat unless you already have done so. Let's presume also from conversation, then.

 

OK, weird enough for ya?

 

Possible situations:

  • Player has no MemCard. Code save is accessed from RESET and from Stats.
  • Player has a MemCard, connected when in Attraction. s/he starts a game, and is prompted for a nickname/filename. The MemCard block is allocated. Save can happen (almost) anywhere now.
  • Player has a MemCard, but not connected until s/he starts playing. Since we didn't see it up front, we don't let him/her try to save until on the map. Then, s/he gets prompted whether to create a file and/or view the code.
  • Played had a MemCard, but removed it. We just prompt him/her to re-insert it. If s/he refuses/cancels, we assume it's gone and go back to the "no MemCard available" state. If it's inserted, we look for the "splat" (open-for-writing) file on the card and proceed just as if nothing had happened.
  • Player removes the MemCard during play and inserts another. Now, this is a problem, because the player's name data was stored on the MemCard in a "directory" area! So, we treat this like a "lost" MemCard, above.

Note that the "directory" marks the active file and tracks filenames. In CBM DOS, we called "open" files "splat" files, because the DOS marked them with a * beside their names. (And, if you saw a splat file in BASIC, it was a pretty sure bet that something had crashed while writing the file, unless some machine language "wedge" was writing to it right as you loaded the directory file.) If we see a MemCard from the main menu with splay files, we'll need to validate their checksum(s), and if they fail, delete them :(

 

Oh, right... basic checksums. Something really basic, maybe CRC or similar.

 

Incidentally, to keep people relatively honest, there'll be some checksum bits in the screen codes, too.

 

http://www.atariage.com/forums/index.php?a...&showentry=1567

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...