
Reviving a 19 Year Old Gameboy Emulator - superdisk
https://nickfa.ro/index.php?title=Reviving_a_19_Year_Old_Gameboy_Emulator
======
userbinator
_The first thing I noticed is that the sound output is going through this
convoluted 2-buffer system where it writes to one, and when it fills up,
switch to the other_

[https://en.wikipedia.org/wiki/Multiple_buffering](https://en.wikipedia.org/wiki/Multiple_buffering)

I've worked with some Windows audio code before and this is the norm --- while
it's playing one buffer, you write to the other one, and switch between the
two so the sound card gets an uninterrupted stream of data. In earlier
versions of Windows (3.x), the DMA on the sound card would read directly from
the buffer.

------
nothanksmydude
This is a _fantastic_ example of my favorite programming technique:

When nothing makes sense and you're real emotional about it and want to give
up... GIVE UP!*

*But you have to write another one from scratch tomorrow because there's good odds you'll do it right on accident and will then be able to diff and understand exactly where you went wrong. Being able to identify this situation and when doing this is useful as early as possible will make you very valuable. The break between attempts is important, go do literally anything else besides code.

I once spent a week going in literal circles because of some degree/radian
conversion errors. The rewrite took about 15 minutes.

Never trust anyone's ability to count, not even your own.

It's particularly useful in this exact situation, where the differences are
mere +'s and -'s, off by one here or there, maybe a bad copy paste with
similar looking variable names. Typically math related

~~~
vanderZwan
> going in _literal_ circles because of some degree/radian conversion errors

Hehe, nice.

And thanks for the tip! Retrying tomorrow is nothing new to me, but I never
thought to save yesterday's progress and diff it with the next day's rewrite
to figure out _why_ I was stuck.

~~~
nothanksmydude
It's especially useful when the changes are so small/subtle that you wouldn't
even catch them looking at commit history.

------
anyfoo
> I found (apparently) the only Gameboy emulator written in Pascal, ever: UGE.

Hmm, I don't know. If I've learned anything about programming languages, then
it's that the progression of programs written in them is usually: #1 Hello
World, #2 Factorial, #3 Gameboy Emulator.

~~~
Crinus
Yeah, i think his Google-fu skills need improvement, in another page he
mentions that there weren't any IRC clients in Pascal, but i remember at least
a couple of IRC libraries for Delphi (and personally i wrote an IRC component
in Delphi - you could drop the component on a form and drag-and-drop your way
on a simple IRC client, which i used at the time to make dedicated themed
clients for the communities i was into :-P).

------
Thorrez
Were all those errors observable back in 2000? It could be that compiler and
operating systems differences now are what caused/revealed some bugs. For
example the speed problem was probably much less back then due to slower
computers.

~~~
Crinus
Most likely. For example, this:

> passing in a member of a record rather than a pointer to that record... No
> idea why

...sounds like a difference in how the Windows API was exposed. In Delphi and
Free Pascal there are two ways to expose a C function that uses a pointer.
This:

    
    
        void Foo(int* ip);
    

can be exposed like this:

    
    
        procedure Foo(ip: PInteger); cdecl;
    

or like this:

    
    
        procedure Foo(var ip: Integer); cdecl;
    

The former allows you to pass any pointer to integer, the latter requires an
Integer variable reference (which is implemented by the compiler by passing a
pointer to the variable). The difference between the two is that you can pass
a Nil (Pascal's NULL) to the first, but the second requires a variable.

Older versions of Borland Pascal and Delphi (not sure about newer Delphi
versions) used the second declaration style where it made sense, but Free
Pascal uses a more direct translation of the Windows headers, opting for the
first declaration style.

My guess is that the compiler used by the original author of UGE used the
first style.

------
kevin_thibedeau
A bit sad that the emulator is running on a personal supercomputer and a
spinloop is the solution to slowing it down.

~~~
superdisk
If you have any other suggestion I'd like to hear it. Calling sleep or using
an OS timer isn't precise enough.

~~~
asveikau
What if you tally up the amount of delay you should have done, then when it
gets to a big enough granularity where a sleep call would actually give you
that amount, sleep.

Eg. Don't try to sleep accurately between the simulated cycles. Let things
happen "too fast" for longer and do the delays in batches.

Not sure if this would wind up perceivably too bursty. Just an idea based on
things I have seen in other domains.

For the record I don't think spinning is too bad of it's a very short
duration, shorter than the scheduler will give you when you take your thread
off the CPU.

~~~
superdisk
Sleep, at least on Windows, is allowed to have +/\- 15 ms (default system
heartbeat interval) of accuracy, which I don't think would work for this case.

[https://docs.microsoft.com/en-
us/windows/desktop/api/synchap...](https://docs.microsoft.com/en-
us/windows/desktop/api/synchapi/nf-synchapi-sleep)

I could mess around with the Win32 API or the NT API or something to make the
heartbeat rate more granular, but according to the docs that kills battery, so
I'm guessing it's going to be doing pretty much the same thing as what I'm
doing manually.

~~~
morcheeba
... that can still work. Measure how much time it actually slept and adjust
accordingly. Or, is there some timer that runs at a reasonable rate (100Hz)
where you csn yield once you've done 10msec worth of emulation? (I don't know
the windows API, so just spitballing from the embedded world here)

~~~
nothanksmydude
You seem like you appreciate good timers. If you ever want to revolt in
horror/have a few hearty belly laughs, look into how windows has and does
handle various granularities of timing

------
SmellyGeekBoy
I love the content but I also wanted to point out how much I enjoyed your
website design. Genuinely confused me for a second!

~~~
saagarjha
It's powered by MediaWiki. An interesting choice for a blog, though I guess it
gives you thinks like content management and update history for free…

------
jplayer01
I'd say the best part of this whole thing is that the original author even
made his code available. If he hadn't, we'd be stuck with another broken
implementation that nobody could fix or improve long after the author
abandoned the project.

