Bug in genesis.c?

Ask anything your want about Megadrive/Genesis programming.

Moderator: BigEvilCorporation

furrykef
Interested
Posts: 30
Joined: Mon Jul 21, 2008 7:28 pm

Bug in genesis.c?

Post by furrykef » Sat Jul 26, 2008 9:37 am

I'm converting dma_vram_copy from genesis.c into ASM and I think I found a bug in it, at least the version I have. (I got it from one of his examples, so maybe he's updated it since then...)

Code: Select all

void dma_vram_copy(uint source,ushort dest,ushort len)
{
    register volatile ushort *pw;
    register uint *pl;

    /* Halt the Z80 for DMA */
    pw = (ushort *) Z80_HALT;
    *pw = 0x100;

    /* Point to GFX register */
    pw = (ushort *) GFXCNTL;

    /* Setup DMA length */
    len >>= 1;
    *pw = 0x9300L + (len & 0xff);
    *pw = 0x9400L + ((len >> 8) & 0xff);

    /* Setup DMA address */
    source >>= 1;
    *pw = 0x9500L + (source & 0xff);

    source >>= 8;
    *pw = 0x9600L + (source & 0xff);

    source >>= 8;
    *pw = 0x9700L + (source & 0xff);

    /* Enable DMA */
    pl = (uint *) GFXCNTL;
    *pl = GFX_DMA_ADDR((uint) dest);

    /* Enable Z80 */
    pw = (ushort *) Z80_HALT;
    *pw = 0;
}
The suspected error is in this part:

Code: Select all

    pl = (uint *) GFXCNTL;
    *pl = GFX_DMA_ADDR((uint) dest);
The problem is that we don't know where the result of GFX_DMA_ADDR is stored. I bet it'd be stored in a register, in which case it basically compiles to "move.l d0, GFXCNTL", which violates the rule that the instruction that activates the DMA transfer must use RAM, so it'd probably crash on the actual hardware. You need to do something like push it on the stack and move it form there into GFXCNTL, right?

I haven't tested to see how this code actually compiles, but I think it's irrelevant anyway; it's still an error in the code even though it may compile into the correct operation. I think the only way to be absolutely sure that the operation uses memory would be to use inline ASM.

- Kef

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Sat Jul 26, 2008 2:24 pm

You need to have code in RAM only if you're DMAing from outside the ROM area (i.e from MD RAM to VRAM).
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

HardWareMan
Very interested
Posts: 745
Joined: Sat Dec 15, 2007 7:49 am
Location: Kazakhstan, Pavlodar

Post by HardWareMan » Sat Jul 26, 2008 2:31 pm

I use this method:

Code: Select all

        move.w   #$9320,(a6)            ;Lower byte of size => #19
        move.w   #$940D,(a6)            ;Upper byte of size => #20
        move.w   #$9500,(a6)            ;Lower byte of origin => #21
        move.w   #$96C0,(a6)            ;Middle byte of origin => #22
        move.w   #$977F,(a6)            ;Upper byte of origin => #23
        move.l   #$40200080,(a6)        ;Write to VRAM at offset 0x0000 
It is works on hardware.

furrykef
Interested
Posts: 30
Joined: Mon Jul 21, 2008 7:28 pm

Post by furrykef » Sat Jul 26, 2008 2:32 pm

TmEE co.(TM) wrote:You need to have code in RAM only if you're DMAing from outside the ROM area (i.e from MD RAM to VRAM).
But that's not what the official documentation says:
sega2f.doc wrote:Source address are $000000-$3FFFFF(ROM) and $FF0000--$FFFFFF(RAM) for memory to VRAM transfers. In the case of ROM to VRAM transfers, a hardware feature causes occasional failure of DMA unless the following two conditions are observed:

--The destination address write (to address $C00004) must be a word
write.
--The final write must use the work RAM.
Whichever way is correct, there's still a bug because the function doesn't know whether the source address is in RAM or not -- not the way it's written, anyway.
HardWareMan wrote:move.l #$40200080,(a6) ;Write to VRAM at offset 0x0000
Shouldn't that write to 0x0200? Or am I confused?

- Kef
Last edited by furrykef on Tue Aug 12, 2008 7:09 am, edited 1 time in total.

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Sat Jul 26, 2008 7:03 pm

hmmm.... I have not had any issues with DMA, except when I discovered that DMA doesn't cross 128KB blocks... I do extensive testing on real HW and I've not had a single problem with any of my programs.
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

furrykef
Interested
Posts: 30
Joined: Mon Jul 21, 2008 7:28 pm

Post by furrykef » Sat Jul 26, 2008 7:59 pm

And you've tested it on all variations of the hardware? Just checkin'.

HardWareMan
Very interested
Posts: 745
Joined: Sat Dec 15, 2007 7:49 am
Location: Kazakhstan, Pavlodar

Post by HardWareMan » Sun Jul 27, 2008 4:13 am

furrykef wrote:
HardWareMan wrote:move.l #$40200080,(a6) ;Write to VRAM at offset 0x0000
Shouldn't that write to 0x0200? Or am I confused?
You are right. That is old comment, so it is not correct.

furrykef
Interested
Posts: 30
Joined: Mon Jul 21, 2008 7:28 pm

Post by furrykef » Sun Jul 27, 2008 8:09 am

Sounds like you should revise your code. After all, bad comments are worse than no comments. ;)

- Kef

HardWareMan
Very interested
Posts: 745
Joined: Sat Dec 15, 2007 7:49 am
Location: Kazakhstan, Pavlodar

Post by HardWareMan » Sun Jul 27, 2008 9:23 am

furrykef wrote:Sounds like you should revise your code. After all, bad comments are worse than no comments. ;)
- Kef
Not all code. This example is copy-pasted from one project and comment was rewritten. I guess I just missed this number.

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Sun Jul 27, 2008 9:35 am

furrykef wrote:And you've tested it on all variations of the hardware? Just checkin'.
It works on MD2 VA1, MD1 VA4, MD1 VA6, Nomad, Xeye(basically same as MD2 VA1) and Wondermega... no trouble so far...
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

furrykef
Interested
Posts: 30
Joined: Mon Jul 21, 2008 7:28 pm

Post by furrykef » Sun Jul 27, 2008 9:37 am

So are the docs completely wrong, or are there cases where you do indeed need to access RAM in the instruction where you activate DMA?

TmEE co.(TM)
Very interested
Posts: 2440
Joined: Tue Dec 05, 2006 1:37 pm
Location: Estonia, Rapla City
Contact:

Post by TmEE co.(TM) » Sun Jul 27, 2008 10:12 am

Nobody can say they're wrong... there's over 10 other models of MDs around that I don't have... I've never had any problems with what I've got when doing ROM to VRAM transfers. I guess when I'm doing more serious work on my game, I might run into some quirks... I'm more specialized in MD sound part...
Mida sa loed ? Nagunii aru ei saa ;)
http://www.tmeeco.eu
Files of all broken links and images of mine are found here : http://www.tmeeco.eu/FileDen

notaz
Very interested
Posts: 193
Joined: Mon Feb 04, 2008 11:58 pm
Location: Lithuania

Post by notaz » Mon Jul 28, 2008 11:51 am

Many commercial games start ROM->VRAM (and even RAM->VRAM) DMAs while running from ROM, so there is nothing to worry about.

furrykef
Interested
Posts: 30
Joined: Mon Jul 21, 2008 7:28 pm

Post by furrykef » Mon Jul 28, 2008 3:38 pm

According to the manual, the instruction doesn't have to run from RAM (although that is one way to do it), it just has to use RAM. So do those games do something like this?

Code: Select all

    move.l d0, -(a7)
    move.l (a7), GFXCTNL
    move.l (a7)+, d0
Or do they just do this?

Code: Select all

    move.l d0, GFXCTNL

Stef
Very interested
Posts: 3131
Joined: Thu Nov 30, 2006 9:46 pm
Location: France - Sevres
Contact:

Post by Stef » Mon Jul 28, 2008 11:53 pm

I wrote the code in this way because i tested it on hardware and i never met any problems with it. I don't say it will never happen, i do know the officials documents said we must write the last command from RAM but if i can avoid all the "obscure tricks" to make things work then i avoid them. Maybe i'll need to fix that later but for now it works so it's ok for me. Same is true for the IO read functions : officials documents said you have to disable Z80 but i never needed it so i never do it ;)

Post Reply