Iron Maiden chiptune musicdisc + 26 kHz mod/ahx player

Announce (tech) demos or games releases

Moderator: Mask of Destiny

Kabuto
Interested
Posts: 27
Joined: Sun Aug 25, 2013 6:56 pm

Post by Kabuto » Sun Dec 07, 2014 12:27 am

@Chilly Willy: Interesting. What's the trick you're talking about?

@Mask of Destiny: yeah, one of the many fixes I'm gonna do. Might be tricky as no emulator exhibits this behaviour (but I got a modded MD2 that does)

@bastien: nice to hear, thanks :)


Regarding the z80 access timings, tests on a real MD revealed that what Mask of Destiny wrote seems to be correct. I played a low frequency sample so I could easily see missed writes in my audio editor after filtering the low frequency wave out.

68k delay / z80 T cycles / result

8 / <= 4 / lots of misses
12 / <= 4 / no misses at all
12 / <= 5 / a few misses (2 per second)
12 / <= 6 / lots of misses (50 per second)

Here's the transfer code with 12 cycles of delay:

Code: Select all

        move.w  #$100, (a1)        ; Request Z80 bus
        swap    d6         ; some delay
        move.l  d7, (a4)+	; Write 2 samples
        move.w  d6, (a1)        ; Release Z80 bus
Testing also revealed a bug in Exodus, it requires at least 18 cycles of delay for <= 4T, or else it will glitch. Or replacing the (a1) in the first line with $A11100 which also makes the bug go away in exodus (and my code slower). That's pretty odd, since I usually assume that the write cycle always happens last in an instruction, and as expected hardware testing shows that doing this replacement has no effect on real hardware regarding the glitches.


[Edit: more research on exodus bug to confirm that it's just an exodus bug and not a behaviour that occurs on real hardware too]

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

Post by Chilly Willy » Sun Dec 07, 2014 7:36 am

Kabuto wrote:@Chilly Willy: Interesting. What's the trick you're talking about?
Just what we said - using the user stack pointer. The 68000 has two separate stack pointers: the user stack pointer, and the supervisor stack pointer. A7 is set to one or the other depending on the mode 68000 is in. While in supervisor mode, you can also use "move usp,an" or "move an,usp" to read/write the user stack pointer. PCM DMA requires fast access of the data to avoid eccesive jitter, as well as to not take too much overhead to keep from slowing the main program down.

So rather than keeping a pointer to the pcm data in memory, the pointer is kept in usp instead. A timer generates an int at the sample rate, and the int code looks somewhat like this:

Code: Select all

interrupt:
    move.l a0,-(sp)
    move usp,a0
    move.b (a0)+,PCM_REGISTER
    cmpa.l #DMA_END,a0
    bne.b .exit
;loop
    lea DMA_START,a0
.exit:
    move a0,usp
    movea.l (sp)+,a0
    rte
That would be for a looping output. If you were just playing a one shot, you'd simply disable the interrupt when you hit DMA_END. The ST didn't have a pcm output register - what you did was set the PSG into a special state and then manipulate the volume register (something like that). So PCM_REGISTER was really the channel volume register. Common rates were 3.5 kHz and 7 kHz. With that many ints per second, you really had to keep the interrupt handler as simple and fast as possible.

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

Post by Stef » Sun Dec 07, 2014 11:11 am

Kabuto wrote: Regarding the z80 access timings, tests on a real MD revealed that what Mask of Destiny wrote seems to be correct. I played a low frequency sample so I could easily see missed writes in my audio editor after filtering the low frequency wave out.

68k delay / z80 T cycles / result

8 / <= 4 / lots of misses
12 / <= 4 / no misses at all
12 / <= 5 / a few misses (2 per second)
12 / <= 6 / lots of misses (50 per second)

Here's the transfer code with 12 cycles of delay:

Code: Select all

        move.w  #$100, (a1)        ; Request Z80 bus
        swap    d6         ; some delay
        move.l  d7, (a4)+	; Write 2 samples
        move.w  d6, (a1)        ; Release Z80 bus
Definitely interesting to know that :) I always though the bus request operation was a lot slower. So basically 2 nop between the request and first write is enough to assure the values are correctly written.

Post Reply