Post subject: Using SNES9X trace logger for RNG analysis
Skilled player (1886)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
Hi, I'm trying to understand how RNG works in the SNES game Goof Troop, and I figured that I should be able to decipher how the RNG works by using the trace logger. Here's what I know about about RNG: The current RNG value is stored as a 16 bit word at RAM address 7E1A58. The RNG changes when you pick up a pot, but I don't know exactly how. I made a trace log for a few frames during which I picked up a pot and thus changed the RNG. So somewhere in this trace log file there should be information on how the RNG changed, but I have a hard time figuring out where. Does anyone here have experience with the trace logger? Is there a guide or manual somwhere? I didn't find one when googling. What should I look for in the trace log file if I want to find out how 7E1A58 changed during these frames? (I searched for the string 7E1A58 with no luck, all addresses here seem to start with 8) Also, while I'm at it, can someone point me to where I can read up on what all these 3 letter commands stand for? I know a few (lda=load, bne=branch on not equal), but not all of them. The closest thing I've found was this: http://en.wikipedia.org/wiki/List_of_CIL_instructions but only a few are represented here.
Editor, Skilled player (1941)
Joined: 6/15/2005
Posts: 3247
I'd use Geiger's Snes9x Debugger: http://geigercount.net/crypt/ It supports read/write/exec breakpoint and op advance, and that is very useful. About commands, I know of these (I might have made some mistakes, though): LD(A,X,Y) - load to register, either #$ (fixed number), $ (memory address), or $,X (offset from memory address, only with LDA) ST(A,X,Y) - store from register, $ (memory address), or $,X (offset from memory address, only with STA) STZ - store 0, $ (memory address), or $,X (offset from memory address) ADC - add to register with carry flag, either #$ (fixed number), $ (memory address), or $,X (offset from memory address). If carry flag is 1, ADC adds one more, otherwise, no. Carry flag is set to 1 if there is overflow, set to 0 otherwise. CLC - clear carry flag (set to 0); almost always ADC follows it. SBC - subtract from register with carry flag, either #$ (fixed number), $ (memory address), or $,X (offset from memory address). If carry flag is 0, SBC subtracts one more, otherwise, no. Carry flag is set to 0 if there is underflow, set to 1 otherwise. SEC - set carry flag (set to 1); almost always SBC follows it. CMP, CP(X,Y) - compare register with number (CMP is register A), either #$ (fixed number), $ (memory address), or $,X (offset from memory address). It does so by temporarily subtracting the number from the register, but unlike SBC, this doesn't change the value of the register, but only sets the special flags. If register is less than the number, carry flag is set to 0; otherwise it is set to 1. If A is equal to the number, zero flag is set to 1; otherwise it is set to 0. BCC - branch if carry flag is 0, either relative (1 byte offset) or absolute (2 byte address) BCS - branch if carry flag is 1, either relative (1 byte offset) or absolute (2 byte address) (note if it does not follow CMP, the zero flag is 1 if the last operation results in a value of 0, and 0 otherwise) BEQ - branch to address if zero flag is 1, either relative (1 byte offset) or absolute (2 byte address) BNE - branch to address if zero flag is 0, either relative (1 byte offset) or absolute (2 byte address) JMP - unconditional branch, absolute (2 byte address) JSR - execute subroutine, absolute (2 byte address) RTS - return from subroutine IN(X,Y) - increment register DE(X,Y) - decrement register TA(X,Y) - transfer from A to X/Y, set X/Y to the value of A T(X,Y)A - transfer from X/Y to A, set A to the value of X/Y PH(A,X,Y) - push value of register into stack PL(A,X,Y) - pull value from stack and set register to that value ASL A - shift the bits of A to the left (multiply by 2) LSR A - shift the bits of A to the right (unsigned divide by 2) ASR A - shift the bits of A to the right with respect to signed bit (signed divide by 2) ROL A - rotate the bits of A to the left, through the carry bit ROR A - rotate the bits of A to the right, through the carry bit NOP - do nothing I think there are other functions like REP and SEP (which set the 8-bit or 16-bit modes) and XBA (swap high and low bytes).
P.JBoy
Any
Editor
Joined: 3/25/2006
Posts: 850
Location: stuck in Pandora's box HELLPP!!!
here's a list of 65816 opcodes I've made
Former player
Joined: 5/4/2005
Posts: 502
Location: Onett, Eagleland
I used MESS to debug FFIV's monster encounter formula. It's got some pretty useful functions the snes9x debugger doesn't. I've been playing around with BSNES's new debugger laevateinn and it's quite useful. It lacks some necessary features like a "goto" disassembly address and memory searcher, but I still prefer it simply because I know BSNES is more accurately emulating the SNES hardware than anything else out there. It has a trace feature. http://bsnes.googlecode.com/files/laevateinn_v086.7z Here's a nice document on the 65C816 that includes a instruction set and description: http://www.westerndesigncenter.com/wdc/datasheets/Programmanual.pdf
I think.....therefore I am not Barry Burton
Skilled player (1886)
Joined: 4/20/2005
Posts: 2160
Location: Norrköping, Sweden
Thank you all for your responses. In the end, I used the trace logger file to dissect the RNG - I wrote another program that translates each row of the trace logger to plain language, so I could more easily follow what is happening. P.JBoy's list was very helpful for this, so thank you very much for that. I have a question though: For the STA command, how do I know if it stores an 8 bit or a 16 bit number? For example, if the trace logger says STA $0000 and A contains the hexadecimal number $012C, will it place the value $01 on address $0000 and the value $2C on address $0001? Or does it only move the 8 bit number $01?