Porting an emulator

I have a PC emulator that uses SDL. I’m porting from 1.2 to 2 so that
the guest can have dual monitors. It’s kind of like VMWare I guess.
I went through the migration guide. I don’t think it really covered my
use case.

I have the GUI in a different thread from the emulator core, so there
needs to be some locking. With SDL 1.2 the screen surface was locked
as needed, but I gather we’re not supposed to use screen surfaces anymore.
There isn’t an SDL_LockWindow or SDL_LockRenderer. SDL_LockTexture exists,
but might be useless since I seem to need to destroy textures to resize.

The old code would take a lock, ask the emulator core to fill in some
raw pixel data and some update rectangles, then tell SDL to update each
rectangle. (the emulator tracks modified pixels) The emulator core needs
to know the stride; this isn’t available anymore because an SDL_Texture
is an opaque object.

So I have this update locking issue, and meanwhile there is the problem
of resizing. At any moment, the emulator core could inform me that the
video size has changed. Somebody has to realloc an array. It looks like
I need to destroy and then create a whole bunch of things; there is an
SDL_SetWindowSize but no SDL_SetTextureSize to go with it. There isn’t
an SDL_SetSurfaceSize either, FWIW.

BTW, the old code would poll the emulator core at 100 Hz to see if there
were any video updates. This probably isn’t the best, but it was an OK
compromise between latency and overhead. I hope SDL_UpdateWindowSurfaceRects
does nothing if numrects happens to be zero.

Looking toward the future, OpenGL support for the guest would be nice.
I’d kind of like to allow for that.

Oh, and a keyboard concern: the SDL_Scancode stuff is supposed to be
from the USB standard; it isn’t 100% clear if the exact same numbers
are used. I’d like to use them directly if possible.

You probably want to create a texture with format SDL_PIXELFORMAT_ARGB8888
and access SDL_TEXTUREACCESS_STREAMING, and then do something like this:

while (true) {
handle events
if ( size changed )
recreate streaming texture and your pixels and pitch
if ( pixels or size changed )
foreach changed rect:
SDL_UpdateTexture(texture, rect, pixels for rect, pitch);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer)
}

If you do rectangle coalescing, that will improve performance.

I’m also assuming that your pixels are ARGB format. If not, you can use a
different texture format and SDL will do optimized pixel conversion behind
the scenes.

The SDL scancodes and USB scancodes match up through 256.

It should be relatively easy to thunk through OpenGL calls from your
emulator to host OpenGL for almost native performance.

Cheers!On Tue, Feb 25, 2014 at 11:16 PM, Albert Cahalan wrote:

I have a PC emulator that uses SDL. I’m porting from 1.2 to 2 so that
the guest can have dual monitors. It’s kind of like VMWare I guess.
I went through the migration guide. I don’t think it really covered my
use case.

I have the GUI in a different thread from the emulator core, so there
needs to be some locking. With SDL 1.2 the screen surface was locked
as needed, but I gather we’re not supposed to use screen surfaces anymore.
There isn’t an SDL_LockWindow or SDL_LockRenderer. SDL_LockTexture exists,
but might be useless since I seem to need to destroy textures to resize.

The old code would take a lock, ask the emulator core to fill in some
raw pixel data and some update rectangles, then tell SDL to update each
rectangle. (the emulator tracks modified pixels) The emulator core needs
to know the stride; this isn’t available anymore because an SDL_Texture
is an opaque object.

So I have this update locking issue, and meanwhile there is the problem
of resizing. At any moment, the emulator core could inform me that the
video size has changed. Somebody has to realloc an array. It looks like
I need to destroy and then create a whole bunch of things; there is an
SDL_SetWindowSize but no SDL_SetTextureSize to go with it. There isn’t
an SDL_SetSurfaceSize either, FWIW.

BTW, the old code would poll the emulator core at 100 Hz to see if there
were any video updates. This probably isn’t the best, but it was an OK
compromise between latency and overhead. I hope
SDL_UpdateWindowSurfaceRects
does nothing if numrects happens to be zero.

Looking toward the future, OpenGL support for the guest would be nice.
I’d kind of like to allow for that.

Oh, and a keyboard concern: the SDL_Scancode stuff is supposed to be
from the USB standard; it isn’t 100% clear if the exact same numbers
are used. I’d like to use them directly if possible.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org