Page 1 of 1

Proper way to emulate DMA transfers.

Posted: Thu Feb 16, 2017 6:01 pm
by urbanspr1nter
Hi all, I am currently writing an SNES emulator, and have been implementing the CPU so far. I have implemented about 120 opcodes and have gotten it to be able to execute some code in Super Mario World ROM. For debugging, I have it output some disassembly. I have gotten to the point where the SMW rom executes what looks to be a DMA transfer... I have never written an emulator for a game console before and was wondering if anyone here could point me in the right direction on how DMA transfer will work in an emulated sense.

My assumption is that CPU loop stops and we actually modify the array that represents RAM directly and move the PC value the number of bytes that were read? (In a sense, this would behave like an interrupt, right?)

The piece of disassembly I have encountered is along the lines of:

Code: Select all

LDA $9277, X
At $9277, I see there are bytes $42 and $26 loaded. Which prompts a series of consecutive bytes to follow:

Code: Select all

7C 92 00 F0 A0 04 F0 80 05 00
I actually am using a disassembly for reference and it looks to be referring to this piece of code here:

Site for reference:
http://caffie.net:31415/root/smw-irq/bl ... ank_00.asm

Image

Any thoughts?

Thanks!

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 8:50 am
by creaothceann
documentation

HDMA is DMA that automatically runs in HBLANK when enabled.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 9:15 am
by tepples
I thought it was called HDMA because it ran in horizontal blanking, not vertical blanking.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 9:33 am
by creaothceann
...fixed.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 10:22 am
by urbanspr1nter
creaothceann wrote:documentation

HDMA is DMA that automatically runs in HBLANK when enabled.
So basically, I would watch for a flag in HBLANK or some sort and then proceed with emulating the transfers from there?

In my mind:
1. CPU execution stops due to HBLANK.
2. Handle the HDMA transfer. => From here, the PC is incremented to transfer the appropriate data.
3. Proceed with CPU execution again?

Thanks.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 10:26 am
by niconii
PC? As in the program counter? No, that shouldn't be touched at all, it transfers data from whatever HDMA tables are pointed to in the HDMA registers.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 10:37 am
by urbanspr1nter
Nicole wrote:PC? As in the program counter? No, that shouldn't be touched at all, it transfers data from whatever HDMA tables are pointed to in the HDMA registers.
Ah, ok. I guess my main and probably very stupid question is... How would we move past the following bytes in the emulator:

If the PC (program counter) if left off around here:

Code: Select all

7C 92 00 F0 A0 04 F0 80 05 00
Those would be interpreted as opcodes and operands -- but it looks like from the assembly reference, it looks to just be raw data.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 10:44 am
by niconii
The PC is never there in the first place, it doesn't need to move past them.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 11:50 am
by nocash
Did you already emulate the RTS opcode, or at least understand what RTS is supposed to do?

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 11:51 am
by urbanspr1nter
Nicole wrote:The PC is never there in the first place, it doesn't need to move past them.
Ah I realize this now after tracing this... So basically it's something like this for this snippet of code:

Code: Select all

setup_window_HDMA:
	LDX.b #$04				                ;$009250	\ Index for DMA set up
.loop						                ;                \ Upload to $4374 to $4370
	LDA.w window_HDMA_settings,X		;$009252	  |
	STA.w $4370,X				                ;$009255	  |
	DEX					                        ;$009258	  |
	BPL .loop				                        ;$009259	 /
	LDA.b #$00				                ;$00925B	 \ HDMA Data bank $00
	STA.w $4377				                ;$00925D	 /


....

window_HDMA_settings:                 
	db $41,$26                                               ;$009277
	dl window_HDMA_data

window_HDMA_data:
	db $F0                                                      ;$00927C
	dw $04A0
	db $F0
	dw $0580
	db $00
X = $04

LDA $9277, X => LDA $927C, Then A = $00
STA $4370, X => STA $4374, Then $00 gets stored in $4370
DEX => X = 3

Repeat until X is negative

And we will have:

Code: Select all

$4370 -> $41
$4371 -> $26
$4372 -> $7C
$4373 -> $92
$4374 -> $00
Apologies for being so newbie. Still trying to learn assembly, hehe.

Re: Proper way to emulate DMA transfers.

Posted: Fri Feb 17, 2017 11:55 am
by urbanspr1nter
nocash wrote:Did you already emulate the RTS opcode, or at least understand what RTS is supposed to do?
Yes -- i realized now that it was my misunderstanding in the assembly code that caused me to trace it the incorrect way initially. But correct me if I am wrong:

RTS will basically:

- Pull the PC values from the stack.
-> increments the PC by 1 to point to the next instruction of where the jump occurred.