xkeropiの画面出力をGDKからSDLに置き換える(2) ソース解説
前回、xkeropiの画面出力をSDLにて行ったわけですが、今回はその改造箇所のソース解説になります。
まずは、SDLの初期化SDL_Init()について。オリジナルのxkeropiでは、サウンド出力のみをSDLで行っています。
コメントが文字化けしとるな。
今回は画面出力についてもSDLに行わせるので、SDL_Init()はx11/dswin.cからx11/winx68k.cppのmain()内に移動して、SDL_INIT_VIDEOを引数に追加します。その後SDL_SetVideoMode()でとりあえず800x600のウィンドウを設定。
まずは、SDLの初期化SDL_Init()について。オリジナルのxkeropiでは、サウンド出力のみをSDLで行っています。
コメントが文字化けしとるな。
--- xkeropi-20101107.org/x11/dswin.c 2010-11-07 06:22:50.000000000 -0800
+++ xkeropi-20101107/x11/dswin.c 2013-07-12 00:37:13.135048788 -0700
@@ -71,7 +71,6 @@
{
SDL_AudioSpec fmt;
DWORD samples;
- int rv;
// ??????????????
if (playing) {
@@ -95,13 +94,6 @@
audio_nextbuf = 0;
audio_event = 0;
- // ??????
- rv = SDL_Init(SDL_INIT_AUDIO);
- if (rv < 0) {
- audio_fd = -1;
- return FALSE;
- }
-
// ??????????????????????????????
bzero(&fmt, sizeof(fmt));
fmt.freq = rate;
今回は画面出力についてもSDLに行わせるので、SDL_Init()はx11/dswin.cからx11/winx68k.cppのmain()内に移動して、SDL_INIT_VIDEOを引数に追加します。その後SDL_SetVideoMode()でとりあえず800x600のウィンドウを設定。
--- xkeropi-20101107.org/x11/winx68k.cpp 2003-12-05 10:07:17.000000000 -0800
+++ xkeropi-20101107/x11/winx68k.cpp 2013-07-12 07:03:36.799561482 -0700
@@ -4,6 +4,7 @@
extern "C" {
#endif
+#include "SDL.h"
#include "common.h"
#include "fileio.h"
#include "timer.h"
@@ -93,9 +94,6 @@
GtkWidget *main_vbox;
GtkWidget *menubar;
GtkWidget *drawarea;
-extern GdkImage *surface;
-extern GdkPixmap *pixmap;
-extern GdkPixmap *splash_pixmap;
static void set_window_size(GtkWidget *);
static void set_icon_bitmap(GtkWidget *);
@@ -597,6 +595,7 @@
int
main(int argc, char *argv[])
{
+ int sdlaudio = -1;
if (set_modulepath(winx68k_dir, sizeof(winx68k_dir)))
return 1;
@@ -606,6 +605,22 @@
LoadConfig();
+#ifndef NOSOUND
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
+#endif
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ return 1;
+ }
+#ifndef NOSOUND
+ } else {
+ sdlaudio = 0;
+ }
+#endif
+ SDL_WM_SetCaption(APPNAME" SDL", NULL);
+ if (SDL_SetVideoMode(FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, 16, SDL_SWSURFACE) == NULL) {
+ return 1;
+ }
+
gtk_set_locale();
gtk_rc_add_default_file(".xkeropirc");
gtk_init(&argc, &argv);
@@ -693,7 +708,7 @@
MIDI_SetMimpiMap(Config.ToneMapFile); //ե ȿ
MIDI_EnableMimpiDef(Config.ToneMap);
- if (!DSound_Init(Config.SampleRate, Config.BufferSize)) {
+ if (sdlaudio == 0 && !DSound_Init(Config.SampleRate, Config.BufferSize)) {
if (Config.DSAlert)
fprintf(stderr, "Can't init sound.\n");
}
最後にx11/windraw.cの改造について。ミソはScrBufです。xkeropiはこれをフレームバッファのポインタとして操作するので、sdl_surface->pixelsをあらかじめ渡しておき、xkeropiがSDL側のバッファに対して描写するようにします。
ScrBufに0xffffを書き込んでいるのは今回入れたデバッグ用コードです。前回のスクリーンショットで、画面上部の白い帯が出力されているのはこれのせいです。本来はScrBuf操作時にLock/Unlockしないといけない気がしますが、ここ以外のScrBuf操作箇所にはまだLock/Unlockを入れていません。
最後がWinDraw_Draw()関数です。xkeropiが画面を書き換えた後にこの関数が呼ばれるようなので、ここが呼び出されたタイミングでSDL_UpdateRect()し、ScrBufバッファの更新内容を画面に描画します。
--- xkeropi-20101107.org/x11/windraw.c 2008-11-07 17:42:42.000000000 -0800
+++ xkeropi-20101107/x11/windraw.c 2013-07-12 06:53:32.255567816 -0700
@@ -25,6 +25,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include
#include "common.h"
#include "winx68k.h"
#include "winui.h"
@@ -241,6 +242,8 @@
GdkColormap *colormap;
GdkBitmap *mask;
+ SDL_Surface *sdl_surface;
+
WindowX = 768;
WindowY = 512;
@@ -263,22 +266,27 @@
return FALSE;
}
- /* 15 or 16 bppʳ ϥ ݡ ȳ */
- if (visual->depth != 15 && visual->depth != 16) {
- fprintf(stderr, "No support depth.\n");
- return FALSE;
- }
- WinDraw_Pal16R = visual->red_mask;
- WinDraw_Pal16G = visual->green_mask;
- WinDraw_Pal16B = visual->blue_mask;
-
- surface = gdk_image_new(GDK_IMAGE_FASTEST, visual, FULLSCREEN_WIDTH,
- FULLSCREEN_HEIGHT);
- if (surface == NULL) {
+ sdl_surface = SDL_GetVideoSurface();
+ if (sdl_surface == NULL) {
g_message("can't create surface.");
return 1;
}
- ScrBuf = (WORD *)(surface->mem);
+
+ WinDraw_Pal16R = sdl_surface->format->Rmask;
+ WinDraw_Pal16G = sdl_surface->format->Gmask;
+ WinDraw_Pal16B = sdl_surface->format->Bmask;
+
+ ScrBuf = (WORD *)sdl_surface->pixels;
+
+ SDL_LockSurface(sdl_surface);
+ {
+// printf("hoge\n");
+ int i;
+ for (i = 0; i < 80*100; i++) {
+ *(ScrBuf + i) = 0xffff;
+ }
+ }
+ SDL_UnlockSurface(sdl_surface);
pixmap = gdk_pixmap_new(drawarea->window,
FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT, visual->depth);
@@ -333,6 +341,10 @@
void FASTCALL
WinDraw_Draw(void)
{
+ SDL_Surface *sdl_surface;
+ sdl_surface = SDL_GetVideoSurface();
+ SDL_UpdateRect(sdl_surface, 0, 0, FULLSCREEN_WIDTH, FULLSCREEN_HEIGHT);
+
GtkWidget *w = (GtkWidget *)drawarea;
GdkDrawable *d = (GdkDrawable *)drawarea->window;
と、かなり足早ですが、ソース解説はここまで。
Comment
コメントの投稿
Trackback
http://hissorii.blog45.fc2.com/tb.php/211-38ddb62f