Best Genesis/Mega Drive emulator for DC?
- Juan
- DCEmu Commie
- Posts: 3398
- https://www.artistsworkshop.eu/meble-kuchenne-na-wymiar-warszawa-gdzie-zamowic/
- Joined: Sun Jun 15, 2003 11:47 pm
- Location: Montevideo
- Has thanked: 39 times
- Been thanked: 3 times
- Segata Sanshiro
- Psychotic DCEmu
- Posts: 686
- Joined: Thu Oct 23, 2003 3:23 pm
- Location: the future
- Has thanked: 0
- Been thanked: 0
- Contact:
I've got no problems with Wonderboy 6
But Wonderboy 5 use a custom SRAM technique (internal EEPROM), different than others roms so the genesis plus code need to be modified to disable sram reading/writing at initial rom detection (when detecting sram.custom)
i made the change in genesis plus gamecube's port and it worked well
but there will be no sram support for this game until you code a specific driver for the eeprom access (it has been made in kega for example)
But Wonderboy 5 use a custom SRAM technique (internal EEPROM), different than others roms so the genesis plus code need to be modified to disable sram reading/writing at initial rom detection (when detecting sram.custom)
i made the change in genesis plus gamecube's port and it worked well
but there will be no sram support for this game until you code a specific driver for the eeprom access (it has been made in kega for example)
-
- Insane DCEmu
- Posts: 126
- Joined: Wed Jan 10, 2007 11:56 am
- Has thanked: 0
- Been thanked: 0
TROUBLE WITH GPWT
Anyone having trouble with GPWT to run should try my new A-Z Tutorial under "Sega Genesis GPWT Newbie-Proof A-Z EASY Tutorial"
Be sure to use UNZIPPED ROMS!!!!
Be sure to use UNZIPPED ROMS!!!!
- Christuserloeser
- Moderator
- Posts: 5948
- Joined: Thu Aug 28, 2003 12:16 am
- Location: DCEvolution.net
- Has thanked: 10 times
- Been thanked: 0
- Contact:
Thanks a lot for sharing the info eke-ekeeke-eke wrote:I've got no problems with Wonderboy 6
But Wonderboy 5 use a custom SRAM technique (internal EEPROM), different than others roms so the genesis plus code need to be modified to disable sram reading/writing at initial rom detection (when detecting sram.custom)
i made the change in genesis plus gamecube's port and it worked well
but there will be no sram support for this game until you code a specific driver for the eeprom access (it has been made in kega for example)
It's not a problem to use zipped ROMsTechnoWolf wrote:Be sure to use UNZIPPED ROMS!!!!
Insane homebrew collector.
By the way, i finally discover why some games (Castle of Illusion, Quackshot ) didn't have in-game FM music. This occurs in each Genesis Plus port apparently (i was working on the Gamecube's port made by Softdev, see http://www.tehskeen.com/ ).
The problem was in the sound.c code, where it seems that Charles Mc Donald made a mistake in handling FM Timers A & B and inverted the status of the 2 timers, which are used in the "fm_status" returned when the program read the FM registers.
So the Z80 program (which was in charge of producing music) was kept in a loop, reading the bad timer and didn't send data to produce music. The correction I made solved this problem
For Genesis Plus ports devellopers, here are the (minor) changes I made in sound.c:
- in function fm_update_timers:
becomes
- in function fm_write:
become
I found the correct timer handling thanks to the YM2612 Programmer Guide which can be found here: http://www.smspower.org/maxim/docs/ym2612/index.html
Hope this will help to improve your awesome Dreamcast port
The problem was in the sound.c code, where it seems that Charles Mc Donald made a mistake in handling FM Timers A & B and inverted the status of the 2 timers, which are used in the "fm_status" returned when the program read the FM registers.
So the Z80 program (which was in charge of producing music) was kept in a loop, reading the bad timer and didn't send data to produce music. The correction I made solved this problem
For Genesis Plus ports devellopers, here are the (minor) changes I made in sound.c:
- in function fm_update_timers:
/* Set overflow flag (if flag setting is enabled) */
if(timer.enable)
{
fm_status |= (1 << i);
}
becomes
/* Set overflow flag (if flag setting is enabled) */
if(timer.enable)
{
fm_status |= (1 << (1-i));
}
- in function fm_write:
/* RESET */
if(data & 0x10) fm_status &= ~1;
if(data & 0x20) fm_status &= ~2;
become
/* RESET */
if(data & 0x10) fm_status &= ~2;
if(data & 0x20) fm_status &= ~1;
I found the correct timer handling thanks to the YM2612 Programmer Guide which can be found here: http://www.smspower.org/maxim/docs/ym2612/index.html
Hope this will help to improve your awesome Dreamcast port
eke-eke wrote:By the way, i finally discover why some games (Castle of Illusion, Quackshot ) didn't have in-game FM music. This occurs in each Genesis Plus port apparently (i was working on the Gamecube's port made by Softdev, see http://www.tehskeen.com/ ).
The problem was in the sound.c code, where it seems that Charles Mc Donald made a mistake in handling FM Timers A & B and inverted the status of the 2 timers, which are used in the "fm_status" returned when the program read the FM registers.
So the Z80 program (which was in charge of producing music) was kept in a loop, reading the bad timer and didn't send data to produce music. The correction I made solved this problem
For Genesis Plus ports devellopers, here are the (minor) changes I made in sound.c:
- in function fm_update_timers:/* Set overflow flag (if flag setting is enabled) */
if(timer.enable)
{
fm_status |= (1 << i);
}
becomes
/* Set overflow flag (if flag setting is enabled) */
if(timer.enable)
{
fm_status |= (1 << (1-i));
}
- in function fm_write:
/* RESET */
if(data & 0x10) fm_status &= ~1;
if(data & 0x20) fm_status &= ~2;
becomes
/* RESET */
if(data & 0x10) fm_status &= ~2;
if(data & 0x20) fm_status &= ~1;
I found the correct timer handling thanks to the YM2612 Programmer Guide which can be found here: http://www.smspower.org/maxim/docs/ym2612/index.html
Hope this will help to improve your awesome Dreamcast port
- Christuserloeser
- Moderator
- Posts: 5948
- Joined: Thu Aug 28, 2003 12:16 am
- Location: DCEvolution.net
- Has thanked: 10 times
- Been thanked: 0
- Contact:
In fact, i'm not pretty sure about what I did since in all emulator source code I've read, the FM read register is handled the same as Charles Mc Donald did
That is:
Perhaps it's rather an error in the documentation and the change I've made only works because of particular case
by the way, i managed to solve this problem in another way:
The result here is that, with games which previously don't have FM sound (Mickey, Quackshot, Wonderboy 3...):
- I see the FM out sound buffer be filled with data (no 0x00 as before)
- some games that previously hang (Undead Line for example) now run fine
I must discuss that with Charles McDonald or whoever have some interess in this but i'm pretty sure that the problems we had with those games came from FM timer not being handled properly.
Please note that I've only made test on the original DOS version (easier to compile & test) and that I can't produce any sound with this one (need DOSBOX or something like that, but I'm not good with those manipulation). I only check with debugging marks that the FM sound buffer at exit were filled with data other than 0x00 (which were not the case before) but I can't say if there is bug or not in music playback
i'll be glad if you could test my change on the DC port with those particular games
That is:
Code: Select all
bit 0 = Timer A overflow
bit 1 = Timer B overflow
by the way, i managed to solve this problem in another way:
This way, we let the mame FM core (fm.c) handle the timers and the FM status returned on read1/ don't call the function "fm_update_timers" in system.c
2/ in sound.c, make function "fm_read" return YM2612Read(0,address)
3 in fm.h, set FM_INTERNAL_TIMER to 1
The result here is that, with games which previously don't have FM sound (Mickey, Quackshot, Wonderboy 3...):
- I see the FM out sound buffer be filled with data (no 0x00 as before)
- some games that previously hang (Undead Line for example) now run fine
I must discuss that with Charles McDonald or whoever have some interess in this but i'm pretty sure that the problems we had with those games came from FM timer not being handled properly.
Please note that I've only made test on the original DOS version (easier to compile & test) and that I can't produce any sound with this one (need DOSBOX or something like that, but I'm not good with those manipulation). I only check with debugging marks that the FM sound buffer at exit were filled with data other than 0x00 (which were not the case before) but I can't say if there is bug or not in music playback
i'll be glad if you could test my change on the DC port with those particular games
- Christuserloeser
- Moderator
- Posts: 5948
- Joined: Thu Aug 28, 2003 12:16 am
- Location: DCEvolution.net
- Has thanked: 10 times
- Been thanked: 0
- Contact:
VDMSound is a nice tool and very easy to use:
http://www.borgeneration.com/tools.shtml
Also I've pmed BlackAura but he's very busy atm. Maybe you could try to compile the Dreamcast version yourself? Fackue compiled a nice package that should help you setting up a DC dev enviroment in Windows:
viewtopic.php?t=88526
GenesisPlusDC latest public version including Source code:
http://www.dcevolution.net/dsdevelopmen ... source.rar
Included MR logo:
http://www.borgeneration.com/tools.shtml
Also I've pmed BlackAura but he's very busy atm. Maybe you could try to compile the Dreamcast version yourself? Fackue compiled a nice package that should help you setting up a DC dev enviroment in Windows:
viewtopic.php?t=88526
GenesisPlusDC latest public version including Source code:
http://www.dcevolution.net/dsdevelopmen ... source.rar
Included MR logo:
Insane homebrew collector.
- Christuserloeser
- Moderator
- Posts: 5948
- Joined: Thu Aug 28, 2003 12:16 am
- Location: DCEvolution.net
- Has thanked: 10 times
- Been thanked: 0
- Contact:
- Quzar
- Dream Coder
- Posts: 7497
- Joined: Wed Jul 31, 2002 12:14 am
- Location: Miami, FL
- Has thanked: 4 times
- Been thanked: 9 times
- Contact:
I've been working on the DC port for quite a bit. I made these changes and sound still seems to be broken, at least in mickey (the only one of those games I have). Before making the changes, the sound simply isn't there, but afterwards it only works from time to time.
"When you post fewer lines of text than your signature, consider not posting at all." - A Wise Man
- Christuserloeser
- Moderator
- Posts: 5948
- Joined: Thu Aug 28, 2003 12:16 am
- Location: DCEvolution.net
- Has thanked: 10 times
- Been thanked: 0
- Contact:
I'll post my notes regarding things that I'd love to see implemented next:
- Updating to the newest FAME + FAZE versions
- Both have been released with the latest MAME4All update: http://chui.dcemu.co.uk/releases/mame4a ... rc.tar.bz2
Maybe the Z80 emulator could simply be 'bundled' with the CPU options at first (so one wouldn't need to rewrite the menu):BlackAura wrote:I also need to add a Z80 CPU switcher in - CZ80 is currently hard-coded in. It might be wise to put the old MAME Z80 emulator back, since CZ80 seems to cause rather a lot of games to stop working.
- C68k + MAMEZ80
- FAME + FAZE - 24khz sound emulation
FAZE/FAME should hopefully free enough CPU resources... I am having wet dreams over this... It however might probably be a good idea to keep the current low sample rate for the software renderer.
I hope this could be of help to increase the perfomance:
http://haze.mameworld.info/2006/08/11/hazemd-002a/ - It's a rewrite of the MAME/MESS drivers for MD/G emulation, source code is included. From what I've read it also has a completely rewritten sound driver. Might be really interesting to see if it's any better or faster than the current FM emulator in GenesisPlusDC.
I also found some interesting notes from BA and Stef D in this old thread here about optimizations in sound emulation, and regarding using an older MAME FM emulator (Stef mentioned MAME v0.35 or v0.36) instead of the one from Gens or newer MAME versions:
viewtopic.php?t=61992&postdays=0&postorder=asc&start=20
So I hope that - in combination with the new FAZE/FAME cores - either one of the older MAME sound divers or the rewritten one by Haze actually would allow 24 khz emulation. 24khz actually does sound significantly better than 22khz. If you keep in mind that at 44/48khz all drums and hihats sound off (too high pitched) - in about any existing MD/G emulator out there!, this would be pretty accurate and much better than anyone could ask for. - Auto-Frameskip for software renderer
...so it attempts to keep 60Hz/50Hz, depending on the region setting in GPDC.
This would enable games like Sailor Moon to be playable. - Auto-Single-Game-Boot-Feature
...so it skips the menu and goes straight to the game. - 4 player support
...for Mega Bomberman, Double Dribble, etc.
Insane homebrew collector.
- fox68k
- DC Developer
- Posts: 49
- Joined: Tue Aug 03, 2004 11:01 am
- Has thanked: 0
- Been thanked: 0
- Contact:
Keep in mind that the FAME source found in MAME4ALL is not suitable for GP. It should be generated properly to match GP requirements.Christuserloeser wrote:I'll post my notes regarding things that I'd love to see implemented next:
- Updating to the newest FAME + FAZE versions
- Both have been released with the latest MAME4All update: http://chui.dcemu.co.uk/releases/mame4a ... rc.tar.bz2
I would like to update the FAME package with the lastest generation sources. However, the new C version is keeping me from a new release since there it should be reviewed to support the full range of working options.
Anyway, i can post here the generation source along with some notes to help devs out.
Greetings.
- fox68k -
Finally, I managed to understand why this strange thing happened. In fact, debugging the Z80, I've noticed that it was kept in a loop, reading the FM Register.Quzar wrote:I've been working on the DC port for quite a bit. I made these changes and sound still seems to be broken, at least in mickey (the only one of those games I have). Before making the changes, the sound simply isn't there, but afterwards it only works from time to time.
Technically, on read, the emulator returns the FM status, which contains, in his 2 first bits, the status of the 2 FM timers , TimerA & Timer B (a bit set to 1 means that the Timer has overflowed). It seems also that those games made a lot of use of this to synchronise the Z80 and that the order of the bit in returned status is correct (apparently a mistake in documentation).
These timers are updated externally by Genesis Plus (at each frame to be precise, that means each 64us) and can be controlled by the Z80 or 68000 programm with FM writes.
So, Genesis Plus need to interprate this special write (YM2612 0x27 register, see Techncal Doc) in order to manage correctly the Timers and also the FM Status returned on Read. The available command are:
- Start or Stop TimerA or Timer B
- Enable or Disable Timer Overflow to set the FM status TimerA or TimerB flag
- Reset the FM status TimerA or TimerB flag
At this point, I made a test, letting the FM core (the MAME's one) managing the Timers and the FM status himself (set FM_INTERNAL_TIMER to 1 in fm.h and directly read status with YM2612Read) and noticed that sound playback was finally here, but unfortunately, the tempo was not good and some new games had problem with music playback that weren't before.
In fact, this was due to the way the FM core update the Timers value, which was not correct because it has no idea about the real emulator timings.
So, I came back to external timer, managed by Genesis Plus himself and finally found were the probleme was:
In fact, when it recognizes a FM register writing which want to start or stop a timer, Genesis Plus acted like this:
in funtion "fm_write", in sound.c
This is not correct because the timers count have to be reinitialized (set to 0) ONLY if the timer was not already started. Doing like this made the timers reset infinitely each time this register is writing with the LOAD bit set to 1 (which, in those games, the Z80 program effectively do each time it want to access this register and don't want to stop the timer)case 0x27: /* Timer Control */
/* LOAD */
timer[0].running = (data >> 0) & 1;
if(timer[0].running) timer[0].count = 0;
timer[1].running = (data >> 1) & 1;
if(timer[1].running) timer[1].count = 0;
So, I only changed the code like this:
case 0x27: /* Timer Control */
/* LOAD */
if(!timer[0].running && (data & 1 )) timer[0].count = 0;
timer[0].running = (data & 1);
if(!timer[1].running && (data & 2 )) timer[1].count = 0;
timer[1].running = (data & 2);
And with only this small modifiaction, now we have sound (please forget all the previous changes I gave in my last posts) !
By the way, It makes some other games which previously hangs (games were 68000 is waiting for the Z80, looping forever) to work fine (Undead Line for example).
Please note, that I also made some other modifications in sound.c that don't have so much repercussion but I thought it would be more correct like that:
- in function "fm_update_timers", don't stop the Timers when associated counter overflows.
- in function "sound_reset", add Timers and FM Status initialization:
I also replace in gen_reset() and system_reset() the call to YM2612Init() by the function above.void sound_reset(void)
{
if(snd.enabled)
{
YM2612ResetChip(0);
/* reset timers status */
timer[0].running = 0;
timer[1].running = 0;
timer[0].enable = 0;
timer[1].enable = 0;
timer[0].count = 0;
timer[1].count = 0;
timer[0].base = 0;
timer[1].base = 0;
/* reset FM status */
fm_status = 0;
}
}
I only made test on the Gamecube's Port but thanks to the link you gave in this topic, I will try to compile a DC version and see what happens
PS: GenPlus for Gamecube uses the last MAME Z80 and YM2612 cores for emulation, so there can be some difference, as BlackAura said
- Quzar
- Dream Coder
- Posts: 7497
- Joined: Wed Jul 31, 2002 12:14 am
- Location: Miami, FL
- Has thanked: 4 times
- Been thanked: 9 times
- Contact:
after all those changes it seems to work right now =). I guess that means my thing is now in alpha4 =P. The only thing I see as being off is the speed of the music, which seems to be extremely fast (although I havn't played CoI in a long time, only the second mickey game).
Thanks a bundle for sharing these findings with us.
Thanks a bundle for sharing these findings with us.
"When you post fewer lines of text than your signature, consider not posting at all." - A Wise Man
I think this is due to the sample rate used in the DC port (12000 ?), which is also used to init the genesis audio and the sound buffers. The Timer increment (64us at each scanline) only works for high sample rate (22500 and higher), I think.
As these timers are used by the Z80 program to synchronise his FM data writing, fast tempo means Z80 running too fast because of FM timers decrement to quickly.
To be more precise, if RATE is the sample rate of music playback, passed also to the audio_init() function, and if genesis is in 60Hz mode(by default in GP):
- we have to produce RATE samples per seconds and there are 60 frames per seconds => RATE/60 samples per frame, which actually determine the length of the sound buffers (sound buffer are updated after each frame)
- in 60Hz mode, we have 262 scanlines per frame, that means RATE/15720 average samples per scanlines (+/- 1)
So, if N < 15720, there are some scanlines where no samples have to te produced and some others where 1 sample is produced. The formula used in GenPlus to determine the total numbers of samples achieved at a specific scanlines is : (i * RATE)/15720 where i is the number of the scanline (between 0 and 261)
- FM sound buffers are the same size of the output sound buffers and are updated totally at the end of each frame but ALSO partially, each time the Z80 (or the 68000) access the FM register. The number of samples updated corresponds to the number of samples needed between the actual scanline and the previous one.
So, for example in our case, between 2 scanlines, we could have the timers incrementing by 64us and eventually one of the timer, readed by the Z80, finished his count. This unlock the Z80 which produce some new data BUT, as I said before, no samples needed to be updated between those 2 scanlines
=> the solution is to synchronise timers with sample rate rather than frame rate (or cpu clock), that means calculate the timer increment (added at each scanline) according to the number of the samples produced in this particular scanline.
- sound_tbl is the table which contains the number of achieved sample for each 262 scanline, in audio_init (see system.c), sound_tbl is initialized like this:
sound_tbl = ((i*RATE) / 15720) ---> {0, 0, 1, 2, 3, 3,... , 199} in our case
- the number of samples to be produced for scanline i is:
if i < 261: N = sound_tbl[i+1] - sound_tbl ---> 0 or 1 in our case
else N = (RATE/60) - sound_tbl ---> 1 in our case (last line)
- one sample must be produced each 1/RATE seconds = 1000000/RATE usec
So, in conclusion, the timer has to be incremented by:
inc = (N *1000000)/RATE microseconds
We only have to modified the "FM_Timer_Update" function to give in entry the increment and calculate it at the end of each scanline, before calling the function .
I hope I was clear enough and that I didn't made too much mistakes, but here's the idea and that's how it is implemented in Gens also I think
As these timers are used by the Z80 program to synchronise his FM data writing, fast tempo means Z80 running too fast because of FM timers decrement to quickly.
To be more precise, if RATE is the sample rate of music playback, passed also to the audio_init() function, and if genesis is in 60Hz mode(by default in GP):
- we have to produce RATE samples per seconds and there are 60 frames per seconds => RATE/60 samples per frame, which actually determine the length of the sound buffers (sound buffer are updated after each frame)
- in 60Hz mode, we have 262 scanlines per frame, that means RATE/15720 average samples per scanlines (+/- 1)
So, if N < 15720, there are some scanlines where no samples have to te produced and some others where 1 sample is produced. The formula used in GenPlus to determine the total numbers of samples achieved at a specific scanlines is : (i * RATE)/15720 where i is the number of the scanline (between 0 and 261)
- FM sound buffers are the same size of the output sound buffers and are updated totally at the end of each frame but ALSO partially, each time the Z80 (or the 68000) access the FM register. The number of samples updated corresponds to the number of samples needed between the actual scanline and the previous one.
So, for example in our case, between 2 scanlines, we could have the timers incrementing by 64us and eventually one of the timer, readed by the Z80, finished his count. This unlock the Z80 which produce some new data BUT, as I said before, no samples needed to be updated between those 2 scanlines
=> the solution is to synchronise timers with sample rate rather than frame rate (or cpu clock), that means calculate the timer increment (added at each scanline) according to the number of the samples produced in this particular scanline.
- sound_tbl is the table which contains the number of achieved sample for each 262 scanline, in audio_init (see system.c), sound_tbl is initialized like this:
sound_tbl = ((i*RATE) / 15720) ---> {0, 0, 1, 2, 3, 3,... , 199} in our case
- the number of samples to be produced for scanline i is:
if i < 261: N = sound_tbl[i+1] - sound_tbl ---> 0 or 1 in our case
else N = (RATE/60) - sound_tbl ---> 1 in our case (last line)
- one sample must be produced each 1/RATE seconds = 1000000/RATE usec
So, in conclusion, the timer has to be incremented by:
inc = (N *1000000)/RATE microseconds
We only have to modified the "FM_Timer_Update" function to give in entry the increment and calculate it at the end of each scanline, before calling the function .
I hope I was clear enough and that I didn't made too much mistakes, but here's the idea and that's how it is implemented in Gens also I think
- Christuserloeser
- Moderator
- Posts: 5948
- Joined: Thu Aug 28, 2003 12:16 am
- Location: DCEvolution.net
- Has thanked: 10 times
- Been thanked: 0
- Contact:
That would be great, Foxfox68k wrote:Keep in mind that the FAME source found in MAME4ALL is not suitable for GP. It should be generated properly to match GP requirements.Christuserloeser wrote:I'll post my notes regarding things that I'd love to see implemented next:
- Updating to the newest FAME + FAZE versions
- Both have been released with the latest MAME4All update: http://chui.dcemu.co.uk/releases/mame4a ... rc.tar.bz2
I would like to update the FAME package with the lastest generation sources. However, the new C version is keeping me from a new release since there it should be reviewed to support the full range of working options.
Anyway, i can post here the generation source along with some notes to help devs out.
Hm, I got a question regarding FAZE then: Do you think it would be save to implement FAZE from the MAME4ALL source into GenesisPlusDC ?
Thanks for all your work on FAME and FAZE!
Woohoo ! This sounds very promising and I can't wait to see ...er hear it implemented. Thanks a lot for contributing to GenesisPlusDC!eke-eke wrote:=> the solution is to synchronise timers with sample rate rather than frame rate (or cpu clock), that means calculate the timer increment (added at each scanline) according to the number of the samples produced in this particular scanline.
Insane homebrew collector.