DMA to VRAM from RAM

For anything related to VDP (plane, color, sprite, tiles)

Moderators: BigEvilCorporation, Mask of Destiny

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

DMA to VRAM from RAM

Post by r57shell » Tue Jun 04, 2013 12:45 am

Two questions:
1) Size of last move. Can I use move.l instead move.w?
2) Register #1 bit DMA ON state after DMA?
I have real hardware, but I don't have any flash cart yet, so I can't test.

My current steps:
1) turn on DMA
2) set DMA length
3) set DMA src
4)

Code: Select all

pea (DMA_command_with_destination)
move.w (sp)+,($C00004)
stop_z80
move.w (sp)+,($C00004)
resume_z80
It works well on any emulators which I tested, but...
It seems does not work on real hardware.
Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Jun 04, 2013 1:01 am

Do you access the VDP inside an interrupt? If so, are you disabling ints before accessing the VDP outside interrupts?

... and you really ought to be doing a long access, not word accesses.

You don't need to stop the Z80 during a DMA - if the VDP is taking control of the 68000 bus, the Z80 is automatically held up until it's done.

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Tue Jun 04, 2013 1:14 am

Chilly Willy wrote:Do you access the VDP inside an interrupt?
How did you know? )))
Ok, moved, now I don't access the VDP inside VBLANK.
Chilly Willy wrote:You don't need to stop the Z80 during a DMA - if the VDP is taking control of the 68000 bus, the Z80 is automatically held up until it's done.
I don't want to held down z80. It's my mistake, I mean: restrict access from z80 to M68k rom. (say: "don't touch him")
Chilly Willy wrote:... and you really ought to be doing a long access, not word accesses.
But everywhere used word access for last move. I have not seen any example of DMA from RAM using long access in last move.

Something else? Updated.
Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Jun 04, 2013 1:44 am

SGDK uses a long.

You've still got something fundamentally wrong - you're still not updating on real hardware and it still trashes the display after several seconds playing.

We really need to see the code to say what's wrong. Your pseudo-code seems fine, which means it's a bug in the actual code. The fact that pushing right changes the number on screen on an emu and not real hardware SHOULD give you an idea of where to look for trouble. Neither of your counters increment on the screen either on real hardware. NOTHING changes until you press A, then several seconds into the music, the display is trashed.

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Tue Jun 04, 2013 2:13 am

Updated: DMA removed at all. I will think, what can be wrong. Now, I'm going to sleep. ~~
Another build. DMA with long access in the end, and joypad reading moved from VBLANK: http://elektropage.ru/r57shell/Player1.bin
Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Jun 04, 2013 3:32 am

Still no update, and now it doesn't play any sound. Doesn't do anything but show the screen the first time and then nothing.

Funny, works on fine on the emulator.

walker7
Interested
Posts: 45
Joined: Tue Jul 24, 2012 6:27 am

Post by walker7 » Tue Jun 04, 2013 5:46 am

From Charles MacDonald's Sega Genesis VDP documentation:
When a transfer is done out of the ROM area ($000000-3FFFFF), the machine will lock up unless the write that triggers the DMA operation is done using RAM.

Usually this means putting the command word or the latter half of the command word in RAM and moving that into the control port, putting the command word on the stack and moving that into the control port, or having the instruction that moves the command word into the control port execute out of RAM.
I would suggest using the stack, since it effectively uses a RAM address. After you create your VDP command, push it on the stack, then pull it and store it at the same time, like this (assume that the VDP command is in register d0 in this example):

Code: Select all

move.l	d0,-(a7)
move.l	(a7)+,($C00004)

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Tue Jun 04, 2013 11:32 am

Turned All things off. Without DMA.
Only counters update, and screen update.

http://elektropage.ru/r57shell/Player2.bin

Source: http://pastebin.com/BHymZ1LN
Compiled: http://elektropage.ru/r57shell/GEMS_Player_cut.bin
Highlighter of source, moves instruction after label, to start of line :S
Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Jun 04, 2013 5:13 pm

Okay, this one actually acts differently - the counters advance on the screen, and you have a line of blinking dots going through the "Game: Comix Zone" line. They appear over the letters, which don't blink, so it's in the other layer than the text.

Oh, the blinking dots are probably trash from update_palettes() - you don't update the palette in the vblank, it's like this

Code: Select all

update_proc:
 bsr     update_info
 bsr     update_planeA_map
 bsr     update_palettes
 rts
Since there's little being updated right now, it's updating the palettes in the active part of the display, which causes a line or two were you get trash as the cram entry gets written. If the palette isn't changing, you shouldn't write the palette more than once, and if it IS changing, only write the entries that change, and do so in the horizontal or vertical blank areas of the screen.

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Tue Jun 04, 2013 5:25 pm

Which of ROM acts so? In latest, no string "Comix Zone"
dots... Hmm.. I don't change Plane B, only Plane A.
VBLANK occurs in begining of display update or in the end?
Anyway, source posted. Display always turned ON.
May be not enough speed without DMA.
I can turn on again DMA. (Bugs may be in joypads. they now turned off).

I never expected, that emulators emulating so bad...

I want place update process in the end of diplay update. (after last line showed). What should I do?

Ok I will turn on DMA, and see, is it work, and if work, then problem not with DMA. )

With DMA from VRAM: http://elektropage.ru/r57shell/GEMS_Player_cut_dma.bin
Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Jun 04, 2013 6:33 pm

r57shell wrote:Which of ROM acts so? In latest, no string "Comix Zone"
dots... Hmm.. I don't change Plane B, only Plane A.
The dots are strictly due to WHEN you write the palette. If you write to cram during the active video line, the fetched cram is replaced by the value written to cram, regardless of the entry. That gives you a dot of trash on the display. It can happen with writing via CPU or DMA, as long as that writing happens during the active display of a line.

VBLANK occurs in begining of display update or in the end?
The VINT occurs after the last active display line, which is also the start of the vertical blank period.

Anyway, source posted. Display always turned ON.
May be not enough speed without DMA.
I can turn on again DMA. (Bugs may be in joypads. they now turned off).

I never expected, that emulators emulating so bad...
Emulators typically are designed around making commercial games run "acceptably." Accuracy is usually an afterthought. The new Exodus cycle-accurate emulation might be better for testing on.
I want place update process in the end of diplay update. (after last line showed). What should I do?
Trigger it off the vblank somehow. You could do the update IN the vblank int handler, or you could set a flag telling the main task that NOW is the time to do updating.

Ok I will turn on DMA, and see, is it work, and if work, then problem not with DMA. )

With DMA from VRAM: http://elektropage.ru/r57shell/GEMS_Player_cut_dma.bin
This displays an advancing clock, but a few tiles are messed up (w, x, y, and the arrow are trashed... probably every tile from w to the end are trashed).

Be sure your data being DMAd is not crossing a 128KB boundary. If you look at the DMA routine in sgdk, if the data crosses a 128KB boundary, it splits it into two DMA operations: the first goes up to the 128KB boundary, and the second does the rest after the boundary.

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Tue Jun 04, 2013 7:24 pm

Chilly Willy wrote:The dots are strictly due to WHEN you write the palette.
I understand.
Chilly Willy wrote:If you write to cram during the active video line, the fetched cram is replaced by the value written to cram, regardless of the entry.
I know it too. But, to avoid those dots, I need to do update during inactive video line. Is there so period? How to catch start of it.
Now update start RIGHT after VBLANK interupt occurs.
Chilly Willy wrote:The VINT occurs after the last active display line, which is also the start of the vertical blank period.
Vertical blank period means that no active line? I just want to be sure with meaning of "blank" word. I assume that after VINT, there is some time before next active line (first), and that this delay much longer than delay between two active line in middle.
Chilly Willy wrote:You could do the update IN the vblank int handler, or you could set a flag telling the main task that NOW is the time to do updating.
I do so. wait_vblank - it is "NOW". But, as I see, this "NOW" = bad moment, or update proc takes too much time, so it handles due active lines.
Chilly Willy wrote:This displays an advancing clock, but a few tiles are messed up (w, x, y, and the arrow are trashed... probably every tile from w to the end are trashed).
So, DMA works. Answer to first question of topic is: any size. This "part" of DMA works as expected. Only one thing left: DMA on flag in #1 register clears it's state or not.
Chilly Willy wrote: Be sure your data being DMAd is not crossing a 128KB boundary.
Not crossing.

Shows Joypad: http://elektropage.ru/r57shell/GEMS_Player_cut_dma.bin
And, without: move.w #$8174,($C00004).l, so DMA turn ON only once.
Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Jun 04, 2013 8:10 pm

Okay, this one shows the joy state, and seems to read fine. As far as the font goes, only the arrow on the selected line is garbage - the w,x,y are fine this time.

The blank period is not active. You can safely change the palette in either the horizontal or vertical blank, but the horz blank is so short that you can only change a couple colors. The VDP status has bits that show when the blank periods are active. The VINT occurs at the start of the vblank, and you have (262 - 224 for NTSC) lines to do what you need before the active period starts again.

r57shell
Very interested
Posts: 478
Joined: Sun Dec 23, 2012 1:30 pm
Location: Russia
Contact:

Post by r57shell » Tue Jun 04, 2013 9:38 pm

I don't know why arrow, or w,x,y (I don't know where), trashed. Source posted, just uncomment sections "With DMA" and comment "Without DMA".

So, It means that DMA ON flag remains. Some document said that it is not remains.
Joypad works correctly. What else can trash DMA result?
Playing music from start: http://elektropage.ru/r57shell/GEMS_Player_cut_dma.bin
Image

Chilly Willy
Very interested
Posts: 2984
Joined: Fri Aug 17, 2007 9:33 pm

Post by Chilly Willy » Tue Jun 04, 2013 10:17 pm

Doesn't make a sound. Not crashing, though.

The source you posted only uses the CPU to copy the tile, so I can't say what you're doing wrong there. Maybe you forgot that the length you pass to copy_tiles is one less than the number of tiles to copy (for the dbra). Remember to add one before shifting left to get the DMA length.

Post Reply