Gambatte 0.5.0-wip2 released

Announce new emulators, discuss which games run best under each emulator, and much much more.

Moderator: General Mods

Post Reply
creaothceann
Seen it all
Posts: 2302
Joined: Mon Jan 03, 2005 5:04 pm
Location: Germany
Contact:

Post by creaothceann »

sinamas wrote:
creaothceann wrote:
sinamas wrote:As for the other warnings, I find that adding parentheses around expressions with (to me) obvious precedence tends to clutter up the code. Is it really too much to expect that programmers can be arsed to learn relatively basic operator precedence?
Sounds (to me) similar in spirit to "Real men don't need comments. It's all there in the code anyway, so why bother?"
IMO comments are useful for explaining stuff that can't be easily encoded in function declarations, variable names or similar, or stuff that looks wrong but is right. I know I'm pretty lazy on the comments though, and I could be better at doing stuff like moving pieces of code into their own appropriately named functions.

Operator precedence is easily learned as you use the operators. There is quite a limited amount of operators. Some operators may be seldomly used in certain kinds of code, but are used a lot for other kinds of code. It seems annoying to me to demand parentheses in short expressions in code heavy of such operators (kind of like having to parenthesize multiplies in more conventional pieces of code). I think it's reasonable to expect that the persons editing that kind of code would familiarize themselves with those operators. Granted, for long expressions doing a bit of grouping can aid readability (and I could probably be better at that), but I think whitespace serves that purpose better.

Now, I realize that a lot of these things depend on personal preference, so if the general consensus among programmers is that bitwise operators should always be parenthesized I may be willing to cave (at least it means I won't have to use -Wno-parentheses to avoid drowning in irrelevant warnings).
I guess it's something like this: For me there's no usefulness in operator precedences, so I dislike parantheses-less expressions because they force me to learn these rules.

There are languages that don't have operator precedences - without parantheses they just go through the expression from left to right, which is much easier IMO.
vSNES | Delphi 10 BPLs
bsnes launcher with recent files list
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

funkyass wrote:compilers don't warn about human readability issues with the source code its processing, they warn because its not sure if its processing the code correctly, so if something screws up later it at least warned you about it before hand.

-Wparentheses primarily deals with { and }, not ( and ) if I read the GCC docs correctly.
man gcc wrote:-Wparentheses
Warn if parentheses are omitted in certain contexts, such as when there is an assignment in a context where a truth value is expected, or when operators are nested whose precedence people often get confused about.
EDIT: Well, I'll probably end up complying with the warnings to stay on the safe side of things, assuming GCC has a good reason to assume that people are confused about these things. And if they're not confused to begin with, GCC will help make it so, since most people just edit their code to comply with the warnings.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

sinamas wrote: which could probably cause a pink screen on arhitectures where sizeof(long) != sizeof(int) and int isn't 16-bit (besides being strictly undefined), if you were using a YUV-based color format that is. If you were using XV on such an architecture this was probably the problem. Otherwise I haven't been able to reproduce it.
I use XV.

Code: Select all

X-Video Extension version 2.2
screen #0
  Adaptor #0: "NV17 Video Texture"
    number of ports: 32
    port base: 355
    operations supported: PutImage
    supported visuals:
      depth 24, visualID 0x21
      depth 24, visualID 0x24
      depth 24, visualID 0x25
      depth 24, visualID 0x26
      depth 24, visualID 0x27
      depth 24, visualID 0x28
      depth 24, visualID 0x29
      depth 24, visualID 0x2a
      depth 24, visualID 0x2b
      depth 24, visualID 0x2c
      depth 24, visualID 0x2d
      depth 24, visualID 0x2e
      depth 24, visualID 0x2f
      depth 24, visualID 0x30
      depth 24, visualID 0x31
      depth 24, visualID 0x32
      depth 24, visualID 0x33
      depth 24, visualID 0x34
      depth 24, visualID 0x35
      depth 24, visualID 0x36
      depth 24, visualID 0x37
      depth 24, visualID 0x38
      depth 24, visualID 0x39
      depth 24, visualID 0x3a
      depth 24, visualID 0x3b
      depth 24, visualID 0x3c
      depth 24, visualID 0x3d
      depth 24, visualID 0x3e
      depth 24, visualID 0x3f
      depth 24, visualID 0x40
      depth 24, visualID 0x41
      depth 24, visualID 0x42
      depth 24, visualID 0x43
      depth 24, visualID 0x44
      depth 24, visualID 0x45
      depth 24, visualID 0x46
      depth 24, visualID 0x47
      depth 24, visualID 0x48
      depth 24, visualID 0x49
      depth 24, visualID 0x4a
      depth 24, visualID 0x22
      depth 24, visualID 0x4b
      depth 24, visualID 0x4c
      depth 24, visualID 0x4d
      depth 24, visualID 0x4e
      depth 24, visualID 0x4f
      depth 24, visualID 0x50
      depth 24, visualID 0x51
      depth 24, visualID 0x52
      depth 24, visualID 0x53
      depth 24, visualID 0x54
      depth 24, visualID 0x55
      depth 24, visualID 0x56
      depth 24, visualID 0x57
      depth 24, visualID 0x58
      depth 24, visualID 0x59
      depth 24, visualID 0x5a
      depth 24, visualID 0x5b
      depth 24, visualID 0x5c
      depth 24, visualID 0x5d
      depth 24, visualID 0x5e
      depth 24, visualID 0x5f
      depth 24, visualID 0x60
      depth 24, visualID 0x61
      depth 24, visualID 0x62
      depth 24, visualID 0x63
      depth 24, visualID 0x64
      depth 24, visualID 0x65
      depth 24, visualID 0x66
      depth 24, visualID 0x67
      depth 24, visualID 0x68
      depth 24, visualID 0x69
      depth 24, visualID 0x6a
      depth 24, visualID 0x6b
      depth 24, visualID 0x6c
      depth 24, visualID 0x6d
      depth 24, visualID 0x6e
      depth 24, visualID 0x6f
      depth 24, visualID 0x70
      depth 24, visualID 0x71
    number of attributes: 3
      "XV_SET_DEFAULTS" (range 0 to 0)
              client settable attribute
      "XV_ITURBT_709" (range 0 to 1)
              client settable attribute
              client gettable attribute (current value is 0)
      "XV_SYNC_TO_VBLANK" (range 0 to 1)
              client settable attribute
              client gettable attribute (current value is 1)
    maximum XvImage size: 2046 x 2046
    Number of image formats: 4
      id: 0x32595559 (YUY2)
        guid: 59555932-0000-0010-8000-00aa00389b71
        bits per pixel: 16
        number of planes: 1
        type: YUV (packed)
      id: 0x32315659 (YV12)
        guid: 59563132-0000-0010-8000-00aa00389b71
        bits per pixel: 12
        number of planes: 3
        type: YUV (planar)
      id: 0x59565955 (UYVY)
        guid: 55595659-0000-0010-8000-00aa00389b71
        bits per pixel: 16
        number of planes: 1
        type: YUV (packed)
      id: 0x30323449 (I420)
        guid: 49343230-0000-0010-8000-00aa00389b71
        bits per pixel: 12
        number of planes: 3
        type: YUV (planar)
  Adaptor #1: "NV05 Video Blitter"
    number of ports: 32
    port base: 387
    operations supported: PutImage
    supported visuals:
      depth 24, visualID 0x21
      depth 24, visualID 0x24
      depth 24, visualID 0x25
      depth 24, visualID 0x26
      depth 24, visualID 0x27
      depth 24, visualID 0x28
      depth 24, visualID 0x29
      depth 24, visualID 0x2a
      depth 24, visualID 0x2b
      depth 24, visualID 0x2c
      depth 24, visualID 0x2d
      depth 24, visualID 0x2e
      depth 24, visualID 0x2f
      depth 24, visualID 0x30
      depth 24, visualID 0x31
      depth 24, visualID 0x32
      depth 24, visualID 0x33
      depth 24, visualID 0x34
      depth 24, visualID 0x35
      depth 24, visualID 0x36
      depth 24, visualID 0x37
      depth 24, visualID 0x38
      depth 24, visualID 0x39
      depth 24, visualID 0x3a
      depth 24, visualID 0x3b
      depth 24, visualID 0x3c
      depth 24, visualID 0x3d
      depth 24, visualID 0x3e
      depth 24, visualID 0x3f
      depth 24, visualID 0x40
      depth 24, visualID 0x41
      depth 24, visualID 0x42
      depth 24, visualID 0x43
      depth 24, visualID 0x44
      depth 24, visualID 0x45
      depth 24, visualID 0x46
      depth 24, visualID 0x47
      depth 24, visualID 0x48
      depth 24, visualID 0x49
      depth 24, visualID 0x4a
      depth 24, visualID 0x22
      depth 24, visualID 0x4b
      depth 24, visualID 0x4c
      depth 24, visualID 0x4d
      depth 24, visualID 0x4e
      depth 24, visualID 0x4f
      depth 24, visualID 0x50
      depth 24, visualID 0x51
      depth 24, visualID 0x52
      depth 24, visualID 0x53
      depth 24, visualID 0x54
      depth 24, visualID 0x55
      depth 24, visualID 0x56
      depth 24, visualID 0x57
      depth 24, visualID 0x58
      depth 24, visualID 0x59
      depth 24, visualID 0x5a
      depth 24, visualID 0x5b
      depth 24, visualID 0x5c
      depth 24, visualID 0x5d
      depth 24, visualID 0x5e
      depth 24, visualID 0x5f
      depth 24, visualID 0x60
      depth 24, visualID 0x61
      depth 24, visualID 0x62
      depth 24, visualID 0x63
      depth 24, visualID 0x64
      depth 24, visualID 0x65
      depth 24, visualID 0x66
      depth 24, visualID 0x67
      depth 24, visualID 0x68
      depth 24, visualID 0x69
      depth 24, visualID 0x6a
      depth 24, visualID 0x6b
      depth 24, visualID 0x6c
      depth 24, visualID 0x6d
      depth 24, visualID 0x6e
      depth 24, visualID 0x6f
      depth 24, visualID 0x70
      depth 24, visualID 0x71
    number of attributes: 2
      "XV_SET_DEFAULTS" (range 0 to 0)
              client settable attribute
      "XV_SYNC_TO_VBLANK" (range 0 to 1)
              client settable attribute
              client gettable attribute (current value is 0)
    maximum XvImage size: 2046 x 2046
    Number of image formats: 5
      id: 0x32595559 (YUY2)
        guid: 59555932-0000-0010-8000-00aa00389b71
        bits per pixel: 16
        number of planes: 1
        type: YUV (packed)
      id: 0x32315659 (YV12)
        guid: 59563132-0000-0010-8000-00aa00389b71
        bits per pixel: 12
        number of planes: 3
        type: YUV (planar)
      id: 0x59565955 (UYVY)
        guid: 55595659-0000-0010-8000-00aa00389b71
        bits per pixel: 16
        number of planes: 1
        type: YUV (packed)
      id: 0x30323449 (I420)
        guid: 49343230-0000-0010-8000-00aa00389b71
        bits per pixel: 12
        number of planes: 3
        type: YUV (planar)
      id: 0x3
        guid: 03000000-0000-0010-8000-00aa00389b71
        bits per pixel: 32
        number of planes: 1
        type: RGB (packed)
        depth: 24
        red, green, blue masks: 0xff0000, 0xff00, 0xff
NV17 had the issue, trying NV05, it worked fine.

Latest SVN, NV17 still fails.
sinamas wrote: As for the other warnings, I find that adding parentheses around expressions with (to me) obvious precedence tends to clutter up the code.
I find that not adding parentheses in many cases tends to trip up a lot of people, because some people find the order of operations counter intuitive.

Also way back in GCC 3.1 or so, I found that using -masm=intel could change the order of operations in a few cases, which drove me crazy, and I had to add parentheses to my code everywhere.
sinamas wrote: Is it really too much to expect that programmers can be arsed to learn relatively basic operator precedence?
Probably.

And the amount of times where I've seen people screw up on bit operators is too much to count.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
grinvader
ZSNES Shake Shake Prinny
Posts: 5632
Joined: Wed Jul 28, 2004 4:15 pm
Location: PAL50, dood !

Post by grinvader »

That's because the default order of operations is retarded.
The moron who decided the bit stuff should be below shifts, themselves below + or - should be executed for crime against everything that makes sense in this world.
皆黙って俺について来い!!

Code: Select all

<jmr> bsnes has the most accurate wiki page but it takes forever to load (or something)
Pantheon: Gideon Zhi | CaitSith2 | Nach | kode54
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

Nach wrote:
sinamas wrote: which could probably cause a pink screen on arhitectures where sizeof(long) != sizeof(int) and int isn't 16-bit (besides being strictly undefined), if you were using a YUV-based color format that is. If you were using XV on such an architecture this was probably the problem. Otherwise I haven't been able to reproduce it.
I use XV.

Code: Select all

*snip*
NV17 had the issue, trying NV05, it worked fine.

Latest SVN, NV17 still fails.
Since I haven't been able to find something that would break 64-bit UYVY by inspection (and I don't have a 64-bit system conveniently available at the moment), let's see if we can narrow this down a little.

Could you try this patch and see if it makes a difference? It basically reverts to a slower, simpler RGB32->UYVY algorithm.
64b_uyvy_test1.patch

If that worked, could you also try this one, which just disables caching in the original algorithm.
64b_uyvy_test2.patch

(Apply with "patch -sp0 < foo.patch" in the svn root directory.)

Make sure you remember to relink gambatte_qt after rebuilding libgambatte. It may also be worth testing with other compiler versions or lower optimization flags just in case there's a bug in GCC.
Nach wrote:Also way back in GCC 3.1 or so, I found that using -masm=intel could change the order of operations in a few cases, which drove me crazy, and I had to add parentheses to my code everywhere.
Sounds like a pretty nasty bug in GCC, unless your code depended on undefined behavior.
That said, I've added parentheses to all the parts that GCC complains about.

EDIT: corrected test2.patch link even though this issue appears to have been resolved.
Last edited by sinamas on Sun Jul 13, 2008 12:24 am, edited 1 time in total.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

sinamas wrote:
Nach wrote:
sinamas wrote: which could probably cause a pink screen on arhitectures where sizeof(long) != sizeof(int) and int isn't 16-bit (besides being strictly undefined), if you were using a YUV-based color format that is. If you were using XV on such an architecture this was probably the problem. Otherwise I haven't been able to reproduce it.
I use XV.

Code: Select all

*snip*
NV17 had the issue, trying NV05, it worked fine.

Latest SVN, NV17 still fails.
Since I haven't been able to find something that would break 64-bit UYVY by inspection (and I don't have a 64-bit system conveniently available at the moment), let's see if we can narrow this down a little.

Could you try this patch and see if it makes a difference? It basically reverts to a slower, simpler RGB32->UYVY algorithm.
64b_uyvy_test1.patch

If that worked, could you also try this one, which just disables caching in the original algorithm.
64b_uyvy_test2.patch

(Apply with "patch -sp0 < foo.patch" in the svn root directory.)

Make sure you remember to relink gambatte_qt after rebuilding libgambatte. It may also be worth testing with other compiler versions or lower optimization flags just in case there's a bug in GCC.
Well, latest SVN no longer has the issue. Perhaps all those parentheses did the trick.
sinamas wrote:
Nach wrote:Also way back in GCC 3.1 or so, I found that using -masm=intel could change the order of operations in a few cases, which drove me crazy, and I had to add parentheses to my code everywhere.
Sounds like a pretty nasty bug in GCC, unless your code depended on undefined behavior.
That said, I've added parentheses to all the parts that GCC complains about.
It was perfectly fine code, -masm=intel has never been perfect, and was especially broken in the early 3.x line.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

Nach wrote:Well, latest SVN no longer has the issue. Perhaps all those parentheses did the trick.
Brilliant. Then I suspect not only people, but even GCC itself, get(s) confused about these things.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

sinamas wrote: but even GCC itself, get(s) confused about these things.
Ha! :lol:


Have you gotten any of my e-mails? I found a slight bug in Joystick support in Windows. I'd appreciate if you can sign onto an IM client so we can discuss it.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

Sorry, I haven't seen your e-mails as I seldomly check that mail account. I've sent you an e-mail reply, but now I'm off to bed.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

I found another bug which we both share.

In the input dialog, we make the QLineEdit read only. In Windows, they show an input box is currently selected by showing a blinking cursor in it. Other OSs/Styles color the border of the box.

Basically, since we have it read only, in Windows, it's not possible to tell a box is selected. To remedy this, I make those input boxes rendered in a different style.

I put this in the constructor:

Code: Select all

setStyle(QStyleFactory::create("plastique"));
This however means you'll have to recompile your statically linkable Windows version to include the Plastique style.

It may also be possible to fix this situation using CSS, but I didn't look much into that option.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

Actually, I changed it to read/write a couple of months ago, when I revamped the input dialog, without any issues, since I catch almost all keyboard input anyway. Try the most recent SVN snapshot, or compile your own, to see it working (only tested in XP).

EDIT:
without any issues
It appears you can paste into it (and everything else the right click menu provides) though, which kind of sucks. setContextMenuPolicy(Qt::PreventContextMenu) takes care of that, but I can still middle click to paste under X11 (and other platforms can probably be configured to behave similarly). Maybe setting a validator will work... Aye, that appears to work nicely... except I can still paste into the ones that aren't cleared, damn it! There's always the textEdited signal, but this is getting pretty hacky. Using the textEdited signal seems to be sufficient by itself to prevent any kind of invalid editing though.

I ended up using the textEdited signal to prevent all edits, as well as replacing the context menu with one that only has applicable choices.
Nach
ZSNES Developer
ZSNES Developer
Posts: 3904
Joined: Tue Jul 27, 2004 10:54 pm
Location: Solar powered park bench
Contact:

Post by Nach »

We're probably best off setting readonly and using CSS to change the background color of it on focus. I haven't looked much into Qt's CSS engine though.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
franpa
Gecko snack
Posts: 2374
Joined: Sun Aug 21, 2005 11:06 am
Location: Australia, QLD
Contact:

Post by franpa »

Can a way to specify what sav file is used with a game? would make it easier when playing linked versions of the zelda oracle games.
Core i7 920 @ 2.66GHZ | ASUS P6T Motherboard | 8GB DDR3 1600 RAM | Gigabyte Geforce 760 4GB | Windows 10 Pro x64
TheManuel
New Member
Posts: 5
Joined: Thu Jul 24, 2008 1:48 pm

Command line parameters for Gambatte?

Post by TheManuel »

Hello.

I am interested in using Gambatte integrated into a front-end running in an arcade cabinet .
Can anybody point me to any existing builds of Gambatte for Windows that might support command line arguments?

Gambatte already supports launching the application with a game loaded from the command line but I can see no way of having it lauch in full screen and with the menu bar hidden.

If someone knows how to do this, please let know.

Thanks.
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

In between other things, I've been sporadically working on a fast audio resampler. As it's nearing completion, I'd like to share some of the things I've learned along the way, and some of the things one can do to achieve high performance.

Anyone who knows a bit about audio knows that audio is frequency domain information. Our ears only care about the frequency components of an audio signal, unlike our eyes which care about edges and lines in the space/time domain of an image.

This, of course, means that changing the sampling rate of an audio signal differs significantly from changing the resolution of an image (since we're preserving information in a different domain). Luckily, it also means that it's possible to losslessly recover the information in an audio signal from a vector of discrete amplitude samples in time, provided that one can assume that all frequency components that it represents are lower than half the sampling rate (so that they can be uniquely represented and identified).

Reducing sample rate by an integer factor n (decimation) basically amounts to filtering away frequencies above rate/2n and keeping every nth sample. Increasing sample rate by an integer factor n (interpolation) can basically be done be stuffing n-1 zeros between each sample and filtering away frequencies that are higher than the original rate/2.

(Zero stuffing introduces spectral images at multiples of the original sample rate solely because we're implicitly saying that the samples now may represent higher frequencies. That is, the output system would assume so. If you convert samples to analog infinitesimal amplitude spikes, there would be infinite spectral images at multiples of the sample rate, but if the output system knows the sample rate it can simply filter them away.)

The filtering used is usually convolution with a windowed sinc kernel.

To resample by arbitrary (or at least rational) factors there are two common approaches. One virtually converts the discrete sample-based signal into a continous signal (it only exists logically and is an approximation), filtered to only contain frequencies lower than the target rate/2, which is then sampled as if sampling a real continous signal. This is described here.

The other approach consists of virtual interpolation followed by decimation to change the sample rate by a rational factor. Virtual because it's logically combined into a single step without actually doing things like zero stuffing, and only computing samples that are actually kept. Since we know that only every nth virtual sample is non-zero, we can safely skip multiplying filter coefficients with the other ones, since they contribute zero anyway. This means that for each increase in input sample position, we skip n positions forward in the filter kernel. The initial position in the kernel depends on the output sample position, for a total of n possible phases. Fortunately it's easy to rearrange the filter kernel to be sorted by phase to improve locality of reference. This is called polyphase filtering and is covered pretty well in dspguru's Multirate DSP FAQ.

In general the polyphase approach allows a tighter inner loop, and better locality of reference, and thus higher performance. Another major performance factor is whether it's implemented using floating point or fixed point arithmetic. Even modern consumer grade CPUs are significantly faster at integer arithmetic than floating point. It's usually harder to do an implementation using fixed point arithmetic, because there are more considerations about overflow and accuracy that need to be done.

Most open source implementations I know of seem to be using the first apporach and floating point arithmetic, and as such end up being a lot slower than necessary (or desired for real time purposes). I did, however, stumble upon a good polyphase fixed point implementation, after having written my own. It's part of libavcodec. A simple comparison of it and libsamplerate can be seen here and here. I also found the prior and ensuing discussion there interesting. I bet a lot of projects would be better off using this rather than the more popular libsamplerate.

Anyway, my current polyphase implementation is about 40% faster than the libavcodec resampler according to my tests (using the exact same filter length, number of phases, ratio etc. so that's independent of quality), which means I'm doing pretty good I guess.

With this it's possible to change the sample rate of a signal directly, in one pass. But for large ratio changes this is far from ideal. For instance, say you want to decimate a signal from 2R to R, and you determine that you need to use a 64-tap windowed sinc filter to reach the quality that you want. Now suppose the original signal had a rate of 32R. To decimate this directly to R at equivalent quality you would need a 64*16 = 1024-tap filter, which can be pretty resource intensive as you may guess.

Fortunately there are ways around that. When you decimate a signal down to a rate higher than the final target rate, you end up with two frequency bands. The band that contains the frequencies we want to preserve and that are representable by the final rate, and a "don't care" band that contains higher frequencies that will be filtered away at a later stage anyway. This means that we can allow noise or aliasing in the "don't care" band. As such we can be less strict about filters used for intermediate decimation, and only gradually use higher quality filters as necessary while reducing the sample rate. The following illustration shows the two frequency bands and what will alias into which band upon decimating a signal at 4 times the final sample rate by 2. The distance between the final band and the band that will alias into it is equal to the length of the low pass filter roll off, which is inversely proportional to the number of taps needed in a windowed sinc filter.

Image

Taking this to an extreme is CIC filtering which can be used to very efficiently decimate (or interpolate) any rate down to between 4 and 8 times the final rate. A good description of CIC filtering can be found here.

The same principle can be applied in reverse for high ratio interpolation, and further to polyphase filtering of course. Finally, if you're resampling to a sample rate above 40 kHz, you get a "don't care" band for frequencies above 20 kHz that are inaudible to humans and as such can be abused for a longer filter roll-off.

That's it for today's lesson. A good, free, low requirements introduction book to DSP can be found at http://www.dspguide.com/.

EDIT: It appears that some not so uncommon desktop CPUs may be faster at floating point multiplication than integer multiplication. That's a bit inconvenient. But then there's conversion overhead, and integer additions which are faster.
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

New release.

The raw changelog is long enough that I almost decided not to release since it's too damn tiring to go through it all. Well, if you notice anything new, it's probably covered somewhere in the changelog. Despite my master-level selective laziness, a less intimidating list of some of the highlights follows. (Hopefully no one will notice that the following is the product of a random line selector run on the changelog.)

- WX register affecting PPU sprite timing.
- Lots of OAMDMA timing stuff, including bus conflicts with the CPU, PPU and H/GDMA.
- Cycle-accurate PPU sprite mapping reads.
- Fixed a bug where the unhalt event timer wasn't corrected on cycle counter reset which could cause games to freeze in an almost endless halt (cycle counter reset happens every few minutes).
- More accurate PPU tile loading / rendering pipelining behavior.
- Save states with OSD thumbnails, text etc.
- Real-time, sophisticated resampling framework with several performance/quality profiles for dynamically generated windowed sinc and CIC chains based on analysis of fourier transforms and optimal cost equations. Fast 2-tap linear as a low quality alternative.
- Lots of Mac OS X improvements, Core Audio, video mode switching.
- Multi-monitor support.
- Play menu with Pause, Frame Step, Dec/Inc/Reset Frame Rate.
- New and improved input dialog with many key mapping choices, alternate keys, etc.
- Direct3D9 video engine, with page flipping, triple buffering, vsync, device selection, etc.
- Separate Qt GUI/media framework code from Gambatte specific code.
- New audio/video timing model based on rate estimations in terms of OS timers.
- Custom sample rate and approximate buffer latency choice.
- Hq3x.
- Force DMG.
franpa
Gecko snack
Posts: 2374
Joined: Sun Aug 21, 2005 11:06 am
Location: Australia, QLD
Contact:

Post by franpa »

Where are gambatte settings stored on WindowsXP? "C:\Documents and Settings\%USER%\Application Data\gambatte"? I delete that yet Gambatte still remembers display options o_O.

Is it stored in the registry?

EDIT: HKEY_CURRENT_USER\Software\gambatte
Core i7 920 @ 2.66GHZ | ASUS P6T Motherboard | 8GB DDR3 1600 RAM | Gigabyte Geforce 760 4GB | Windows 10 Pro x64
DancemasterGlenn
Veteran
Posts: 637
Joined: Sat Apr 21, 2007 8:05 pm

Post by DancemasterGlenn »

Thanks for the release, it's great to see all of the work you've put into the project since 3.1. I'm actually blanking on where the linux settings are stored, personally... anyone?

A few things (entirely possible that I myself have brought one of these up in the past, so feel free to chastise me for not searching back). This is using the deb file (in ubuntu hardy).

- When I hide/show the menu with the escape key, sometimes my system freezes for a second or two. Not sure if this is just my system being odd.
- Sound doesn't seem to want to play nice with my system, point being that if I navigate away and scroll through my browser or whatnot, I get a lot of crackles. Sometimes these happen during gameplay as well. I've tried alsa and oss, a number of the filters, both sample rates, and buffering up to 800 ms. Might just not be playing nice with pulse?
- Did we already determine it wasn't a good idea for an option where one could use a gamepad to play even when the window wasn't in focus? I use that option a lot in bsnes and other emulators, but if it isn't feasable that's fine too.

That's all I've found so far, looks like a solid release. Thanks again, sinamas!

EDIT: have you thought about getting someone to make an icon for gambatte? I know I always use this image for my dock:
Image
A little messily edited, and since it's the real thing I'm under the impression it couldn't be used as an official icon anyway (correct?) but man, I loves me some yellow Game Boy Colors.
I bring the trouble.
franpa
Gecko snack
Posts: 2374
Joined: Sun Aug 21, 2005 11:06 am
Location: Australia, QLD
Contact:

Post by franpa »

randomly the video will sync to a different refresh other then 60hz, I don't know why it happens but it happens while playing Zelda OoA and the only way to get it to sync with 60hz again for a while is to restart the emu.
Core i7 920 @ 2.66GHZ | ASUS P6T Motherboard | 8GB DDR3 1600 RAM | Gigabyte Geforce 760 4GB | Windows 10 Pro x64
byuu

Post by byuu »

sinamas, your programming work is always a source of inspiration to me. My ultimate goal one day is to reach half the level you, blargg and others have already achieved.

Seriously, what you've done with the video cycle timing is nothing short of breath-taking. In truth, I never doubted your timing ideas. I spent two years trying to come up with a single routine like one of the dozens peppered throughout video.cpp to no avail. The reality is that I'm just not good enough to pull off the sort of magic that you do, and so I take the easy way out by completely sacrificing speed for simplicity.

For those afraid to dig into the code, here's a tiny example:

Code: Select all

bool LCD::cgbpAccessible(const unsigned long cycleCounter) {
	if (cycleCounter >= vEventQueue.top()->time())
		update(cycleCounter);

	bool accessible = true;

	if (enabled && lyCounter.ly() < 144) {
		const unsigned lineCycles = lyCounter.lineCycles(cycleCounter);

		if (lineCycles > 79U + doubleSpeed && lineCycles < 80U + 169U + doubleSpeed * 3U + m3ExtraCycles(lyCounter.ly()) + 4U - doubleSpeed * 2U)
			accessible = false;
	}

	return accessible;
}
For those not in the know ... this is the sort of code that allows one to remain cycle-accurate, without having to literally cycle-step everything at a tremendous impact to speed.

It's ridiculously easy to make one minor mistake in an algorithm like this and cause very subtle, difficult-to-debug timing problems. Yet sinamas includes literally hundreds of hardware test images along with his source distribution, proving the correctness of these algorithms.

And not surprisingly, I understood exactly nothing from your polyphase / CIC sampling post. Then again, I've never understood anything related to audio theory.

Looking at your work, it really does make my efforts seem silly in comparison. I'm convinced they will be superseded by a programmer with your talent level one day. Which is in no way a bad thing. I hope at least that my research will be of some value in the long-term.

That said, one thing is for certain -- the Gameboy hardware and internal operation will be well preserved in the future. Thank you for the new release.
franpa
Gecko snack
Posts: 2374
Joined: Sun Aug 21, 2005 11:06 am
Location: Australia, QLD
Contact:

Post by franpa »

The level 2 boss in Zelda OoA lags quite a lot too.
Core i7 920 @ 2.66GHZ | ASUS P6T Motherboard | 8GB DDR3 1600 RAM | Gigabyte Geforce 760 4GB | Windows 10 Pro x64
DOLLS (J) [!]
ZNES Developer
Posts: 215
Joined: Mon Aug 02, 2004 11:22 pm

Post by DOLLS (J) [!] »

sinamas wrote:Fast 2-tap linear as a low quality alternative.
Is this a total two taps in total or two taps on each side of the vertex of the tent?. I've been a little confused by the nomenclature used in some filters during my informal study of such. Having said that, would it make sense to disclose such information in the case of a two-taps in total linear filter, being that, as far as I'm aware, it would be impossible to do with fewer? (excluding edge cases).
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

byuu wrote:sinamas, your programming work is always a source of inspiration to me. My ultimate goal one day is to reach half the level you, blargg and others have already achieved.

Seriously, what you've done with the video cycle timing is nothing short of breath-taking. In truth, I never doubted your timing ideas. I spent two years trying to come up with a single routine like one of the dozens peppered throughout video.cpp to no avail. The reality is that I'm just not good enough to pull off the sort of magic that you do, and so I take the easy way out by completely sacrificing speed for simplicity.

For those afraid to dig into the code, here's a tiny example:
...
Looking at your work, it really does make my efforts seem silly in comparison. I'm convinced they will be superseded by a programmer with your talent level one day. Which is in no way a bad thing. I hope at least that my research will be of some value in the long-term.
Oh, come on, with all the awesomeness you've produced over the years, that's just not fair. You don't need to be even a little bit humble, byuu.

I'm actually not too happy with a lot of that code. Notice all the doubleSpeed stuff particularly. I'm pretty much completely unable to explain why many of those double speed dependent differences would occur.
byuu wrote:And not surprisingly, I understood exactly nothing from your polyphase / CIC sampling post. Then again, I've never understood anything related to audio theory.
The only one who responded to that one was blargg, which means that probably not many people did [understand], which may just be an indication of my lack of explanation skill. I think a lot of people expect audio theory to be quite different than it is, since most of us don't think of audio in terms of frequency spectra. Well, DSP is a big field with many complicated areas to have fun with. As long as one accepts that it's complicated and may take some time to understand well, I doubt you'd have too much trouble with it. Knowing some engineering math helps a bit though.
DancemasterGlenn wrote:Thanks for the release, it's great to see all of the work you've put into the project since 3.1. I'm actually blanking on where the linux settings are stored, personally... anyone?
~/.config/gambatte
These locations are really just Qt's defaults. I'm considering overriding at least the windows one to not use the registry.
DancemasterGlenn wrote:- When I hide/show the menu with the escape key, sometimes my system freezes for a second or two. Not sure if this is just my system being odd.
Haven't experienced that one. Well, except in Vista full screen with page flipping activated, but that's to be expected.
DancemasterGlenn wrote:- Sound doesn't seem to want to play nice with my system, point being that if I navigate away and scroll through my browser or whatnot, I get a lot of crackles. Sometimes these happen during gameplay as well. I've tried alsa and oss, a number of the filters, both sample rates, and buffering up to 800 ms. Might just not be playing nice with pulse?
Did you try using the "hw" device in alsa? If that works better it's probably related to pulseaudio. It's weird that higher buffer sizes don't help on the crackling. As long as you get reasonably good buffer status information from the sound driver, being closer to underrun than overflow before writing to the audio buffer causes gambatte to halve the video frame time until the situation gets better. Otherwise it waits close to an estimated frame time, based on the estimated rate of which the sound driver accepts samples, to get as smooth video as possible. If the OS scheduler doesn't give us CPU time frequently enough in contention with other processes underruns will happen. It's possible that the buffer status information from pulse is messed up. It worked well enough when I tried it on my system though. Perhaps it's time for a dedicated pulseaudio engine after all. Yet another audio API to support.
DancemasterGlenn wrote:- Did we already determine it wasn't a good idea for an option where one could use a gamepad to play even when the window wasn't in focus? I use that option a lot in bsnes and other emulators, but if it isn't feasable that's fine too.
Yet that would make it impossible/annoying to switch between two running applications that accept gamepad input. All other input methods depend on window focus, so I thought, why treat gamepads differently? Perhaps the liklyness of using two applications accepting gamepad input at the same time is low enough that it undermines the usefulness of such behavior.
DancemasterGlenn wrote:EDIT: have you thought about getting someone to make an icon for gambatte? I know I always use this image for my dock:
A little messily edited, and since it's the real thing I'm under the impression it couldn't be used as an official icon anyway (correct?) but man, I loves me some yellow Game Boy Colors.
Not very high on my list of priorities. I thought, better with no artwork than crappy artwork, which at least excludes me doing it. And, yes, using an actual image of a game boy probably isn't a very good idea.
franpa wrote:randomly the video will sync to a different refresh other then 60hz, I don't know why it happens but it happens while playing Zelda OoA and the only way to get it to sync with 60hz again for a while is to restart the emu.
There's probably little I can do. A lot of hardware/drivers have vsync issues all on their own. Sometimes you can get more stable behavior by enabling page flipping (only affects full screen). Vsync depends on the video driver being able to stably wait/block until the start of vblank each frame, and on getting a decent estimate of the current actual sample rate from the sound engine. Oh, and on the actual sample rate and refresh rate actually being reasonably close to the nominal value. For instance the windows video drivers on my laptop give me a 62.3 Hz refresh rate while reporting a nominal rate of 60 Hz, as well as missing vblank a lot unless page flipping is active.
DOLLS (J) [!] wrote:Is this a total two taps in total or two taps on each side of the vertex of the tent?. I've been a little confused by the nomenclature used in some filters during my informal study of such. Having said that, would it make sense to disclose such information in the case of a two-taps in total linear filter, being that, as far as I'm aware, it would be impossible to do with fewer? (excluding edge cases).
That's two taps in total and a triangular weighing function. All FIR filters can in fact be seen as being linear, which is why I chose to specify the number of taps in that one. The word linear is often used ambiguously.
byuu

Post by byuu »

I'm actually not too happy with a lot of that code.
It seems that happens to all of us who care about our work :/

The way you separated the core as its own stand-alone library was a really nice touch. The UI bindings in mine are far too tightly bound, and the cart / reader objects blur the line between core and UI.
Notice all the doubleSpeed stuff particularly. I'm pretty much completely unable to explain why many of those double speed dependent differences would occur.
Ah, yeah. I noticed some of those commented out. I was thinking it was a ROM memory speed at first, and then after seeing it used in cycle counting, I figured it was a CGB processor speed setting. I'm pretty clueless about the GB.

And yeah, when you start getting the extreme edge-case stuff down, the behavior never seems intuitive. I/O cycles turning into reads, weird pseudo-random delays before certain events trigger, etc etc.

Can't even explain what you're doing, because there's no logical reasoning for it from a hardware design stand-point.
As long as one accepts that it's complicated and may take some time to understand well, I doubt you'd have too much trouble with it. Knowing some engineering math helps a bit though.
The worst part ... with DSP stuff, I really can't hear any difference between linear, hermite and band-limited resampling. I only go with the mid-level quality method because I think it looks prettier in graph form x.x
And, yes, using an actual image of a game boy probably isn't a very good idea.
Take a page from blargg's S-SMP IPLROM assembler, and implement a tiny vector-art renderer, and generate a GBC-alike icon at runtime. Seems to be good enough to fool Debian licensing folk ;)
as well as missing vblank a lot unless page flipping is active.
Lousy drivers. Have you tried GetScanLineRasterPosition / GetRasterStatus / whatever in a tight loop? Eats up all your CPU time, but might be better at catching vblank transitions. And if you have any blank region at the bottom, you can eke out a little extra faux-vblank time.
sinamas
Gambatte Developer
Gambatte Developer
Posts: 157
Joined: Fri Oct 21, 2005 4:03 pm
Location: Norway

Post by sinamas »

byuu wrote:And yeah, when you start getting the extreme edge-case stuff down, the behavior never seems intuitive. I/O cycles turning into reads, weird pseudo-random delays before certain events trigger, etc etc.

Can't even explain what you're doing, because there's no logical reasoning for it from a hardware design stand-point.
Yeah, tell me about it!
byuu wrote:The worst part ... with DSP stuff, I really can't hear any difference between linear, hermite and band-limited resampling. I only go with the mid-level quality method because I think it looks prettier in graph form x.x
Try running gambatte at 8000 Hz and I'm sure you'll hear the difference. The difference at higher rates is less obvious but I can still easily hear it most of the time. But the case of resampling from ~2 MHz to ~44 kHz is much harder than the case of resampling from 32 kHz to ~44 kHz. Imagine that you have a perfect interpolation function. Meaning, given samples of an audio signal you could use it to perfectly reconstruct the underlying signal. Now if, and only if, this signal contains no frequencies higher than half the output sample rate, you could use this interpolation function to reconstruct the signal and sample it at the new sample rate to do perfect resampling. This naive approach depends on the interpolation function. Actually, you can use an interpolation function that results in a low-passed version of the original signal, and thus use a lower output sample rate. Anyway, a 2-tap or 4-tap FIR, linear or hermite/cubic, doesn't do a whole lot of low-passing, and otherwise deviates (introduces noise/frequencies, and in a way the deviation can actually be seen as not low-passing to the input rate, but let's not go there) a certain amount from the original signal. Generally the deviation is more problematic the lower the ratio of the input sample rate to the output sample rate, and the lack of low-passing is more problematic the higher the ratio of the input sample rate to the output sample rate. Now, in the case of going from 32 kHz to 44 kHz low-passing isn't an issue (well it is in a less naive perspective) so all that remains is how much the interpolation function distorts the signal. Perhaps a hermite function is good enough that the difference to proper resampling isn't very audible. In the case of going from 2 MHz to 44 kHz the lack of low-passing causes lots and lots of aliasing noise, and even more if you go from 2 MHz to 8 kHz.
byuu wrote:Lousy drivers. Have you tried GetScanLineRasterPosition / GetRasterStatus / whatever in a tight loop? Eats up all your CPU time, but might be better at catching vblank transitions. And if you have any blank region at the bottom, you can eke out a little extra faux-vblank time.
I haven't. It would mean yet another video engine option, but if it often works better it'd be well worth it.

EDIT: If you're testing at 8000 Hz, make sure you're not using something like ALSA's default resampling without plugins, which is just a 2-tap linear and sound shitty. Installing libasound2-plugins should fix it I think.
Last edited by sinamas on Tue Oct 28, 2008 7:32 pm, edited 1 time in total.
Post Reply