So here's the version with HDMI support (only changed file is MegaVGA.spin2. The VSync pin field is repurposed when using HDMI mode: if it is odd, the TMDS pins are reversed. If you use the HDMI accessory, you don't want this. Just set VSync pin to zero). Currently only a 800x480 mode is defined. If you want to do a different mode, keep in mind that you can not touch the vertical timing and that you should keep the system clock around that 326 MHz sweet spot.
Will look into the regressions tomorrow. Also found that the worm at the beginning of Mega Turrican is invisible now for some reason. Rather strange.
Not sure what would be worse: bug in the HyperRAM implementation or bug in the previous fixes.
@Wuerfel_21 said:
Very fun with PropTool still not supporting preprocessing.
Not! Is there even a safe way to test for PropTool spin vs Flexspin environment that doesn't break PropTool compiles?
This is frustrating... I might be able to put a simple work-around in like having flexspin understand some special comments like {$if flexspin ...} to indicate flexspin only code. Would that help with your project, @Wuerfel_21 ?
Not really. The problem is selecting between different implementations for memory access, which I'd solve with an #ifdef, but proptool doesn't do it, so what I do instead is:
'{
Enabled code
'}{
Disabled code
'}
Along with labeling them all, that makes it not entirely infuriating to manage.
I think the solution here is to just pester Chip and/or Jeff more.
Agree. As someone who wants to support both platforms with my driver code without resorting to extreme methods like total duplication of files it would be nice to have some way to do this. Flexspin can use all the handy #if stuff and #include but PropTool cannot so if you try to use it you'll break PropTool. If we could even just have PropTool to recognize its own CON constants as a way to conditionally include/exclude some of the following lines being parsed, that at least would be a start. I know it quickly gets messy if there are multiple files or people then ask for nesting etc, but ideally we need something better than manually enabling/disabling various line groups all throughout the source files.
Agreed, having even a very basic preprocessor would be nice in PropTool. Having said that, there are a few work-arounds:
The ternary operator ? works in CON sections for both FlexProp and PropTool, so there's a little bit of configuration possible via that e.g.:
CON
USE_PSRAM = 1
PIN = USE_PSRAM ? 48 : 32
And of course plain IF statements in PUB/PRI can be used to disable code (although probably PropTool doesn't do dead code elimination yet, so you do get code bloat ).
With the most recent FlexSpin (still in github) you can test which compiler you're using via something like:
PUBmain(){$flexprop
' this stuff looks like code to FlexSpin
' but a comment to PNut / PropTool
DEBUG("hello from FlexSpin", 13)
' now start a PNut only section via #ifndef
#ifndef __FLEXSPIN__
}' this is only in PNut/PropTool' due to the #ifndef in the $flexprop comment above
DEBUG("hello from PNut", 13)
{$flexprop
' end the PNut only section
#endif
}
Figured out what the issue with Sonic 1 was. Apparently there's a bit of a non-bug where it tries to decompress level data from $0503BCF2. Real 68000 ingores the 8 unused bits at the top, but I was sending those out as part of the external RAM address. It seems the PSRAM chips have no problem with that, but the HyperRAM seems to return some sort of garbage.
That was definitely poor coding practises by such programmers back then. Sadly it was all too common. The 68k logical address space was always 32-bit, even if a particular model of processor didn't fully implement it.
The other decompression calls (for the SEGA logo, title screen, etc) are on more sensible addresses, so I guess it's really just an oversight.
Mind that they had this funny contraption called an "Address Checker" to make sure the games don't access invalid memory locations (beyond the ones that hang the machine due to missing DTACK)
But those top address bits aren't brought out, so they couldn't check those.
I just realized that there's a Bad Apple for Megadrive, which I guess means there is now a Bad Apple for P2, sortof. I remember @pik33 asked for that ;P
Alternate image title: I hate what the P2EVAL does to my desk.
Staying on subject, you may also play this IPS patch I found at one point while browsing romhacking.net, wherein someone imported Reimu's sprites from Scarlet Weather Rhapsody into Streets of Rage 2, which I find incredibly funny for some reason. Artstyle clash ahoy!
Time for another ZIP:
- Mask top bits of address on code read (fixes Vectorman on HyperRAM)
- Fix CMP instructions setting X (they shouldn't. Doesn't seem to fix any perceived issue)
- Increase VDP color ramp accuracy by precomputing shadowed/highlit colors
Taking advantage of the fact that MegaYume as a whole has a minimum clock frequency of around ~310 MHz whereas OPN2Cog was designed for 250 MHz, I've increased envelope generator update rate 6x (no more clicky attacks) and PSG sample rate 3x (less aliasing).
Going to also post a standalone OPN2Cog with those modifications (as well as the distortion thing from yesterday) in the relevant thread soon, too.
In unrelated news, despite having other things to do, the thought of a SNES sound board emulator won't leave my head, so, uhh, I guess I kinda wrote an SPC700 CPU core. It runs some contrived test code, but is likely super buggy still. As expected, the entire CPU fits into memory with loads of wiggle room (LUT mostly used, COG mostly free).
@Wuerfel_21 said:
… so, uhh, I guess I kinda wrote an SPC700 CPU core…
You are just amazing.
I get up in the morning and I think “I need to do laundry”.
You get up and write a whole new machine… finish it… and I’m still doing laundry. 🤣
News on the SNES sound board front: Trying to work out how the S-DSP works and how to efficiently implement it. Nothing to show for it yet, just prototyping bits and pieces.
In other words, welcome to my hell.
'' Update echo' Advance echo historymov dsp_ehist+0,dsp_ehist+1mov dsp_ehist+1,dsp_ehist+2mov dsp_ehist+2,dsp_ehist+3mov dsp_ehist+3,dsp_ehist+4mov dsp_ehist+4,dsp_ehist+5mov dsp_ehist+5,dsp_ehist+6mov dsp_ehist+6,dsp_ehist+7' Read echo data into historymovptrb,dsp_eptr
addptrb,sp_rambase
rdlong dsp_ehist+7,ptrbtestb dsp_ehist+7,#15wcbitc dsp_ehist+7,#16sar dsp_ehist+7,#1' Advance pointeradd dsp_eptr,#4zerox dsp_eptr,#15cmp dsp_eptr,dsp_ewrap wz' Reset pointer if end reachedif_zgetbyte dsp_eptr,dsp_dir_esa_edl,#1if_zshl dsp_eptr,#8if_zgetnib dsp_ewrap,dsp_dir_esa_edl,#4if_zshl dsp_ewrap,#11if_zfge dsp_ewrap,#4if_zadd dsp_ewrap,dsp_eptr
zerox dsp_ewrap,#15' run FIR filterscas dsp_efir+0,dsp_ehist+0mov dsp_tmp1,0-0getwordpa,dsp_ehist+0,#1scas dsp_efir+0,pamov dsp_tmp2,0-0scas dsp_efir+1,dsp_ehist+1add dsp_tmp1,0-0getwordpa,dsp_ehist+1,#1scas dsp_efir+1,paadd dsp_tmp2,0-0scas dsp_efir+2,dsp_ehist+2add dsp_tmp1,0-0getwordpa,dsp_ehist+2,#1scas dsp_efir+2,paadd dsp_tmp2,0-0scas dsp_efir+3,dsp_ehist+3add dsp_tmp1,0-0getwordpa,dsp_ehist+3,#1scas dsp_efir+3,paadd dsp_tmp2,0-0scas dsp_efir+4,dsp_ehist+4add dsp_tmp1,0-0getwordpa,dsp_ehist+4,#1scas dsp_efir+4,paadd dsp_tmp2,0-0scas dsp_efir+5,dsp_ehist+5add dsp_tmp1,0-0getwordpa,dsp_ehist+5,#1scas dsp_efir+5,paadd dsp_tmp2,0-0scas dsp_efir+6,dsp_ehist+6add dsp_tmp1,0-0getwordpa,dsp_ehist+6,#1scas dsp_efir+6,paadd dsp_tmp2,0-0' let taps 0..6 overflowsignx dsp_tmp1,#15signx dsp_tmp2,#15scas dsp_efir+7,dsp_ehist+7add dsp_tmp1,0-0getwordpa,dsp_ehist+7,#1scas dsp_efir+7,paadd dsp_tmp2,0-0' saturate last addfges dsp_tmp1,dsp_min
fges dsp_tmp2,dsp_min
fles dsp_tmp1,dsp_max
fles dsp_tmp2,dsp_max
'' TODO: add echo into main/feedback'' write echo datarolword dsp_recho,dsp_lecho,#0testbn dsp_flg,#5wc' Echo write enabled?if_cwrlong dsp_recho,ptrb' ptrb is still pointing to echo buffer
Further update still: BRR decode, interpolation, mixing and echo seem to function now, but no luck getting it to run anything that isn't my contrived test code. Likely issue with CPU (or with loading the dump file). Timer could be borked, too, idk.
No of course not, I am doing this on my Amiga that I don't have. ;P
I'm really hoping that you had an Amiga early in life. If you got the bug to emulate an Amiga on the P2, that would be awesome! I'm also hoping someone will do a C64 Emulator, which would be quite a bit earlier, but somehow doesn't preform that well on a Raspberry Pi Zero...
@pik33 said:
I hoped to try the emulator after attaching the 4-bit PSRAM to Eval, but not yet - 16 bit bus needed...
I should be able to get that going, though IDK how performance will be. Just need to get the P2EDGE back on my desk (currently have EVAL+HyperRAM set up, because that, due to a curious shortage of USB to barrel cables, is also the setup I need to test HDMI (I'm too retro to have any actual proper HDMI monitors, I guess.))
In the meantime, here's a preview of the SNES sound thing (obviously titled SPCcog, because stealing @Ahle2 's brand, lol)
Features:
- can sometimes play some music
Misfeatures:
- clicky attacks on some instruments (I think I have an idea what is causing that)
- some sort of memory corruption issue
- hates Seiken Densetsu 3
- was too lazy to edit out the LED debug stuff. Go find it yourself if you're not using a P2EVAL. Or don't, shouldn't matter if you aren't doing stuff with pins 56/57. Should be the only DRV* opcodes in the entire thing.
Yeah I guess if latency is still a major part, a single PSRAM with one quarter of the bandwidth isn't going to matter too much for small transfers. ie. Not a lot of difference between (a+b) and (a+4b) if a is bigger than b to begin with.
Comments
So here's the version with HDMI support (only changed file is
MegaVGA.spin2
. The VSync pin field is repurposed when using HDMI mode: if it is odd, the TMDS pins are reversed. If you use the HDMI accessory, you don't want this. Just set VSync pin to zero). Currently only a 800x480 mode is defined. If you want to do a different mode, keep in mind that you can not touch the vertical timing and that you should keep the system clock around that 326 MHz sweet spot.Will look into the regressions tomorrow. Also found that the worm at the beginning of Mega Turrican is invisible now for some reason. Rather strange.
Not sure what would be worse: bug in the HyperRAM implementation or bug in the previous fixes.
Also, @Electrodude , here's that github: https://github.com/IRQsome/MegaYume
Agree. As someone who wants to support both platforms with my driver code without resorting to extreme methods like total duplication of files it would be nice to have some way to do this. Flexspin can use all the handy #if stuff and #include but PropTool cannot so if you try to use it you'll break PropTool. If we could even just have PropTool to recognize its own CON constants as a way to conditionally include/exclude some of the following lines being parsed, that at least would be a start. I know it quickly gets messy if there are multiple files or people then ask for nesting etc, but ideally we need something better than manually enabling/disabling various line groups all throughout the source files.
Agreed, having even a very basic preprocessor would be nice in PropTool. Having said that, there are a few work-arounds:
The ternary operator ? works in CON sections for both FlexProp and PropTool, so there's a little bit of configuration possible via that e.g.:
CON USE_PSRAM = 1 PIN = USE_PSRAM ? 48 : 32
And of course plain IF statements in PUB/PRI can be used to disable code (although probably PropTool doesn't do dead code elimination yet, so you do get code bloat
).
With the most recent FlexSpin (still in github) you can test which compiler you're using via something like:
PUB main() {$flexprop ' this stuff looks like code to FlexSpin ' but a comment to PNut / PropTool DEBUG("hello from FlexSpin", 13) ' now start a PNut only section via #ifndef #ifndef __FLEXSPIN__ } ' this is only in PNut/PropTool ' due to the #ifndef in the $flexprop comment above DEBUG("hello from PNut", 13) {$flexprop ' end the PNut only section #endif }
Not exactly easy to read but at least it's something...
Figured out what the issue with Sonic 1 was. Apparently there's a bit of a non-bug where it tries to decompress level data from $0503BCF2. Real 68000 ingores the 8 unused bits at the top, but I was sending those out as part of the external RAM address. It seems the PSRAM chips have no problem with that, but the HyperRAM seems to return some sort of garbage.
Mega Turrican is also fixed by this.
That was definitely poor coding practises by such programmers back then. Sadly it was all too common. The 68k logical address space was always 32-bit, even if a particular model of processor didn't fully implement it.
The other decompression calls (for the SEGA logo, title screen, etc) are on more sensible addresses, so I guess it's really just an oversight.
Mind that they had this funny contraption called an "Address Checker" to make sure the games don't access invalid memory locations (beyond the ones that hang the machine due to missing DTACK)

But those top address bits aren't brought out, so they couldn't check those.
Much of it is intentional. Writes to ROM. Use of mirrored memory addresses. Size checks.
It was always a cat and mouse game, but if you can make a warehouse full of unauthorized hardware unsellable, you've at least won the current battle.
Yeah, there's a bunch of tricks done with backup RAM in particular. That will surely be fun.
Though that's got nothing to do with the 68000's 24 bit address bus.
Current objective: Add 6-button controller support.
Engineered to be crappy. So everyone ends up losing in the end.
Ok, 6-button support is in. I guess megayume is now Street Fighter 2 compliant ;P
Some games (particularly early/unlicensed ones) break with this, so there's a config constant to choose what kind of pad is emulated.
I just realized that there's a Bad Apple for Megadrive, which I guess means there is now a Bad Apple for P2, sortof. I remember @pik33 asked for that ;P
Alternate image title: I hate what the P2EVAL does to my desk.
Staying on subject, you may also play this IPS patch I found at one point while browsing romhacking.net, wherein someone imported Reimu's sprites from Scarlet Weather Rhapsody into Streets of Rage 2, which I find incredibly funny for some reason. Artstyle clash ahoy!
Time for another ZIP:
- Mask top bits of address on code read (fixes Vectorman on HyperRAM)
- Fix CMP instructions setting X (they shouldn't. Doesn't seem to fix any perceived issue)
- Increase VDP color ramp accuracy by precomputing shadowed/highlit colors
And here's another one that's been missing so far: Being able to hot-reset the emulator without reloading it.
Well, it's a thing now, CTRL+R
Megayume alpha 032:
Taking advantage of the fact that MegaYume as a whole has a minimum clock frequency of around ~310 MHz whereas OPN2Cog was designed for 250 MHz, I've increased envelope generator update rate 6x (no more clicky attacks) and PSG sample rate 3x (less aliasing).
Going to also post a standalone OPN2Cog with those modifications (as well as the distortion thing from yesterday) in the relevant thread soon, too.
In unrelated news, despite having other things to do, the thought of a SNES sound board emulator won't leave my head, so, uhh, I guess I kinda wrote an SPC700 CPU core. It runs some contrived test code, but is likely super buggy still. As expected, the entire CPU fits into memory with loads of wiggle room (LUT mostly used, COG mostly free).

You are just amazing.
I get up in the morning and I think “I need to do laundry”.
You get up and write a whole new machine… finish it… and I’m still doing laundry. 🤣
News on the SNES sound board front: Trying to work out how the S-DSP works and how to efficiently implement it. Nothing to show for it yet, just prototyping bits and pieces.
In other words, welcome to my hell.
'' Update echo ' Advance echo history mov dsp_ehist+0,dsp_ehist+1 mov dsp_ehist+1,dsp_ehist+2 mov dsp_ehist+2,dsp_ehist+3 mov dsp_ehist+3,dsp_ehist+4 mov dsp_ehist+4,dsp_ehist+5 mov dsp_ehist+5,dsp_ehist+6 mov dsp_ehist+6,dsp_ehist+7 ' Read echo data into history mov ptrb,dsp_eptr add ptrb,sp_rambase rdlong dsp_ehist+7,ptrb testb dsp_ehist+7,#15 wc bitc dsp_ehist+7,#16 sar dsp_ehist+7,#1 ' Advance pointer add dsp_eptr,#4 zerox dsp_eptr,#15 cmp dsp_eptr,dsp_ewrap wz ' Reset pointer if end reached if_z getbyte dsp_eptr,dsp_dir_esa_edl,#1 if_z shl dsp_eptr,#8 if_z getnib dsp_ewrap,dsp_dir_esa_edl,#4 if_z shl dsp_ewrap,#11 if_z fge dsp_ewrap,#4 if_z add dsp_ewrap,dsp_eptr zerox dsp_ewrap,#15 ' run FIR filter scas dsp_efir+0,dsp_ehist+0 mov dsp_tmp1,0-0 getword pa,dsp_ehist+0,#1 scas dsp_efir+0,pa mov dsp_tmp2,0-0 scas dsp_efir+1,dsp_ehist+1 add dsp_tmp1,0-0 getword pa,dsp_ehist+1,#1 scas dsp_efir+1,pa add dsp_tmp2,0-0 scas dsp_efir+2,dsp_ehist+2 add dsp_tmp1,0-0 getword pa,dsp_ehist+2,#1 scas dsp_efir+2,pa add dsp_tmp2,0-0 scas dsp_efir+3,dsp_ehist+3 add dsp_tmp1,0-0 getword pa,dsp_ehist+3,#1 scas dsp_efir+3,pa add dsp_tmp2,0-0 scas dsp_efir+4,dsp_ehist+4 add dsp_tmp1,0-0 getword pa,dsp_ehist+4,#1 scas dsp_efir+4,pa add dsp_tmp2,0-0 scas dsp_efir+5,dsp_ehist+5 add dsp_tmp1,0-0 getword pa,dsp_ehist+5,#1 scas dsp_efir+5,pa add dsp_tmp2,0-0 scas dsp_efir+6,dsp_ehist+6 add dsp_tmp1,0-0 getword pa,dsp_ehist+6,#1 scas dsp_efir+6,pa add dsp_tmp2,0-0 ' let taps 0..6 overflow signx dsp_tmp1,#15 signx dsp_tmp2,#15 scas dsp_efir+7,dsp_ehist+7 add dsp_tmp1,0-0 getword pa,dsp_ehist+7,#1 scas dsp_efir+7,pa add dsp_tmp2,0-0 ' saturate last add fges dsp_tmp1,dsp_min fges dsp_tmp2,dsp_min fles dsp_tmp1,dsp_max fles dsp_tmp2,dsp_max '' TODO: add echo into main/feedback '' write echo data rolword dsp_recho,dsp_lecho,#0 testbn dsp_flg,#5 wc ' Echo write enabled? if_c wrlong dsp_recho,ptrb ' ptrb is still pointing to echo buffer
Further update still: BRR decode, interpolation, mixing and echo seem to function now, but no luck getting it to run anything that isn't my contrived test code. Likely issue with CPU (or with loading the dump file). Timer could be borked, too, idk.
That is exactly the words I said out loud when reading her posts!
I'm really hoping that you had an Amiga early in life. If you got the bug to emulate an Amiga on the P2, that would be awesome! I'm also hoping someone will do a C64 Emulator, which would be quite a bit earlier, but somehow doesn't preform that well on a Raspberry Pi Zero...
I hoped to try the emulator after attaching the 4-bit PSRAM to Eval, but not yet - 16 bit bus needed...
I should be able to get that going, though IDK how performance will be. Just need to get the P2EDGE back on my desk (currently have EVAL+HyperRAM set up, because that, due to a curious shortage of USB to barrel cables, is also the setup I need to test HDMI (I'm too retro to have any actual proper HDMI monitors, I guess.))
In the meantime, here's a preview of the SNES sound thing (obviously titled SPCcog, because stealing @Ahle2 's brand, lol)
Features:
- can sometimes play some music
Misfeatures:
- clicky attacks on some instruments (I think I have an idea what is causing that)
- some sort of memory corruption issue
- hates Seiken Densetsu 3
- was too lazy to edit out the LED debug stuff. Go find it yourself if you're not using a P2EVAL. Or don't, shouldn't matter if you aren't doing stuff with pins 56/57. Should be the only DRV* opcodes in the entire thing.
@pik33
Here you go, ready for 4 bit PSRAM. Performance seems to be similar to HyperRAM.
That's cool if it still works ok with just the single PSRAM.
Yeah, it's neat. I think with reduced code que size it might go a bit faster still.
Yeah I guess if latency is still a major part, a single PSRAM with one quarter of the bandwidth isn't going to matter too much for small transfers. ie. Not a lot of difference between (a+b) and (a+4b) if a is bigger than b to begin with.