Hardware/emulator quirks

Discussion in 'Discussion & Q&A' started by Clownacy, Sep 10, 2015.

  1. AURORA☆FIELDS

    AURORA☆FIELDS the cute one here Member

    Joined:
    Oct 7, 2011
    Messages:
    737
    Location:
    Finlandia
    This is something relating to Clownacy's post earlier: As the VDP manual claims, DMA may fail if two conditions aren't met:
    • The destination address write must be a word write
    • The write must be from work RAM (no d0 move to VDP directly!)
    [​IMG]

    As Clownacy's post suggests, he found an occasional crash with the first condition not met. Well, it seems I have found a crash where the second condition was not met (the first wasn't initially either, but it got ruled out pretty quickly as not causing the bug). For some context: While working for a screen, we noticed something strange happening; random tiles appearing and the game eventually freezing, sometimes with the Z80 continuing to work, sometimes not. This screen used a lot of DMA's to update everything necessary. As it turns out, it occurs in a very specific routine, and after a lot of experimentation, loading the whole DMA command longword into RAM, and then loading it from RAM word by word fixed these issues. After further experimentation, only the last word was required to be written from RAM, as the manual suggests.

    What is strange about this, is that this bug only occured on my 88' (model series 98M) model 1 Japanese SEGA Mega Drive. My model 1 Genesis did not exhibit this behaviour. Similarly, changing the base game to write the entire command directly into VDP did also not trigger this bug at all. It looks as if this is an actual VDP bug at the very least with early revisions of Mega Drives, but it either needs very specific circumstances to trigger or it triggers only very occasionally.
     
    ProjectFM and maple_t like this.
  2. FireRat

    FireRat Well-Known Member Exiled

    Joined:
    Oct 31, 2009
    Messages:
    544
    That's... weird. If only works from RAM, and not CPU regs, does the crash still occur if you copy the final word from ROM? If copying from any "memory" IS what actually lets it work, it means doing so from SRAM/PRAM/WRAM/32xVRAM would also work...
     
  3. AURORA☆FIELDS

    AURORA☆FIELDS the cute one here Member

    Joined:
    Oct 7, 2011
    Messages:
    737
    Location:
    Finlandia
    Given the value is dynamic and I didn't write the code, I wouldn't be able to test it at any rate. I haven my doubts about it being able to work, but I can test some theory with other DMA transfers to see if loading from hardware registers suddenly break the system.
     
    MarkeyJester and FireRat like this.
  4. AURORA☆FIELDS

    AURORA☆FIELDS the cute one here Member

    Joined:
    Oct 7, 2011
    Messages:
    737
    Location:
    Finlandia
    Oh yay, double post! As it turns out, my Japanese model is even more broken! As we were testing Dual PCM FlexEd working on hardware, I re-found a bug that had us scratching our heads. Specifically, it looked like the vertical interrupt on Z80 was never, or very rarely, getting fired. It seemed to be rather random what would work even temporarily before it all crashed and burned. This is strange, because any other hardware we tested on, the bug was not present. We thought this was a special one-off bug in a very early version of the Mega Drive, but it could happen on other models, we are just not sure yet. Soon after, with pretty much random guess, I added a im 1 instruction to the code, and it... Worked! After many hours of playing about and thinking this would never work, that single instruction fixed it. Turns out, im 0 is different in some early Mega Drives. Even more funnily, I had set im to 1 earlier for testing... In the Z80 init code. It turns out, at least I think so, that doing a z80 reset actually resets im back to 0, the mode that is broken (or different?) in these early models. Who knew. So, the conclusion is, never ever forget to set im to 1 or 2 in your z80 sound drivers!
     
  5. GerbilSoft

    GerbilSoft RickRotate'd. Maintenance

    Joined:
    Jul 11, 2009
    Messages:
    22
    Z80 interrupt modes 0 and 2 are known to not be supported on Mega Drive (and I think Master System as well; they may have worked on SG-1000 and SC-3000).

    IM 1 is the simplest interrupt mode, and is not present on the 8080 that the Z80 was derived from. When in IM 1, and the Z80 receives an interrupt, it jumps to $0038. That's it. No special handling required, other than remembering to return from the ISR using the RETI instruction.

    IM 0 is the original interrupt mode found in the 8080. In IM 0, when an interrupt is generated by a device, the device must also place a one-byte instruction on the data bus. This instruction is usually an RST instruction, e.g. RST $38. Since the Mega Drive VDP doesn't do this, the Z80 ends up reading garbage data (68000 prefetch?) and executes a random instruction.

    IM 2, vectored interrupts, is another interrupt mode specific to the Z80. This mode is similar to IM 0 in that it requires the interrupting device to put a value on the data bus when interrupting the CPU. The data value here is the low 8 bits of the interrupt vector. The high 8 bits is located in the Z80's I register. Combine the two, and you get the address of the interrupt vector. The Z80 reads the 16-bit value at this address and jumps to that location. This is similar to the 68000's interrupt table, though it's relocatable. (68020 adds interrupt table relocation, but that isn't useful here.)

    Both IM 0 and IM 2 require the interrupting device to write a value to the data bus. That doesn't happen on Mega Drive, which is why they don't work properly.

    Reference: http://www.z80.info/1653.htm

    EDIT: Since you mentioned that later MDs worked fine with IM 0: It's entirely possible that a later version of the MD chipset places $FF (RST $38) on the Z80 data bus when an interrupt occurs. This would fix broken games, but only on newer systems. (This could also be the result of adding pull-up resistors to the Z80 data bus, maybe.)
     
    Last edited: Apr 16, 2019
  6. FireRat

    FireRat Well-Known Member Exiled

    Joined:
    Oct 31, 2009
    Messages:
    544
    Last edited: May 16, 2019
    ProjectFM and Tanman Tanner like this.
  7. ralakimus

    ralakimus pretty much a dead account Member

    Joined:
    Aug 26, 2013
    Messages:
    1,069
    Turns out, Regen's emulation of YM2612 timers is complete utter shite!

    I don't know the super specific details of why, but take this example for instance, when I compared it to Genesis Plus GX. I set Timer A to $3F0, and Timer B to $F0. On Regen, Timer B overflowed first, and did so pretty quickly. On Genesis Plus GX, it took a while, but Timer A overflowed first, which I believe is how it is supposed to behave on hardware. I have been told that in general, Timer B is supposed to be the slower timer out of the 2, but in other tests I have done, Timer B always came out first on Regen, and Timer A on GPGX.

    EDIT: More stuff. On hardware, it is actually possible for the Z80 to access the I/O registers and such through the 68k bank. I've managed to make it send a bus request to itself (which just makes it halt itself, kek) and also read the hardware version register. I can confirm at least that Exodus allows the bus request thing, but NOT the hardware register thing! Regen and Genesis Plus GX seem to emulate them as they should. Unsure about BlastEm and the rest for now.
     
    Last edited: Jun 26, 2019
    Misinko, Clownacy, ProjectFM and 2 others like this.
  8. ValleyBell

    ValleyBell Well-Known Member Member

    Joined:
    Dec 23, 2011
    Messages:
    156
    Assuming that the YM2612 runs with a clock of 7 670 454 Hz, dividing it by 144 we get the base rate for sample output and timer update: 53267 Hz

    Timer A updates every sample. The algorithm is:
    Code:
    timerA_rate_Hz = 53267 / (1024 - timerA_register)
    This allows a range of 52.02 Hz (register value $000) to 53267 Hz (register value $3FF)
    A value of $3F0 results in a rate of 3329 Hz.
    (trivia: The GEMS driver uses Timer A for DAC playback - usually with divider 5 (value $3FB) for a rate of 10653 Hz.)

    Timer B updates once every 16 samples. The algorithm is:
    Code:
    timerB_rate_Hz = 53267 / ((256 - timerB_register) * 16)
    This allows a range of 13.00 Hz (register value $00) to 3329 Hz (register value $FF)
    A value of $F0 results in a rate of 208 Hz.
    (trivia: Some SMPS Z80 games use Timer B with a value of $CB or $CD to get an approximate 60 Hz timing.)

    So yes, Timer A should expire sooner than Timer B.
    Getting either of those wrong should break a lot of games though.
     
  9. ralakimus

    ralakimus pretty much a dead account Member

    Joined:
    Aug 26, 2013
    Messages:
    1,069
    I just found out that the Timer B bug on Regen is already known.

    What seems to be happening is that the initial Timer B load is bugged. It does it fine when it comes time to reload the value, though. The forum post from the author seemed to indicate that it was going to be fixed, but that was from 2010, and if I did my research correctly, the last release of Regen was in 2009.
     
    Last edited: Jun 26, 2019
    Misinko, Clownacy and Ozaleto like this.
  10. AURORA☆FIELDS

    AURORA☆FIELDS the cute one here Member

    Joined:
    Oct 7, 2011
    Messages:
    737
    Location:
    Finlandia
    So, I've found an interesting thing regarding the 32X: It can break games for seemingly no reason. Now, this may not come as a surprise to anyone, 32X is not exactly known as a quality product. However, I found a very weird issue while testing a hack: Whenever you died at certain spots, with horizontal interrupts enabled, after the screen faded to black, the game would either:
    • Bring up the crash handler with completely nonsensical bug report. All registers were correct, the location shouldn't in practice have caused any issues, and yet some strange addresses were being accessed, causing a crash.
    • The CRAM or VRAM would get corrupted in some very grotesque ways, so badly that you couldn't really see what you were doing
    • The above happened but the game also crashed
    • The screen would turn completely blank or have some strange electrical interference-type shit going on
    • Rarely, the game would not crash, for seemingly no reason
    Me and Markey tracked it down to seemingly be caused by Dual PCM, if we changed some instructions around, or put certain limitations on Dual PCM (such as playing no samples), the crashing would not occur and it would work flawlessly. However, we found a.. "fix", and everything worked correctly. Later, after adding some code, the crashing happened again, with seemingly no reason whatsoever. Eventually, I tested on my Japanese console, and it worked, even after reverting all the changes, it kept working. I removed the 32X from my American console, and... It worked, again, flawlessly.

    In the end, I could never reproduce this crash without the 32X, and could reproduce it every time with the 32X. My conclusion is, in some very specific instances, 32X seems to be able to fuck up the 68k bus, VDP, or something else, which causes these strange effects to happen. Still have no clue what specifically is the issue, but the conclusion is clear: If you have unexplainable issues with your hack, test it without a 32X to make absolutely sure that is not the source of your problems

    I don't know if my 32X is broken, or something is going wrong with the interaction of my console, the 32X, and flashcart. I just wanted to warn everyone that this kind of thing is possible.
     
    ProjectFM and MarkeyJester like this.
  11. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,870
    I don't currently have my hardware setup, so I was unable to test if the same above issue occurs on my model, and if it's specific to the 32X or if it really is just something specifically wrong with her particular hardware, for example, the ribbon inside the 32X is notorious for coming loose, I'm wondering if this would be a contribution to the above issues.

    We could look at unscrewing the 32X, cleaning out the contacts to the ribbon and reinserting it again. I know mine were plugged in properly when I first got it, it was one of the first things I checked after acquiring it.
     
  12. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,870
    Double post...

    I've just tried on my 32X, with and without the metal brackets (just a thought), and I got no such issues. The flashcart itself could be accountable though.
     
  13. LazloPsylus

    LazloPsylus The Railgun The Railgun

    Joined:
    Nov 25, 2009
    Messages:
    Location:
    Academy City
    32x and/or flashcart, I'd surmise. 32x, due to generally finicky nature due to its rather cumbersome and problematic design and known faulting issue (ribbon cables being by far the most common, and could be in play here, as they are responsible for bridging the top and bottom segments, including when acting as a passthrough). Flashcart, due to a variety of known problems with popular flashcarts that can cause long-term damage to your units and themselves after extended use (Krikzz's love of 3V3 hardware without proper voltage translation come to mind...).

    Would take some extended diagnostics and probably some bench checking of the boards to confirm either/or.
     
    ProjectFM likes this.
  14. ralakimus

    ralakimus pretty much a dead account Member

    Joined:
    Aug 26, 2013
    Messages:
    1,069
    Since it has yet to be mentioned here, I'll go ahead and relay it here. Kega Fusion sucks at playing back 32X PWM audio. Here's a demonstration:

    Raw audio
    Hardware
    Gens (Win9x)
    Picodrive (on BizHawk)
    Kega Fusion

    As you can hear, the audio gets muffled a bit on Kega, especially on the quieter parts, unlike the other emulators and hardware (Also yeah, Picodrive's PWM playback is also a tad too slow).
     
  15. Nat The Porcupine

    Nat The Porcupine Well-Known Member Member

    Joined:
    Jun 23, 2017
    Messages:
    53
    Location:
    Pennsyltucky
    So unsurprisingly, across the emulationscape, not many emulators have support for the obscure Mega Mouse/Sega Mouse peripheral that just a few games in the Mega Drive library take advantage of. Of the popular choices for emulators these days, only BlastEM, Kega Fusion, & REGEN even give you the option for mouse input, and well... upon selecting it as an input in REGEN so you can play Wacky Worlds or the like, you may be shocked to find that the cursor goes flying into the upper-right corner of the screen without even touching the mouse & that attempting to move the mouse does nothing at all. What in the blue hell is going on here? Allow me to explain.

    I'm not going to go into the nitty-gritty of how mouse input is actually polled from the peripheral as it's a bit complicated & not necessarily pertinent to the emulation quirk we're talking about today; all you need to know is that, generally speaking, one nybble of data (4-bits/half a byte) is read at a time & assembled into a full 24-bit packet (usually stored in a data register as it is being constructed) that holds all the of the input information for the mouse at the moment it was polled. To make this simple, here's a map of sorts for what the packet looks like at the binary level assuming we are storing it as a long-word:

    [0- 0- 0- 0- | 0- 0- 0- 0- || Yo Xo Ys Xs | C- M- R- L- || X7 X6 X5 X4 | X3 X2 X1 X0 || Y7 Y6 Y5 Y4 | Y3 Y2 Y1 Y0]

    Let's break down what all of this means:
    Y7-Y0 - This byte stores the absolute value of y-axis movement
    X7-X0 - Likewise, this byte stores the absolute value of x-axis movement
    CMRL - These are the button inputs for the mouse, officially named Center, Middle, Right, & Left respectively (Center is also known more commonly as the start button, which is only present on the us version of the mouse)
    Ys/Xs - These flags communicate the sign (positive or negative) of the values by Y7-Y0 & X7-X0 repsectively
    Yo/Xo - These flags also tell us whether the values held by Y7-Y0 & X7-X0 have overflowed at all

    As you can imagine, the quirk with REGEN's emulation of mouse input centers around the way it treats the x & y movement bytes. You see, what official documention about the mouse means when it says these bytes of the packet store the "absolute values of movement" in a given direction is that these bytes store what can effectively be thought of as the mouse's current velocity; if I move the mouse to the left rather slowly, you could expect to see values like say -2 or -3 with the Xs flag set, while if I snap it back to the right quickly, you'll see higher values of maybe 7 to 10 with the Xs flag being cleared since we're now moving in the positive direction. And that makes sense, right? This isn't that different from how mouse input is read by computers too afaik because this approach is scalable; it doesn't lock you down to some set resolution & to try approach mouse input in a way that these were say... set axis coordinates, would be extremely stupid.

    But apparently not too stupid for REGEN.

    Yes everyone, you heard that right, REGEN treats those x & y axis movement bytes as, not the velocity of the mouse in either direction, but absolute screen coordinates that, in theory, the cursor is supposed to be at! WHY!? To make matters worse, when moving the mouse horizontally in the positive direction (aka right)& overflowing passed the value of 255, (because after all, we have a max horizontal resolution of 320px to work with), the value wraps around correctly but the Xo flag isn't set, so even if the mouse peripheral did somehow operate on some proprietary method of movement input compared to other mice of the era by calculating raw screen coordinates & sending that when polled, REGEN's code would still be wrong! How AamirM not only thought that this is how the mouse worked but also completely failed to test it to make sure it worked with any sort of official game that supported the mouse is completely beyond me, but one thing's for sure, REGEN doesn't really have support for it even though it's an input option.

    So... as to why the cursor flies into the upper right-hand corner of the screen when playing a mouse-input game of REGEN, it's a fairly simple explanation. Due to REGEN treating the x & y input bytes as screen coordinates, they are always going to be a positive value somewhere between 0-255, meaning the velocity that the game's mouse driver is interpreting can be a minimum of no velocity at all or a velocity so high that no human could possibly achieve it, and since getting a negative value of any kind is impossible, your cursor is destined to be stuck in the upper-right corner until you turn the game off. The astute among you may have asked "Well wait... shouldn't it be the lower-right corner instead? Positive Y movement should move the cursor down, not up." This is explainable due to one factoid I neglected to mention: Y-input on the mega mouse (and I believe mice in general, but don't quote me on that), at the raw level, is inverted compared to the direction of screen coordinates; pushing the mouse forward gives us positive values while pulling it back gives us negative values. While inverted y-input can be great for certain types of games (don't @ me), for moving a cursor around on screen to click on stuff, it feels... unnatural. As such, most games would negate the raw y input before applying it, causing us to end up in, you guessed it, the upper-right corner in REGEN.

    So yeah, that's how mouse input is broken on REGEN. I know this is a rather obscure quirk, but given that mouse input is the focus of my current project, I wanted to dive deeper into why this is so broken & boy did I find my answer.
     
    Last edited: Aug 28, 2020