Quote:
now I don't have to double post


Or maybe I do, meh.

Had a lot of trouble getting all games to detect the SGB hardware when using $6003.d5,d4 to determine 1-player/2-player/4-player mode for masking the joypad ID. Games like Shin Megami Tensei Devil Children were writing out MLT_REQ and then immediately reading the joypad ID. This gives the BIOS no time to react and update $6003.

So I'll keep being evil for now:
Code:
  if(packetlock) {
    if(p15 == 1 && p14 == 0) {
      if((joyp_packet[0] >> 3) == 0x11) {
        mmio.mlt_req = joyp_packet[1] & 3;
        if(mmio.mlt_req == 2) mmio.mlt_req = 3;
      }


Pull the MLT_REQ state right out of the packet once it completes. Technically no reason the hardware can't do this, although it'd be quite odd for it to use $6003 at all in that case.

I also set it to not increment until both the D-pad and buttons for each controller has been read out. I'm not entirely sure how that's supposed to work, but this works for all the games I'm aware of, so ... whatever.

This also eliminates the need for the strange 0xf - (joyp_id ^ 3) trick I was using to get past the SMT: DC SGB test.

Next, Zelda DX v1.0 and v1.1 had some sort of glitch. Compare v1.0:
Code:
MASK_EN
1,1
1,0
0,1
1,1
0,0 <- this starts a new packet transfer
1,0
0,1
1,1
1,0
0,1
1,1


With v1.2:
Code:
MASK_EN
1,1
1,0
0,1
1,1
1,0 <- and yet it's missing here
0,1
1,1
1,0
0,1
1,1


It's sending a packet start transfer of P15=0,P14=0 periodically. With my previous release, this would eventually spit out a PAL01 command that sets all colors to black, effectively "turning the screen off."

Given that there was a revision to fix this, I expect this bug existed on real hardware as well; but it was most certainly affected by the line hold time requirements.

pandocs states:
Quote:
Data and reset pulses must be kept LOW for at least 5us. P14 and P15 must be kept both HIGH for at least 15us between any pulses.


So probably it was getting all 1's (which is an invalid command, likely ignored) or 1's and 0's. The latter is easy, just disable the if(strobelock) return; line. Fixes Zelda DX.

The proper fix, which I'll work on for a later release, is likely to take the time a value has been set into account before acknowledging it and performing bus contention ORing and such.

One will also note the lack of 1,1 hold that pandocs requests between the 0,1 and 1,0; as that's obviously a joypad polling routine with an errant 0,0 write mixed in somewhere.

Next, audio. With stock SGB audio volume, the SNES sound effects are so quiet you can't even hear them. By dividing the SGB samples by 3, the two blend much better together.

To handle the downsample from 2147KHz to 32KHz, blargg provided a moving average downsampler, which is said to be superior to a 4-tap hermite filter for this kind of difference.

Code:
void Audio::coprocessor_sample(int16 left, int16 right) {
  if(r_frac >= 1.0) {
    r_frac -= 1.0;
    r_sum_l += left;
    r_sum_r += right;
    return;
  }

  r_sum_l += left  * r_frac;
  r_sum_r += right * r_frac;

  uint16 output_left  = sclamp<16>(int(r_sum_l / r_step));
  uint16 output_right = sclamp<16>(int(r_sum_r / r_step));

  double first = 1.0 - r_frac;
  r_sum_l = left  * first;
  r_sum_r = right * first;
  r_frac = r_step - first;

  //write to sound card / mixing buffer / whatever here
  //this is called @ 32KHz
  output_coprocessor_sample(output_left, output_right);
}


Lastly, I also added save state support. Stupid, but fun.

It might be easier to hook up libsupergameboy with Gambatte into MESS, and then work on merging over MESS' DMG core.