
#include <stdio.h>
#include <stdlib.h>
#include "helplay.h"

/*
 *
 *  open_helahela_window  画面の準備をする
 *  set_a_helahela_page   ファイルから読み込んだ１ページ分のデータから
 *                           表示する画像データを作成する
 *  play_helahela         再生する
 *  free_helahela         使用したリソースの開放
 *
 */

#ifdef towns_os

/*
 *           ここから Towns-os 用
 */

static char gwork[10000];       /* グラフィックBIOS用ワークエリア */
static char mwork[10000];       /* マウスBIOS用ワークエリア       */
static char **data;             /* 画像データ                     */
static int page_max;            /* ページ数                       */
static int block_max;

/*
 * GNU-CD2 の EGB ライブラリの _EGB_putBlockColor を定義している部分に
 * バグがありアクセスできないので、代わりにここで定義する。
 */
asm("
    _EGB_putBlockColor:
        push  %esi
	    push  %edi
        movl  12(%esp),%edi
        movw  16(%esp),%al
        movl  20(%esp),%esi
        movb  $0x23,%ah
        push  $0x0110
        pop   %fs
        lcall %fs:(0x20)
        movsbl %ah,%eax
        pop   %edi
        pop   %esi
        ret
");

int open_helahela_window(int page_count)
{
    int i;
    page_max = page_count;
    block_max = page_count / 27 + 1;
    EGB_init(gwork, 10000);
    MOS_start(mwork, 10000);
    EGB_writePage(gwork, 1);
    EGB_screenZoom(gwork, 4, 4);
    EGB_writePage(gwork, 0);
    EGB_screenZoom(gwork, 4, 4);
    data = (char **)malloc(block_max * sizeof(char *));
    if (data == NULL) return -1;
    for (i=0; i<block_max; i++) data[i] = NULL;
    for (i=0; i<block_max; i++){
        data[i] = (char *)malloc(SIZE * 27);
        if (data[i] == NULL){
            page_max = i * 27;
            fprintf(stderr, "helplay : can't malloc (page %d)\n", i*27);
        }
    }
    return 0;
}

int  set_a_helahela_page(int page, const unsigned char *buffer)
{
    int block_num = page / 27;
    int c = page % 27;
    int i;
    if (data[block_num] == NULL) return 1;
    for (i=0; i<SIZE; i++)
        data[block_num][c * SIZE + i] = buffer[i];
    return 0;
}

int play_helahela(int wait)
{
    static struct {
        void           *ad;
        unsigned short ds;
        short          x1, y1, x2, y2;
    } param = { NULL, 0x14, 0, 0, 159, 119};
    int count = 0;
    int play_flag = 0;
    int j;
    int vpage = 0;
    char jyoutai, kaisuu, x, y;

    EGB_writeMode(gwork, 9);
    param.ad = data[0];
    EGB_displayPage(0, gwork, 3);
    EGB_writePage(gwork, 0);
    MOS_writePage(0);
    EGB_putBlockColor(gwork, 0, (char *)&param);
    
    do {
        for (j=0; j< wait * 1500; j++);
        if (play_flag){
            if (++count >= page_max) count = 0;
            param.ad = data[count/27] + (count%27)*SIZE;
            vpage = 1-vpage;
            EGB_writePage(gwork, vpage);
            MOS_writePage(vpage);
            EGB_putBlockColor(gwork, 0, (char *)&param);
            EGB_displayPage(vpage, gwork, 1<<vpage);
        }
        MOS_rdon(0, &jyoutai, &kaisuu, &x, &y);
        if (kaisuu)
          play_flag = 1 - play_flag;
        MOS_rdon(1, &jyoutai, &kaisuu, &x, &y);
        if (kaisuu)
          return 0;
    } while (1);
    
    return 0;
}

void free_helahela(void)
{
    int i;
    for (i=block_max-1; i>=0; i--)
      free(data[i]);
    free(data);
    EGB_displayPage(0, gwork, 3);
    MOS_end();
    MOS_screenterm(gwork);
}

#else

/*
 *           ここから UNIX 用
 */

#include <X11/Xlib.h>

static int               page_max;
static Display           *d;
static Window            w;
static GC                gc;
static Pixmap            *pix;                /* 画像データ(bitmap形式) */
static unsigned char     exchange_table[256]; /* 上位bitと下位bitを
                                                 入れ換える為のテーブル */
static void set_exchange_table()
{
    int i, j;
    for (i=0; i<256; i++){
        exchange_table[i] = 0;
        for (j=0; j<8; j++)
          exchange_table[i] += (i & (1<<j)) ? (1<<(7-j)) : 0;
    }
}

int open_helahela_window(int page_count)
{
    d  = XOpenDisplay(NULL);
    if (d == NULL) return -5;
    w  = XCreateSimpleWindow(d, RootWindow(d, 0), 0, 0, 160, 120, 2,
                             WhitePixel(d, 0), BlackPixel(d, 0));
    XSelectInput(d, w, ButtonPressMask | ExposureMask);
    XMapWindow(d, w);
    gc = XCreateGC(d, w, 0, 0);
    XSetForeground(d, gc, WhitePixel(d, 0));
    XSetBackground(d, gc, BlackPixel(d, 0));
    pix = (Pixmap *)malloc(page_count * sizeof(Pixmap));
    if (pix == NULL) return -6;
    set_exchange_table();
    return 0;
} 

int  set_a_helahela_page(int page, const unsigned char *buffer)
{
    int j;
    unsigned char bit_data[SIZE];
    for (j=0; j<SIZE; j++)
      bit_data[j] = exchange_table[buffer[j]];
    pix[page] = XCreateBitmapFromData(d, w, bit_data, 160, 120);
    if (pix[page] == 0){
         fprintf(stderr, "helplay : can't get pix (page %d)\n", page);
         return 1;
    }
    page_max = page + 1;
    return 0;
}

int play_helahela(int wait)
{
    int count = 0;
    int play_flag = 0;
    XEvent ev;
    
    do {
        if (XPending(d) > 0){
            XNextEvent(d, &ev);
            if (ev.type == ButtonPress){
                if (ev.xbutton.button == 1)
                  play_flag = 1 - play_flag;
                else
                  return 0;
            }
            else if (ev.type == Expose){
                XCopyPlane(d, pix[count], w, gc, 0, 0, 160, 120, 0, 0, 1);
                XFlush(d);
            } 
        }
        if (play_flag){
            if ((++count) >= page_max) count = 0;
            XCopyPlane(d, pix[count], w, gc, 0, 0, 160, 120, 0, 0, 1);
            XFlush(d);
        }
        usleep(1000 * wait);
    } while(1);
    return 0;
}

void free_helahela(void)
{
    int i;
    for (i=page_max-1; i>=0; i--){
        XFreePixmap(d, pix[i]);
    }
    free(pix);
    XCloseDisplay(d);
}

#endif /* towns_os */

