This week is very short to summarize. Other parts of my life have been competing for spare time lately. But in spite of that, I did manage to squeeze in a couple hours of work on Wiz.
I improved integration with debugger integration with Wiz programs. I added some work to improve debug symbol sorting in wiz, so that fully-qualified / global names have precedence over anonymous / compiler-generated names. This means that it will be much easier to search for a particular symbol by name in the debugger and go to it -- and its given name (since Mesen annoyingly only allows one alias for each address of memory) will prefer a deliberate user-chosen name over auto-generated stuff.
I have wanted to also fix Wiz's symbol exporting for the SNES.
The problems are better explained by first explaining what a "debug symbol" is -- basically, a label or identifier that gives a name to an address in memory, constant, or similar thing. This allows you to view these symbolic names rather than hex values inside of a debugger's disassembly viewer. These give names to better indicate where functions, labels, variables, and constant data appear in the program.
The problem is, currently the way addresses are mapped to the symbol file is incorrect. As soon as you have a program outside of bank 0 of ROM, the address calculation is wrong. Or rather, wrong depending on the ROM's map mode that is used.
The SNES is peculiar because the system allows several different ways to access the same memory areas. Firstly, on the CPU-side, the 65816:
- you can access an 8-bit address, which is offset by the direct page register existing somewhere within bank 0 of the memory space.
- you can access a value on the stack.
- you can access a 16-bit absolute address, which has its upper byte of the effective 24-bit determined through the its data bank and program bank registers.
- you can use 24-bit absolute long addressing. It allows you to access the full 24-bit address space of the SNES memory map. This is a similar concept to "far addresses" in 8086 parlance, but bit simpler. For familiarity, Wiz also names this
- you can index an 8-bit direct page address, 16-bit absolute address, or 24-bit absolute address.
- you can use a variable within the direct page or stack as a pointer to a 16-bit or 24-bit address in memory.
- Also, there's two different sizes of stack-based call/return, which use different lengths of addresses:
- 16-bit jumps with JSR (jump to subroutine) and RTS (return from subroutine).
- 24-bit jumps with JSL (jump to subroutine long), and RTL (return from subroutine long).
- and so on (there are more address modes)
At the end, the operands to these addressing modes are decoded at some point into an effective address by the CPU. The way this is done is determined by the memory map of the SNES, which is configurable by the cartridge.
There are LoRom, HiRom and FastRom SNES roms. (Going quick to not miss the Gruedorf post deadline hahah. But edited slightly for clarity and typos.)
Here's a small summary of the "map modes" on the SNES cartridges:
- LoRom lets each bank of memory you access view of ROM in 32K blocks and the 32K of address space contains other stuff (RAM, the hardware registers, etc). These are located at banks
$00 .. $3F/
$80 .. $BF.
- HiRom also lets you view your memory like LoRom (in banks
$00 .. $3F) -- but if you do this, each bank of memory is actually 64K, you only access the upper 32K in each view. But there's another ranges of bank address that let use this as a full contiguous 64K block (in banks
$40 .. $7D, or
$C0 .. $FF). This potentially works better with games that have different data banks and program banks, so the program bank can point to a 64K area, but data bank if, or each can point at a different area.
- HiRom allows more memory to be accessed at once, but requires using banks that contain only ROM space when they are selected, which means you will need to manage your data and program bank registers more, or use 24-bit far addressing more often. HiRom can still be used in LoRom fashion, but will be less efficient when used this way. It steps in 64K increments, but only sees each the upper 32K of a 64K block when viewed in the LoRom compatibility banks.
- LoRom has less memory it can view at once and less maximum capacity, but its modes may be easier to work with because even if the ROM bank changes, the program can still access RAM and at the same time -- which might be useful if you want to copy stuff within the same page using faster+smaller 16-bit instructions. It always steps in 32K increments.
- FastRom mirrors the entire LoRom/HiRom address space in the upper area of the bank address space, but starts from
$80, $81, ...instead of
$00, $01, .... This high bit in the address line is used as a signal that fast access mode can be made (I think the cartridge hardware is responsible for checking this after a game software activates "high speed mode" on the SNES, but the exact details don't matter for writing a program.)
- The main takeaway from this is, the same memory area in the ROM can be accessed in many different "mirrored" banks of memory. (there's more nuances if you get into expansion chips, or weird third-party cartridges which could have their own memory mapping schemes)
Emulators such as bsnes-plus and Mesen have opted to, for whatever reason, import addresses from the symbol file as absolute addresses that are unmirrored (even though the addresses when fetched by the CPU are mirrored) As a result, this means a name can map to exactly one absolute address -- no mirroring occurs.
Maybe because that's what WLA DX already used? Not sure! Anyway, so I need to adapt the debug code to use the absolute bank addresses exactly as they're declared in the Wiz program, which are normally meant to relocate the program counter during assembling, but aren't necessarily the true position in the ROM. Before this, Wiz was only using output-relative offsets: This is a better, relocatable concept, which refers to the exact address in the ROM, and the emulator could load this with mirroring in mind to resolve things. However, since not every emulator works like this, and we don't want to fork existing emulators just to incorporate what we think would be better, a change is needed.
I haven't had a change to sit down and support this mode yet. I need some way to make these two addressing schemes be selectable by debug target:
a) output-relative byte offset, or
b) cpu memory map address space.
This way, WLA DX-style
.sym exports conform to CPU memory maps on all symbols. I'd like to make the default settings for auto-detected by debug symbol file format, to make it so that exporting doesn't have to configure this. Need to think on this a little more.
Anyway! Hopefully soon!