Old Regen pages

AamirM's Regen forum

Moderator: AamirM

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

Post by HardWareMan » Mon Aug 18, 2008 8:50 am

AamirM wrote:
HardWareMan wrote:In your record that sound effect starts quite early, then in record from real YM2612. Why that happen? Not perfect syncronization Z80 with YM2612?
I looked at it and it turned out be due to timers. Although I managed to correct it but it makes sound in some games little slow. Here is a recording with fixed timers. I don't know if I should make those changes to the timers. What do you think?
As WIKI says, PAL version has VCLK=7.61MHz/Z80CLK=3.55MHz and NTSC VCLK=7.67MHz/Z80CLK=3.58MHz. YM2612 using VCLK as master clock signal, so timers is depends on it. If we calculate ratio between VCLK and Z80CLK, we get this value: NTSC 7.61/3.55=2.143 and PAL 7.67/3.58=2.142. And difference between PAL and NTSC ratios is quite little: only 0.01%, so this timing problem cannot be from PAL/NTSC frequency difference. So, maybe you right: only timers can correct this. Or maybe "BUSY" flag emulation...
AamirM wrote:Thanks for your help again. Interestingly, Kega has the same problem too which may indicate it doesn't has correct timers as well. And about the PSG level, yes its incorrect. I will be writing a band limited PSG core soon which won't have perfect square waves and correct noise waveform levels.
I will wait for this.
Last edited by HardWareMan on Mon Aug 18, 2008 11:46 am, edited 1 time in total.

Zoomer
Interested
Posts: 14
Joined: Wed Apr 09, 2008 6:48 pm

Post by Zoomer » Mon Aug 18, 2008 11:03 am

Yep, using Vista x64. If I'll compare Kega and Regen - Regen's window will be a little smaller. And in example I've posted earler - looks like letters in ReGen have been resized or something like that.

About interpolation - can it be included in future in Regen? :)

King Of Chaos
Very interested
Posts: 273
Joined: Fri Feb 29, 2008 8:12 pm
Location: United States

Post by King Of Chaos » Mon Aug 18, 2008 5:12 pm

Zoomer wrote:Yep, using Vista x64. If I'll compare Kega and Regen - Regen's window will be a little smaller. And in example I've posted earler - looks like letters in ReGen have been resized or something like that.
Yeah, it exists in Vista. I was probably one of the first ones to notice this. :P

AamirM
Very interested
Posts: 472
Joined: Mon Feb 18, 2008 8:23 am
Contact:

Post by AamirM » Mon Aug 18, 2008 6:05 pm

Hi,

Ok. I've almost given up on TmEE's DAC problem. Can anybody else finds whats wrong? BTW, no emulator except Kega and MAME/MESS do this right. In my theory, TmEE's program write to DAC so fast such that the buffer gets overwritten before the samples written before get played. Can anybody find a workaround?

stay safe,

AamirM

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Tue Aug 19, 2008 1:11 am

Well, I've got what I think are some YM2612 timer issues in my emulator I need to fix before I can run that sample rom at the proper rate, but when I play it in my emulator, it seems to get the DAC correct. I'm not doing anything exotic to handle the DAC as such, but in my YM2612 core, all register changes are buffered and timestamped. When I want to generate a batch of samples, I know the relative time when each and every sample is generated compared with the stored register changes, so I know when to "commit" each register change. When I'm generating a batch of samples, I check for any register changes which need to be applied before each sample. This allows each register change to take effect at the precise sample it should be applied, which in the case of DAC changes means it should produce a sample-accurate output.

I guess it's up to you what you want to do about buffering. I don't know how you've written your core, but a few thoughts from my experience. It's impossible to create an output which will be 100% accurate from a chip like the YM2612 or SN76489 without either buffering and timestamping changes, running the entire emulator in lock-step one cycle at a time, or generating your sound output in step with your processor execution, but then you've got synchronization issues because both the Z80 and M68000 can access the sound chips. I found the easiest way to solve these problems in my emulator was to buffer every register change to the YM2612. The YM2612 has a separate thread which runs along in parallel one step behind, reading register changes from the back of the buffer and generating the output. It works well, it's accurate, but as you might expect, it's slow.

If you're not already doing something like this in Regen, you might want to implement it on a smaller scale for the DAC register only. Buffer and timestamp every write to the DAC register. When you're generating samples for the YM2612 and DAC is enabled, make sure you accurately process the timestamps for the DAC data changes, and you should be able to pick the exact sample to apply each change. How easy it is to generate these timestamps and relate them to the current sample being generated in the YM2612 depends a lot on the overall architecture of your emulator.

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Tue Aug 19, 2008 7:25 am

I don't have problem with TmEE's tune either (quite excellent one btw :D )

In genesis plus, I'm calling this function before each FM writes and read:
static inline uint32 fm_sample_cnt(uint8 is_z80)
{
if (is_z80) return (uint32) ((double)(count_z80 + current_z80 - z80_ICount) / z80cycles_per_sample[0]);
else return (uint32) ((double) count_m68k / m68cycles_per_sample[0]);
}
m68cycles_per_sample is 144 when emulating the YM2612 at his original frequency, otherwise it is the number of cpu cycles per second divided by the output samplerate

z80cycles_per_sample is m68cycles_per_sample * 7 /15

this gives me the current number of samples that should have been played so far in the current frame, the FM core is updated before writes/read if new samples need to be played... according to R.Belmont, MAME/MESS is working the same way

I'm doing similar stuff for the PSG chip

However, as Nemesis said, adding timestaming informations and updating everything at the end of the frame is probably more efficient. Threaded CPUs is something I would like to try but I'm still not sure it is really required for perfect accuracy.


some discussions on SMSPower:

http://www.smspower.org/forums/viewtopic.php?t=10142
http://www.smspower.org/forums/viewtopic.php?t=2354

AamirM
Very interested
Posts: 472
Joined: Mon Feb 18, 2008 8:23 am
Contact:

Post by AamirM » Tue Aug 19, 2008 7:34 am

Hi,

Ah, a very clever idea :) . Thanks. In Regen, sound is generated very much like its done in Gens. This is not accurate, I know. But one question, how much changes do you buffer and timestamp? And what are you using to timestamp (68k or Z80 cycles or both depending on who wrote to DAC)?

I think Eke implemented a similar thing but I don't know if DAC is running correct in his emu. Eke, is it running TmEE DAC program correctly?

EDIT:
Eke beated me in typing :lol: . He already answered.

stay safe,

AamirM

AamirM
Very interested
Posts: 472
Joined: Mon Feb 18, 2008 8:23 am
Contact:

Post by AamirM » Tue Aug 19, 2008 9:44 am

Hi,

I managed to fix it :D :D . Thanks a lot Eke and Nemesis. You guys are great. This would finally make Tiido happy :) .

stay safe,

AamirM

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Tue Aug 19, 2008 9:59 am

Well, what I do in my emulator probably wouldn't be very adaptable to Regen. I designed the structure of my emulator from the ground up to allow precise time comparisons to be made between cores. My emulator is driven by execution "steps" called timeslices. Each timeslice has a known length, and each core can determine its own progress through the current timeslice, and the progress of any core which it interacts with, at any point in time. A timestamp is a combination of a reference to a timeslice (which gives the length and position of the block of time in which the access occurred), and a time displacement (which gives the current progress of the core which is performing the operation through the timeslice). In this way, the timestamp isn't relative to any other core. A timestamp is represented in "real time" or "system time", with which the YM2612 is able to compare its own progress with.

You shouldn't need a system like that to solve this problem though. I really haven't looked at how other emulators like MAME and Gens manage synchronization issues, but all you should need is a running counter of some kind which you can directly relate to the Z80, M68000, and YM2612, and is high resolution enough to record the times you need. It could be as simple as a running cycle counter based on the system clock, as the clock for every chip will be a clean division from this clock source. You could store a copy of the counter indicating what it was up to the last time you advanced the YM2612 core, and from that stored value, you'll know when each buffered write should be committed.


In terms of the buffering itself, well, in my emulator I spent months designing and optimizing a generic thread-safe container to solve this problem. The container is like an array, except that it is able to store and return the correct value for any address over a range of time. When reading from or writing to the buffer, you pass a timestamp. The buffer itself has a "committed" baseline, which is just an array. On top of this, it stores a sorted list of writes that have occurred past the baseline. The YM2612 audio thread works from the baseline, and advances it in steps as it executes. As buffered writes are committed, the new value is written into the array. Reading committed data is as fast as reading from a raw array. Adding new writes to the buffer only requires adding a small structure to a linked list. Ad-hoc reads past the committed state are relatively slow (requires iteration of the buffer), but can be performed. I've only had to use them so far for the VDP when the external chip reads data from VRAM, which is a rare operation.

I only designed a system like this because I wanted to be able to solve the "unsolvable" timing problems. It's allowed me to implement support for things like mid-line changes to VRAM, and even emulate the flicker bug on CRAM writes. It is VERY accurate, but it's also VERY slow. At this point in time, my emulator doesn't run full speed on a core 2 duo E6750, and that's with each active core running in a dedicated thread. You wouldn't want to try playing a game in it. My emulator is entirely focused on debugging, reverse engineering, hardware prototyping, etc. Being able to play games full speed would just be an added bonus. Maybe in a few years time.


Again, this is overkill for this particular problem. For DAC in Regen, I'd suggest a running cycle counter like I mentioned above, and a simple linked list which for each entry stores the cycle counter at the time of the write, and the new value written. The Z80 or M68000 add new entries to the list when they write to the DAC data register, and when you advance the YM2612, you read the entries in the list and apply them. The only things you'll need to do are probably sort the linked list by write time (in case M68000 and Z80 both try and access it), and deal with the case where the cycle counter overflows.

Nemesis
Very interested
Posts: 791
Joined: Wed Nov 07, 2007 1:09 am
Location: Sydney, Australia

Post by Nemesis » Tue Aug 19, 2008 9:59 am

....and in the time it took me to write that, you've already fixed the problem. :D

Eke
Very interested
Posts: 884
Joined: Wed Feb 28, 2007 2:57 pm
Contact:

Post by Eke » Tue Aug 19, 2008 12:14 pm

it's always interesting to see how people manage different emulator architecture, especially when it is going into smart & optimized designs

so, this mean you are running a pixel-accurate line renderer ?

I tried once implementing those CRAM writes flicker to test the ROM you made but didn't manage to get the exact pixel location upon CPU execution time. Anyway, if you made some new discoveries about VDP timings/specific events, I'm always interested

one thing I'm wondering for example is if changing the backdrop palette entry mid-line is immediately effective and, in general, when does the VDP exactly read or latch values from registers or from his V-RAM

AamirM
Very interested
Posts: 472
Joined: Mon Feb 18, 2008 8:23 am
Contact:

Post by AamirM » Tue Aug 19, 2008 3:12 pm

Hi,

@ Nemesis:

I remember you once told me about how your emulator works a while back on SonicRetro forums. Your idea is very interesting indeed. And no doubt it will be the most accurate when its finished. But as you said yourself, its very slow too (for now). I tried your preview release and it took me like fifteen minutes to get Sonic 1 started. But then again, I have a single core CPU where as your emu is optimized for multicore. And I think in about 4-5 years (maybe less) everybody will be running your emu at fullspeed so I don't see this as a problem. You are doing something different which is awesome.

As for Regen, I've always tried to achieve as much accuracy as I can while remaining as fast as I can using a scanline based execution. In future, I am thinking of writing a pixel-by-pixel VDP and cycle-by-cycle CPUs when and if I see its practical. It should be just as accurate as your model but maybe a little slower.
Nemesis wrote:....and in the time it took me to write that, you've already fixed the problem. :D
Yeah in less than 10 minutes :) . But coding is just a small part. The real part was where you and Eke told me how to fix this. Thats important.

stay safe,

AamirM

King Of Chaos
Very interested
Posts: 273
Joined: Fri Feb 29, 2008 8:12 pm
Location: United States

Post by King Of Chaos » Tue Aug 19, 2008 4:13 pm

Wow, good job Aamir! Thanks Nemesis and Eke for helping him fix it. ;)

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

Post by HardWareMan » Tue Aug 19, 2008 5:30 pm

@AamirM: Well, when we get the next release?

King Of Chaos
Very interested
Posts: 273
Joined: Fri Feb 29, 2008 8:12 pm
Location: United States

Post by King Of Chaos » Tue Aug 19, 2008 6:19 pm

Personally I can't wait, so I can turn the volume up and listen very carefully to the music. ;)

Locked