Copy Link
Add to Bookmark
Report

Anomie's SNES OpenBus & Wrapping Doc

Dreamcast's profile picture
Published in 
SNES
 · 21 Apr 2024

Anomie's SNES OpenBus & Wrapping Doc

Revision: 1126
Date: 2007-04-21 15:07:05 -0400 (Sat, 21 Apr 2007)
<anomie@users.sourceforge.net>

Open Bus

The theory is that the S-CPU chip has something called a "Memory Data Register" or MDR, which stores the value for every read/write. When you attempt to read from unmapped memory, no new value is supplied for this register and so you read the same old value over and over.

Note that CPU IO cycles do not affect the MDR (and therefore the Open Bus value), even though the datasheet specifies addresses for those cycles.

Note that JSL a pushes the old PB before reading the new PB, in case the new PB is being read from Open Bus. Also note that JSR (a,X) pushes the old address (low byte second) before reading the high byte of the new address.

The PPU chips also each have their own MDR, which is updated only when said PPU chip is read. When you read a register with unmapped bits, the PPU fills in only those bits that are defined and leaves the remaining bits as the MDR has them. PPU1's MDR is set by reading $2134-6 or $2138-A, and may also be read from the write-only registers $21x4-6 and $21x8-A (x=0-2). PPU2 involves registers $213B-D only (and maybe $21xB-D, but this is unverified).

Instruction Wrapping

These are my results:

  • Program Counter Increment
    • Always wraps within the bank, at any point in the opcode.

  • Absolute -- a
    • Word reads in native mode will carry into the next bank.

  • Absolute Indexed X -- a,X
    • Adding X may carry into the next bank.
    • Word reads in native mode will carry into the next bank.

  • Absolute Indexed Y -- a,Y
    • Adding Y may carry into the next bank.
    • Word reads in native mode will carry into the next bank.

  • Absolute Indirect -- (a)
    • The "JMP ($xxFF)" bug is fixed.
    • There's no way to test address load wrapping behavior, since it uses Bank 0 as the base and $01:0000-1 is a mirror of $00:0000-1.
    • To be clear: the actual JMP will go to the loaded offset in the current PB, not Bank 0.

  • Absolute Indexed Indirect -- (a,X)
    • Adding X will wrap within the current bank.
    • Address load wraps within the bank (remember, this loads the target address from PB:a+X, not 00:a like (a) or DB:a+X like (a,X).

  • Absolute Long -- l
    • Word reads in native mode will carry into the next bank.

  • Absolute Long Indexed X -- l,X
    • Adding X may carry into the next bank.
    • Word reads in native mode will carry into the next bank.

  • Direct -- d
    • Word reads in native mode will always carry across pages. Theoretically, word reads in emulation mode will wrap within the page when DL=0, and carry when DL!=0.

  • Direct Indirect -- (d)
    • Address load: see 'Direct' above.
    • Data load: Word reads in native mode will carry across pages and banks.

  • Direct Indirect Long -- [d]
    • Address load: Always carries across pages.
    • Data load: Word reads in native mode will carry across pages and banks.

  • Direct Indirect Indexed -- (d),Y
    • Address load: see 'Direct Indirect' above.
    • When Y is added to the indirect address, it will always carry across banks.
    • Data load: Word reads in native mode will carry across pages and banks.

  • Direct Indirect Indexed Long -- [d],Y
    • Address load: see 'Direct Indirect Long' above.
    • When Y is added to the indirect address, it will always carry across banks.
    • Data load: Word reads in native mode will carry across pages and banks.

  • Direct Indexed X -- d,X
    • In native mode, always carry across pages.
    • In emulation mode, wrap within page if DL=0, otherwise carry.
    • Word reads in native mode will always carry across pages. Theoretically word reads in emulation mode will wrap within the page when DL=0, and carry when DL!=0.
    • Reads will NOT carry across banks! e.g. D=$8001, d=1, X=fffe => $00:8000, not $01:8000.

  • Direct Indexed Y -- d,Y
    • Same as Direct Indexed X

  • Direct Indexed Indirect -- (d,X)
    • For address load, see 'Direct Indexed X' above.
    • Data load: Word reads in native mode will carry across pages and banks.

  • PC Relative -- r
    • XXX: untested

  • PC Relative Long -- rl
    • XXX: untested

  • Stack Relative - d,S
    • The address always carries across page boundaries. Yes, this means it can exit the emulation mode stack page.

  • Stack Relative Indirect Indexed -- (d,S),Y
    • Address load: see 'Stack Relative' above.
    • When Y is added to the indirect address, it will always carry across banks.
    • Data load: Word reads in native mode will carry across pages and banks.

  • Block Move
    • Note that when E=1, X and Y are limited to 8 bits, so everything stays in $00xx.

  • Stack Ops
    • When E=1, SH is always 1 and so the stack will normally remain within $01xx.
    • According to the datasheet, the following will somehow access outside $01xx even in emulation mode: JSL; JSR (a,X); PEA; PEI; PER; PHD; PLD; RTL; d,S; (d,S),Y. This is confirmed for PEA; PLD; d,S; and (d,S),Y.
    • If S=0100, PEA will overwrite $0100 and $00ff, and S will end up being 01FE. $01FF will be unchanged. Obviously, a pull here will not read the data you just PEAed.
    • Similarly, a PLD at S=01FF will read D from $200, not $100 (OTOH a PLY will read Y from $100 as expected).

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT