I think he meant logically. Obviously, it's technically possible as it only takes a single VBlank to DMA all the art over before refreshing the screen, but it would look weird in-game if EHZ suddenly shifted to CPZ instantly :P EDIT - Oh, and btw, I fixed the VRAM bug LocalH was talking about. Turns out it wasn't a VRAM issue at all; it was a DMA issue. More specifically, a bug in the game itself. Basically, in order to load level art into VRAM, it does it backwards. It uses the ending address of the decompressed data in RAM and derives the length in words of the first DMA transfer. It does this by using the lower 12 bits (if the ending address were $6C00, it uses $C00, and right shifts it to get the DMA length). Then after the initial transfer it loads the rest of the art backwards by $1000 byte chunks until it reaches $0000. The problem with this code is that it assumes it's going to find a length. If the decompressed art ends at an address divisible by $1000 (as it does in my case), what happens is that the game uses a length of 0 for the first DMA transfer. Gens apparantly ignores DMA transfers of zero length, but the Genesis (and Kega) don't, and it screws everything up as a result. It's an easy fix too: Right before the call to the subroutine $144E around offset 4F1A, just test d3 for zero, and skip the call to $144E if that's the case. Bug fixed, problem solved. And a new rom to be uploaded for testing just for you LocalH
Yeah, that's pretty much what I meant. Using the method #2 I mentioned, you couldn't reload all the art because some of it would be used on-screen at that moment.
Sorry for the bump but since the topic currently is on DMA's I have a question, How would I get the DMA to load art that gets decompressed by one of the decompression routines? There should be a way to do it [S3 does it somehow] so I was wondering if any of you know how?
You've just been told by me and Ultima about an hour ago how to do it. You need to decompress it to a buffer (and you claim to know what one is) and then from there you send it to VDP by programming the registers as you've been told by both of us, and by sending information to the control and data ports.
Stolen from Sonic 3: (yeah, my disassembly) Code (Text): ; ----------------------------------------------------- ; This subroutine sets the DMA (Direct Memory Access) to 68k to VRAM ; ; d1.l - DMA source address (in 68k memory) ; d2.w - DMA destination address (in VRAM) ; d3.w - DMA length ; ----------------------------------------------------- SetupDMA_68kToVRam: ; CODE XREF: KosinskiModDec_Decompress+72p ; ROM:00003676p ... movea.l ($FFFFFBFC).w,a1 cmpa.w #$FBFC,a1 beq.s SetupDMA_NoDMA move.w #$9300,d0 move.b d3,d0 move.w d0,(a1)+; setup VDP register $13 - DMA length bits 7-0 move.w #$9400,d0 lsr.w #8,d3 move.b d3,d0 move.w d0,(a1)+; setup VDP register $14 - DMA length bits 15-8 move.w #$9500,d0 lsr.l #1,d1 move.b d1,d0 move.w d0,(a1)+; setup VDP register $15 - 68k addr bits 8-1 (remember, the bit 0 is always %0!) move.w #$9600,d0 lsr.l #8,d1 move.b d1,d0 move.w d0,(a1)+; setup VDP register $16 - 68k addr bits 16-9 move.w #$9700,d0 lsr.l #8,d1 andi.b #$7F,d1; '' move.b d1,d0 move.w d0,(a1)+; setup VDP register $17 - 68k addr bits 23-17 andi.l #$FFFF,d2; VRAM destination address lsl.l #2,d2 lsr.w #2,d2 swap d2 ; VRAM destination address, edited to suit VDP =P ori.l #$40000080,d2; set up the 68k to VRAM DMA, start it move.l d2,(a1)+ move.l a1,($FFFFFBFC).w loc_1806: cmpa.w #$FBFC,a1 beq.s SetupDMA_NoDMA move.w #0,(a1) SetupDMA_NoDMA: ; CODE XREF: SetupDMA_68kToVRam+8j ; SetupDMA_68kToVRam+5Aj rts ; End of function SetupDMA_68kToVRam