Previous Thread
Next Thread
Print Thread
Page 71 of 120 1 2 69 70 71 72 73 119 120
Joined: Jun 2008
Posts: 205
B
Senior Member
Offline
Senior Member
B
Joined: Jun 2008
Posts: 205
Fuck. It appears every SNES emulator gets ADC and SBC wrong in decimal mode. I've created hardware logs of every possible accumulator and status register result for every possible adc+sbc combination, and posted the details + logs here:
http://board.byuu.org/viewtopic.php?f=16&t=562

Anyone here feel like taking a crack at this? smile

byuu #59914 03/10/10 03:31 AM
Joined: Mar 2001
Posts: 16,834
Likes: 43
R
Very Senior Member
Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 16,834
Likes: 43
Interesting. Can you flag specific combinations that are wrong? I have a working Apple IIgs with a real WDC 65c816, it'd be interesting to see if this is an S-CPU specific thing.

Joined: Apr 2004
Posts: 1,555
J
Very Senior Member
Offline
Very Senior Member
J
Joined: Apr 2004
Posts: 1,555
Hm, perhaps a similar thing as with the NES cpu? That one also has some small differences when compared to a stock 6502.

On homebrew/translation patches: I tend to ignore bug reports on those until they've actually been tested and confirmed working on real hardware.

byuu #59934 03/10/10 03:52 PM
Joined: Jun 2009
Posts: 6
O
Member
Offline
Member
O
Joined: Jun 2009
Posts: 6
Originally Posted By byuu
The Genesis scene is the saddest. Kega Fusion, Regen and now Retrocopy. As if anyone even cares anymore, yet all the big-name Genesis emulators are as closed as could be.



I can't speak for Retrocopy, but Kega Fusion and Regen's authors are known for sharing info if you just ask. I'd say that's an acceptable compromise to the issue.

Joined: Jun 2008
Posts: 205
B
Senior Member
Offline
Senior Member
B
Joined: Jun 2008
Posts: 205
Quote:
Can you flag specific combinations that are wrong?


Sure, we'll start with one case and continue to fix them.

In this post:
http://board.byuu.org/viewtopic.php?f=16&t=562&p=12134#p12134

I have a standalone C99 (or C++98) app that will emulate only adc+sbc, and will iterate over my adc_sbc_test.zip archive files, telling you if you passed or failed.

First failure is in adc_0000-7fff-clc-sed-p. Failure is at 0x207a.

So given the code:
lda #$20; clc; sed; adc #$7a

My emulator gives: A=00, P=2F
Hardware gives: A=00, P=6F

The difference is that the overflow flag is set on hardware, but not under emulation.

It seems there's an entirely different algorithm for overflow calculation in decimal mode.

Quote:
I can't speak for Retrocopy, but Kega Fusion and Regen's authors are known for sharing info if you just ask. I'd say that's an acceptable compromise to the issue.


I have written extensively on this subject:
http://byuu.org/articles/licensing/

I'm very, very much in favor of giving an author full control of their own source code. I understand how insanely demotivating it is to compete with yourself (as would the MAME team with that one closed source fork), how it's not fair to put in a ton of work when nobody returns the favor but does take your ideas, and so on.

And I realize it's a philosophically hypocritical position for me to take, but I truly feel that emulation is different.

Writing the latest media player or video game, that's your creation. It's your design, and releasing the source to that I could care less about.

But writing an emulator is about recreating hardware. We have to realize that hardware does not last forever. Sega will never make another original Mega Drive. Maybe there will be some knockoff clones, maybe even official clones, but they will be hardware emulators just as the RetroDuo is.

Real hardware fails. Capacitors stop holding charges, transistors fry, circuitry fails. This hardware is already ~20 years old. It is becoming increasingly difficult to get hardware to run tests on.

I would posit that in 30 years from now, we won't be able to run hardware tests on the Genesis any longer. Anything we failed to emulate, any behavior we weren't sure about, once that last Genesis fails ... that's it. Game over. We'll never know how it really worked.

Thus, it is absolutely imperative, for the sake of properly documenting and archiving the hardware, that we get over our petty little egos and work together to our fullest extent to preserve the hardware while we still can.

I see it as absolutely tragic that childish popularity contests are holding back reverse engineering efforts in the emulation scene.

Sharing info when someone asks is great, but words are not source code, documentation is never equal to implementation, people are hesitant to pester someone for info all of the time, authors will become annoyed if pestered too much for info, etc. It is a negative environment.

Put another way, do you think Gens or Regen would be a better emulator if Kega were open source? If these authors are willing to share any info, then why not share the source, too?

byuu #59938 03/10/10 05:27 PM
Joined: Mar 2001
Posts: 16,834
Likes: 43
R
Very Senior Member
Offline
Very Senior Member
R
Joined: Mar 2001
Posts: 16,834
Likes: 43
More concisely, closed-source non-commercial emulators are a prime example of the free-rider problem, which tl;drs down to "they get to use the free guys' research for free, and we don't get to use theirs".

At this point, I think the advantages of open source for non-commercial emulation are obvious and nearly overwhelming. I bag on PCSX2 a lot for seemingly only caring about JRPGs, but it does do an impressive job emulating hardware of near-Saturn-level complexity with order of magnitude higher clocks. And Dolphin's been even more impressive, even if I think they're well into the gray area with Wii support. Outside of the Sega space[1], open source rules the roost.

[1] Which is super odd. Genesis, Sega CD, 32X, Saturn, Dreamcast, and Model 2 all have only closed-source reference emulators, although I think more MAMEdevs have ElSemi's Model 2 source than have up to date MAME trees.

Joined: Jun 2008
Posts: 205
B
Senior Member
Offline
Senior Member
B
Joined: Jun 2008
Posts: 205
Yes, free-rider is a big issue as well.

Okay, some more on ADC flags.

00+{00-79} sets V=0, with results of {00-79}
00+{7A-7F} sets V=1, with results of {80-85}
00+{80-FF} sets V=0, with results of {80-FF}

01+{00-78} sets V=0
01+{79-7F} sets V=1, with results of {80-86}
01+{80-FF} sets V=0

Very weird. I'm thinking that 7A is being "rounded" up to 80, and 80+ results set V; but then why doesn't 00+80 set it?

The window for overflow grows by one for each increment of the left-hand value.

---

So I think:

overflow = (A >= (0x7a - B)) && (A <= 0x7f);

Which works until 0x0b6f.

0B+6F: A=70, P=2C, V=0

byuu #59942 03/10/10 06:49 PM
Joined: Dec 2005
Posts: 443
Senior Member
Offline
Senior Member
Joined: Dec 2005
Posts: 443
byuu, could you test:

Code:
if(((~(i^j))&0x8)&((i^k)&0x8))
     set_overflow();


where i= the high nibble of the Accumulator, j = high nibble of the data, and k being the high nibble of the result. That bit of code was given to me many years ago by someone as "correct for known cases" at the time.

ETA: it at least should work for the 0x80+0 case, as well as the 7X cases.

Last edited by Heretical_One; 03/10/10 06:51 PM. Reason: reasoning
Joined: Jun 2008
Posts: 205
B
Senior Member
Offline
Senior Member
B
Joined: Jun 2008
Posts: 205
Okay, this code will pass for all possible combinations of:
lda #$xx; clc; sed; adc #$yy

Code:
void op_adc_b(uint8_t r0, uint8_t r1, uint8_t &a, uint8_t &p) {
  int r;
  if(decimal) {
    uint8_t n0 = (r0     ) & 15;
    uint8_t n1 = (r0 >> 4) & 15;
    n0 += (r1 & 15) + carry;
    if(n0 > 9) {
      n0 = (n0 - 10) & 15;
      n1++;
    }
    n1 += ((r1 >> 4) & 15);
    if(n1 > 9) {
      n1 = (n1 - 10) & 15;
      carry = 1;
    } else {
      carry = 0;
    }
    r = (n1 << 4) | n0;

    uint8_t L = r1 & 0x0f;
    uint8_t H = r1 & 0xf0;
    if((r1 & 0x80) == 0) {
      overflow = (r0 >= (0x7a - r1)) && (r0 <= 0x7f);
      if(L >= 0x0b && H <= 0x60) {
        uint8_t M = 0x6f - (H & 0x7f);
        if(r0 >= (M - (L - 0xb)) && r0 <= M) overflow = false;
      }
    } else {
      overflow = (r0 >= 0x80) && (r0 <= (0xf9 - (r1 - 0x80)));
      if(L >= 0x0b && H <= 0xe0) {
        uint8_t M = 0xef - (H & 0x7f);
        if(r0 >= (M - (L - 0xb)) && r0 <= M) overflow = true;
      }
    }
  } else {
    r = r0 + r1 + carry;
    carry = r > 0xff;
    overflow = ~(r0 ^ r1) & (r0 ^ r) & 0x80;
  }
  negative = r & 0x80;
  zero = (uint8_t)r == 0;

  a = r;
  p = 0x24 | (negative << 7) | (overflow << 6) | (decimal << 3) | (zero << 1) | (carry << 0);
}


Don't ask me why or how ...

Core part:
Code:
    uint8_t L = r1 & 0x0f;
    uint8_t H = r1 & 0xf0;
    if((r1 & 0x80) == 0) {
      overflow = (r0 >= (0x7a - r1)) && (r0 <= 0x7f);
      if(L >= 0x0b && H <= 0x60) {
        uint8_t M = 0x6f - (H & 0x7f);
        if(r0 >= (M - (L - 0xb)) && r0 <= M) overflow = false;
      }
    } else {
      overflow = (r0 >= 0x80) && (r0 <= (0xf9 - (r1 - 0x80)));
      if(L >= 0x0b && H <= 0xe0) {
        uint8_t M = 0xef - (H & 0x7f);
        if(r0 >= (M - (L - 0xb)) && r0 <= M) overflow = true;
      }
    }


---

This code fails the test: if(((~(i^j))&0x8)&((i^k)&0x8))

byuu #59944 03/10/10 07:07 PM
Joined: Apr 2004
Posts: 1,555
J
Very Senior Member
Offline
Very Senior Member
J
Joined: Apr 2004
Posts: 1,555
Looks like a bug in the cpu where it first does the decimal adjust which triggers a flip in the high bit and somehow interprets that as an overflow.

Edit:
hmmm, looking at regular 6502 ADC implementation (http://git.redump.net/cgit.cgi/mess/tree/src/emu/cpu/m6502/ops02.h#n312) it seems to give the results you're seeing....or am i missing something??

Last edited by judge; 03/10/10 07:14 PM.
Page 71 of 120 1 2 69 70 71 72 73 119 120

Link Copied to Clipboard
Who's Online Now
0 members (), 27 guests, and 2 robots.
Key: Admin, Global Mod, Mod
ShoutChat
Comment Guidelines: Do post respectful and insightful comments. Don't flame, hate, spam.
Forum Statistics
Forums9
Topics8,990
Posts118,128
Members5,005
Most Online890
Jan 17th, 2020
Forum Host
These forums are hosted by www.retrogamesformac.com
Forum hosted by www.retrogamesformac.com