Changed method of storing WWLCDPanel data. (I made 1 byte allocated with 1 pixel as 1 byte with 2 pixels) (For speeding up, thought about future color correspondence (241 colors?)) Added WonxDisplay_Sync (). Reduced wasteful drawing in functions of get type. Implement sprite window function. (Not tested) Implement time related functions. (timer.c) Fix sprite priority. (I modified "Priority is given to younger one") Version 0.0.4 alpha - from wonx-a04.tar.gz
431 lines
14 KiB
C
431 lines
14 KiB
C
#include <stdio.h>
|
|
|
|
/*****************************************************************************/
|
|
/* ここから */
|
|
/*****************************************************************************/
|
|
|
|
#include "XDisplayP.h"
|
|
|
|
/*****************************************************************************/
|
|
/* メンバ関数の定義 */
|
|
/*****************************************************************************/
|
|
|
|
unsigned int XDisplay_GetKeyPress(XDisplay d) { return (d->key_press); }
|
|
int XDisplay_GetLCDDraw(XDisplay d) { return (d->lcd_draw); }
|
|
|
|
int XDisplay_GetColorMapPrint(XDisplay d) {return (d->color_map_print); }
|
|
int XDisplay_GetPalettePrint(XDisplay d) {return (d->palette_print); }
|
|
int XDisplay_GetCharacterPrint(XDisplay d) {return (d->character_print); }
|
|
int XDisplay_GetSpritePrint(XDisplay d) {return (d->sprite_print); }
|
|
|
|
int XDisplay_SetColorMapPrint(XDisplay d, int f)
|
|
{ return (d->color_map_print = f); }
|
|
int XDisplay_SetPalettePrint(XDisplay d, int f)
|
|
{ return (d->palette_print = f); }
|
|
int XDisplay_SetCharacterPrint(XDisplay d, int f)
|
|
{ return(d->character_print = f); }
|
|
int XDisplay_SetSpritePrint(XDisplay d, int f)
|
|
{ return (d->sprite_print = f); }
|
|
|
|
/*****************************************************************************/
|
|
/* 内部で使用する関数などの定義 */
|
|
/*****************************************************************************/
|
|
|
|
static XrmOptionDescRec options[] = {};
|
|
static Atom wm_delete_window;
|
|
|
|
static void die(Widget w)
|
|
{
|
|
kill(getpid(), SIGINT);
|
|
}
|
|
|
|
static void quit(Widget w, XEvent * event, String * params, Cardinal * num)
|
|
{
|
|
die(w);
|
|
}
|
|
|
|
static void wm_protocols_proc(Widget w, XEvent * event, String * params,
|
|
Cardinal * num)
|
|
{
|
|
if ((event->type == ClientMessage) &&
|
|
(event->xclient.data.l[0] != wm_delete_window)) {
|
|
XBell(XtDisplay(w), 0);
|
|
} else {
|
|
die(w);
|
|
}
|
|
}
|
|
|
|
static void iconify(Widget w, XEvent * event, String * params, Cardinal * num)
|
|
{
|
|
XIconifyWindow(XtDisplay(w), XtWindow(w), DefaultScreen(XtDisplay(w)));
|
|
}
|
|
|
|
static void pause(Widget w, XEvent * event, String * params, Cardinal * num)
|
|
{
|
|
sleep(3);
|
|
}
|
|
|
|
static XtActionsRec actions[] = {
|
|
{"quit", quit},
|
|
{"wm_protocols_proc", wm_protocols_proc},
|
|
{"iconify", iconify},
|
|
{"pause", pause}
|
|
};
|
|
|
|
static char * translations =
|
|
"<Message>WM_PROTOCOLS: wm_protocols_proc()\n"
|
|
"None<Key>p: pause()\n"
|
|
"Ctrl<Key>i: iconify()\n"
|
|
"Ctrl<Key>c: quit()\n"
|
|
"None<Key>q: quit()";
|
|
|
|
/*===========================================================================*/
|
|
/* 色名からピクセル値を取得する */
|
|
/*===========================================================================*/
|
|
|
|
static unsigned long XDisplay_GetPixelFromColorName(XDisplay x_display,
|
|
char * color_name)
|
|
{
|
|
XColor c0, c1;
|
|
XAllocNamedColor(x_display->display, x_display->colormap, color_name,
|
|
&c0, &c1);
|
|
return (c0.pixel);
|
|
}
|
|
|
|
/*===========================================================================*/
|
|
/* イベントハンドラ */
|
|
/*===========================================================================*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* キーの押下 */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void KeyHandler(Widget w, XtPointer p, XEvent * event,
|
|
Boolean * dispatch)
|
|
{
|
|
XDisplay x_display = (XDisplay)p;
|
|
KeySym key_sym;
|
|
int press = 0;
|
|
|
|
if ((event->type == KeyPress) || (event->type == KeyRelease)) {
|
|
|
|
key_sym = XKeycodeToKeysym(x_display->display, event->xkey.keycode, 0);
|
|
|
|
switch (key_sym) {
|
|
|
|
/* WonderSwan用 */
|
|
case XK_Up : press = KEY_UP1; break;
|
|
case XK_Right : press = KEY_RIGHT1; break;
|
|
case XK_Down : press = KEY_DOWN1; break;
|
|
case XK_Left : press = KEY_LEFT1; break;
|
|
case XK_i : press = KEY_UP2; break;
|
|
case XK_l : press = KEY_RIGHT2; break;
|
|
case XK_k : press = KEY_DOWN2; break;
|
|
case XK_j : press = KEY_LEFT2; break;
|
|
case XK_s : press = KEY_START; break;
|
|
case XK_space : press = KEY_A; break;
|
|
case XK_Shift_L : press = KEY_B; break;
|
|
default : press = 0; break;
|
|
}
|
|
|
|
/* Wonx 操作用 */
|
|
if (event->type == KeyPress) {
|
|
|
|
switch (key_sym) {
|
|
|
|
/* 表示モード変更 */
|
|
case XK_p : x_display->lcd_draw = !(x_display->lcd_draw); break;
|
|
|
|
/* データのダンプ操作 */
|
|
case XK_F1 : x_display->color_map_print = 1; break;
|
|
case XK_F2 : x_display->palette_print = 1; break;
|
|
case XK_F3 : x_display->character_print = 1; break;
|
|
case XK_F4 : x_display->sprite_print = 1; break;
|
|
}
|
|
}
|
|
|
|
if (press) {
|
|
if (event->type == KeyPress) x_display->key_press |= press;
|
|
else x_display->key_press &= ~press;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* イクスポーズ */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void ExposeHandler(Widget w, XtPointer p, XEvent * event,
|
|
Boolean * dispatch)
|
|
{
|
|
XDisplay x_display = (XDisplay)p;
|
|
|
|
XCopyArea(x_display->display, x_display->lcd_pixmap,
|
|
x_display->lcd_window, x_display->copy_gc,
|
|
0, 0, x_display->width, x_display->height, 0, 0);
|
|
return;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* マウスがウインドウを離れたら,キーを初期化する */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static void LeaveWindowHandler(Widget w, XtPointer p, XEvent * event,
|
|
Boolean * dispatch)
|
|
{
|
|
XDisplay x_display = (XDisplay)p;
|
|
x_display->key_press = 0;
|
|
return;
|
|
}
|
|
|
|
/*===========================================================================*/
|
|
/* オブジェクトの生成と消去 */
|
|
/*===========================================================================*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* オブジェクトの生成 */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
XDisplay XDisplay_Create(int width, int height)
|
|
{
|
|
XDisplay x_display;
|
|
int argc = 0;
|
|
char ** argv = NULL;
|
|
XColor color;
|
|
char * color_name[] = {"white", "gray84", "gray78", "gray72",
|
|
"gray66", "gray60", "gray54", "gray48",
|
|
"gray42", "gray36", "gray30", "gray24",
|
|
"gray18", "gray12", "gray6", "black"};
|
|
int i;
|
|
|
|
x_display = (XDisplay)malloc(sizeof(_XDisplay));
|
|
if (x_display == NULL) Error("XDisplay_Create", "Cannot allocate memory.");
|
|
|
|
x_display->width = width;
|
|
x_display->height = height;
|
|
|
|
x_display->toplevel = XtAppInitialize(&(x_display->app_context),
|
|
"Wonx",
|
|
NULL, 0, &argc, argv, NULL, NULL, 0);
|
|
|
|
XtVaSetValues(x_display->toplevel, XtNinput, True, NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNtitle, "Wonx", NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNwidth , x_display->width , NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNminWidth , x_display->width , NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNmaxWidth , x_display->width , NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNheight , x_display->height, NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNminHeight, x_display->height, NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNmaxHeight, x_display->height, NULL);
|
|
|
|
x_display->key_press = 0;
|
|
x_display->lcd_draw = 1;
|
|
|
|
XtRealizeWidget(x_display->toplevel);
|
|
while (!XtIsRealized(x_display->toplevel)) { /* None */ }
|
|
|
|
x_display->display = XtDisplay(x_display->toplevel);
|
|
x_display->root_window = DefaultRootWindow(x_display->display);
|
|
x_display->lcd_window = XtWindow(x_display->toplevel);
|
|
x_display->colormap = DefaultColormap(x_display->display,
|
|
DefaultScreen(x_display->display));
|
|
x_display->depth = DefaultDepth(x_display->display,
|
|
DefaultScreen(x_display->display));
|
|
|
|
x_display->lcd_pixmap = XCreatePixmap(x_display->display,
|
|
x_display->lcd_window,
|
|
x_display->width,
|
|
x_display->height,
|
|
x_display->depth);
|
|
|
|
x_display->copy_gc = XCreateGC(x_display->display, x_display->lcd_window,
|
|
0, 0);
|
|
XSetFunction(x_display->display, x_display->copy_gc, GXcopy);
|
|
|
|
for (i = 0; i < 16; i++) {
|
|
XParseColor(x_display->display, x_display->colormap,
|
|
color_name[i], &color); /* 色の名前 → RGB値*/
|
|
XAllocColor(x_display->display, x_display->colormap,
|
|
&color); /* 色を確保し,ピクセル値を得る */
|
|
x_display->color_gc[i] = XCreateGC(x_display->display,
|
|
x_display->lcd_window, 0, 0);
|
|
XSetForeground(x_display->display, x_display->color_gc[i], color.pixel);
|
|
XSetFunction(x_display->display, x_display->color_gc[i], GXcopy);
|
|
}
|
|
|
|
/* フォントの確保 */
|
|
x_display->font = XLoadFont(x_display->display, "8x16");
|
|
x_display->font_gc = XCreateGC(x_display->display,
|
|
x_display->lcd_window, 0, 0);
|
|
XSetFont(x_display->display, x_display->font_gc, x_display->font);
|
|
XSetFunction(x_display->display, x_display->font_gc, GXcopy);
|
|
XSetForeground(x_display->display, x_display->font_gc,
|
|
XDisplay_GetPixelFromColorName(x_display, "white"));
|
|
XSetBackground(x_display->display, x_display->font_gc,
|
|
XDisplay_GetPixelFromColorName(x_display, "black"));
|
|
|
|
XFillRectangle(x_display->display, x_display->lcd_window,
|
|
x_display->color_gc[0],
|
|
0, 0, x_display->width, x_display->height);
|
|
|
|
/* イベントハンドラの登録 */
|
|
XtAddEventHandler(x_display->toplevel, KeyPressMask | KeyReleaseMask,
|
|
False, KeyHandler, x_display);
|
|
XtAddEventHandler(x_display->toplevel, ExposureMask,
|
|
False, ExposeHandler, x_display);
|
|
XtAddEventHandler(x_display->toplevel, LeaveWindowMask | FocusChangeMask,
|
|
False, LeaveWindowHandler, x_display);
|
|
|
|
/* アイコンの設定 */
|
|
#if 0
|
|
XtVaSetValues(x_display->toplevel, XtNiconPixmap,
|
|
x_display->icon_pixmap, NULL);
|
|
XtVaSetValues(x_display->toplevel, XtNiconMask ,
|
|
x_display->icon_mask , NULL);
|
|
#endif
|
|
|
|
/* アクションの設定 */
|
|
XtAppAddActions(x_display->app_context, actions, XtNumber(actions));
|
|
|
|
/* トランスレーションの設定 */
|
|
XtOverrideTranslations(x_display->toplevel,
|
|
XtParseTranslationTable(translations));
|
|
|
|
/* ウィンドウマネージャからの f.delete への対応 */
|
|
wm_delete_window = XInternAtom(x_display->display,
|
|
"WM_DELETE_WINDOW", False);
|
|
XSetWMProtocols(x_display->display, x_display->lcd_window,
|
|
&wm_delete_window, 1);
|
|
|
|
/* Xサーバと同期をとる */
|
|
/* True だと,イベントキュー内のイベントを廃棄する */
|
|
XSync(x_display->display, True);
|
|
|
|
return (x_display);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* オブジェクトの消去 */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
XDisplay XDisplay_Destroy(XDisplay x_display)
|
|
{
|
|
int i;
|
|
|
|
if (x_display == NULL) return (NULL);
|
|
|
|
/* あとでリソースの解放を追加すること */
|
|
if (x_display->color_gc != NULL) {
|
|
for (i = 0; i < 16; i++) {
|
|
if (x_display->color_gc[i])
|
|
XFreeGC(x_display->display, x_display->color_gc[i]);
|
|
x_display->color_gc[i] = 0;
|
|
}
|
|
}
|
|
|
|
free(x_display);
|
|
|
|
return (NULL);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Xサーバとの同期 */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
int XDisplay_Sync(XDisplay x_display)
|
|
{
|
|
XEvent event;
|
|
|
|
XFlush(x_display->display);
|
|
|
|
/* Xサーバと同期をとる */
|
|
/* False だと,イベントキュー内のイベントを廃棄しない */
|
|
XSync(x_display->display, False);
|
|
|
|
/* イベントの処理 */
|
|
while (XtAppPending(x_display->app_context)) {
|
|
XtAppNextEvent(x_display->app_context, &event);
|
|
XtDispatchEvent(&event);
|
|
}
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* 描画 */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
int XDisplay_DrawLCDWindow(XDisplay x_display, WWLCDPanel ww_lcd_panel)
|
|
{
|
|
int x, y, n;
|
|
int px, py;
|
|
int num;
|
|
XRectangle * rectangles;
|
|
int pixel;
|
|
int ww_lcd_width, ww_lcd_height;
|
|
|
|
num =
|
|
WWLCDPanel_GetHeight(ww_lcd_panel) * WWLCDPanel_GetWidth(ww_lcd_panel);
|
|
rectangles = (XRectangle *)malloc(sizeof(XRectangle) * num);
|
|
if (rectangles == NULL)
|
|
Error("XDisplay_DrawLCDWindow", "Cannot allocate memory.");
|
|
|
|
ww_lcd_width = WWLCDPanel_GetWidth( ww_lcd_panel);
|
|
ww_lcd_height = WWLCDPanel_GetHeight(ww_lcd_panel);
|
|
|
|
/* ここの処理はホットスポットになるので,のちのちにチューニングすること */
|
|
|
|
for (pixel = 0; pixel < 16; pixel++) {
|
|
n = 0;
|
|
for (y = 0; y < ww_lcd_height; y++) {
|
|
for (x = 0; x < ww_lcd_width; x++) {
|
|
if (pixel == WWLCDPanel_GetPixel(ww_lcd_panel, x, y)) {
|
|
px = (x * x_display->width ) / ww_lcd_width;
|
|
py = (y * x_display->height) / ww_lcd_height;
|
|
rectangles[n].x = px;
|
|
rectangles[n].y = py;
|
|
rectangles[n].width = (x+1) * x_display->width / ww_lcd_width - px;
|
|
rectangles[n].height = (y+1) * x_display->height / ww_lcd_height- py;
|
|
|
|
/* 隣接してる同色のピクセルは,極力いっしょに描画する */
|
|
x++;
|
|
while ( (x < ww_lcd_width) &&
|
|
(pixel == WWLCDPanel_GetPixel(ww_lcd_panel, x, y)) ) {
|
|
rectangles[n].width = (x+1) * x_display->width / ww_lcd_width - px;
|
|
x++;
|
|
}
|
|
x--;
|
|
|
|
n++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (n > 0) {
|
|
XFillRectangles(x_display->display,
|
|
x_display->lcd_pixmap,
|
|
x_display->color_gc[pixel],
|
|
rectangles, n);
|
|
}
|
|
}
|
|
|
|
XCopyArea(x_display->display, x_display->lcd_pixmap,
|
|
x_display->lcd_window, x_display->copy_gc,
|
|
0, 0, x_display->width, x_display->height, 0, 0);
|
|
|
|
XDisplay_Sync(x_display);
|
|
|
|
free(rectangles);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/* ここまで */
|
|
/*****************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
/* End of File. */
|
|
/*****************************************************************************/
|