RPG Memory Organisation

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
Posts: 42
Joined: Sun Jun 30, 2013 7:59 am

RPG Memory Organisation

Post by CrowleyBluegrass » Sat Jan 18, 2020 9:08 am

Hi all :)

I'm thinking about very basic memory organisation for an rpg and was hoping to get some advice/tips. If I have enemy stats defined as a struct-of-arrays in rom like:

Code: Select all

enemy_hps = .db 01 02 03 04 ...
enemy_strs = .db 01 02 03 04 ...
the idea is that in battle, once the enemy index is known, a set of fixed zp locations are used (copied to) to store the current enemy info for more optimal access:

Code: Select all

enum $0000
  current_enemy .dsb 4
roughly the same would be done for the player, except copying for higher ram to zp perhaps rather than rom. Some things that have come to mind are:
1) As per-enemy information increases (steal list, elemental resistance, flee rate...) the number of fixed zp locations per-battle increases. I know speed vs space is the classic trade-off of CS, but I figured there may be alternatives.
2) For ensuring healing doesn't exceed max hp (and similarly for variable+stackable (de)buffs to stats) you seemingly need - not only the constant values mentioned above for reference in zp - but also *copies* you can modify too! That would mean duplicates of health, strength and other stats that can change during battle. Assuming you don't just have constant, non-stackable debuffs via a simple "is_silenced" sort of flag. From what I can tell from (https://www.nicholasmikstas.com/dragon-warrior-defines) this is what DW1 does, keeps copies of modifiable stats and has a byte that stores current statuses.

This is my first time doing any sort of memory organisation/planning, so please forgive any noobish errors or bad explanations. For anyone who has worked on any rpgs (or has reverse-engineered them) I'd be most grateful to know of any information you can offer in general regarding implementing this sort of system.


P.S I'm actually attempting to use a software stack whenever it seems appropriate (aka anything using temporary values that isn't too speed-critical) and I must say (for worse, I'm sure many are going to opine) it feels much comfier than worrying about manually managing shared-zp space all the time. Here, it didn't really seem ideal due to the values being persistent and also the number of them. You could put pointers to the zp copies on the stack but that just seems like dancing around the problem and using indirectly needlessly. However, if you'd personally still use a stack for handling these battle values, I'd love to hear how.

Posts: 1070
Joined: Mon Feb 07, 2011 12:46 pm

Re: RPG Memory Organisation

Post by zzo38 » Mon Jan 20, 2020 12:11 am

I am not so sure that you should put everything in the zero page, although clearly some things should be put. Also it depend what mapper you are using, how the bank switching works (if you are using such a mapper at all), since it might be sufficiently efficient depending on the case. How many times does the data need to be accessed in one frame? Are you going to heal more than once per frame? If not them you may not need a duplicate of the value. You can also store stuff in the RAM other than zero page. For flags, note that you can store multiple flags in one byte, and that in 6502, the BIT instruction can be used to read bit7 and bit6 together, which may improve speed. Your memory organization in ROM seems like is good though; it is best to store each value in a separate table, rather than all next to each other for one record (although depending on the bank switching, as I mentioned above, there might be a reason to do it differently). If you have a assembler with macros that can be used to automatically fill in (this is what I do, including for jump tables; on Knuth's MIX, this is effectively a COME FROM), then you might do so. Presumably you should know how many characters there are in one battle, and how many stats there are, and which ones should need to be in RAM, and which ones should be fast so should be in zero page. I would not use a stack to handle the battle values though, at least in my opinion.

Posts: 861
Joined: Tue Feb 07, 2017 2:03 am

Re: RPG Memory Organisation

Post by Oziphantom » Mon Jan 20, 2020 6:33 am

define RPG, Zelda or FF?

Honestly if its FF oh dear a whole extra 30 clocks is nothing to worry about. Store inventory RAM, but putting the stats of the monsters you are currently fighting into ZP makes sense. If you spend 1/20th or 99% of a black frame doing the copy routine, it is still 1 frame, and even if you have 1 or 5 the player won't care.

User avatar
Posts: 700
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA

Re: RPG Memory Organisation

Post by gauauu » Mon Jan 20, 2020 11:40 am

Oziphantom wrote:
Mon Jan 20, 2020 6:33 am
define RPG, Zelda or FF?

If you spend 1/20th or 99% of a black frame doing the copy routine, it is still 1 frame, and even if you have 1 or 5 the player won't care.
This is right on. You can get TONS done in a few frames, and a few frames is barely noticeable in a turn-based non-real-time game.

Posts: 1492
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: RPG Memory Organisation

Post by Pokun » Mon Jan 20, 2020 3:57 pm

Yeah as everyone says, for a traditional turn-based RPG the main problem is space (both ROM and RAM), not time (speed). FF1 do manages to have really slow battles for some reason though. I guess it was just Nasir being a newbie programmer together with short deadlines. There are many other NES RPGs with faster battles.
However as long as you have room for everything, fixed RAM locations is probably easiest. Unless you are going for passwords, you probably have at least 8 kB extra RAM on cartridge, part of that you can use as extra work RAM, so I don't think you will run out of RAM very soon (unless your save files are very large).

Would zero page really make that much of a difference? On the other hand you probably don't have that much timing critical things that must be in zero page so you might as well put them there to minimize possible delays in very large or very common calculations.

I'd have all changeable stats and state/buff/debuff flags in RAM for all characters in a battle, including copies of all modifiable stats. But I guess you could also have buffs being based on a set formula so it's enough to have the buff state flag and then recalculate the stats each time you need them instead of having a copy of all modified stats (DW1 calculates all stats from just your Hero's experience points and name to make save files smaller due to its password-based design, although that is just for saving). But in that case you must keep count if buffs are stackable. It's probably easier to have a copy of all modifiable stats. For PCs I don't think you need an extra set of stats just for battle though. You can treat field mode and battle mode the same way, you might have things like poison marshes that can hurt you outside of battle as well anyway, so you could keep them always in ZP (or wherever you keep them).

IIRC, DW1 has just about 4 stats (HP, MP, strength and agility) that are relevant in battle (and not derived), only 2 or 3 states and only 2 resistances (magic/breath resistance and Dragonking breath resistance) plus a resistance for all the states for enemies only (Hero's state resistance is fixed) which are constant and can be looked up from a table in ROM. I don't think DW1 has any stackable buffs and debuffs, or does it? DW2 do though.

Also I'm not sure how you use a stack? A stack is good for things like menus with many sub-menus, so you can backtrack out of them one by one by pressing B (which the DW games and many other games of the era seldom does).

Posts: 22017
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Re: RPG Memory Organisation

Post by tepples » Mon Jan 20, 2020 6:18 pm

Pokun wrote:
Mon Jan 20, 2020 3:57 pm
Unless you are going for passwords, you probably have at least 8 kB extra RAM on cartridge, part of that you can use as extra work RAM
If you're going for self-flashability, as is possible with mapper 30, you can avoid passwords by writing to a log-structured file system in NOR flash memory on the cartridge. But it's not very useful as extra work RAM because of slow write speed and flash wear.

Post Reply