-/* chuukei.c */
+/*!
+ @file chuukei.c
+ @brief 中継機能の実装
+ @date 2014/01/02
+ @author
+ 2014 Deskull rearranged comment for Doxygen.
+ */
#include "angband.h"
-#ifdef CHUUKEI
-
#include <stdio.h>
#include <stdarg.h>
#include <ctype.h>
+#ifdef WINDOWS
+#include <windows.h>
+#endif
+#ifdef CHUUKEI
#if defined(WINDOWS)
#include <winsock.h>
#elif defined(MACINTOSH)
#endif
#define MAX_HOSTNAME 256
-#define RINGBUF_SIZE 65536*8
-#define FRESH_QUEUE_SIZE 1024
-#define WAIT 100*1000 /* ¥Ö¥é¥¦¥ºÂ¦¤Î¥¦¥¨¥¤¥È(usñ°Ì) */
+#endif
+
+#define RINGBUF_SIZE 1024*1024
+#define FRESH_QUEUE_SIZE 4096
+#ifdef WINDOWS
+#define WAIT 100
+#else
+#define WAIT 100*1000 /* ブラウズ側のウエイト(us単位) */
+#endif
#define DEFAULT_DELAY 50
+#define RECVBUF_SIZE 1024
-static int sd; /* ¥½¥±¥Ã¥È¤Î¥Õ¥¡¥¤¥ë¥Ç¥£¥¹¥¯¥ê¥×¥¿ */
-static long epoch_time; /* ³«»Ï»þ¹ï */
-static long time_diff; /* ¥×¥ì¥¤Â¦¤È¤Î»þ´Ö¤Î¤º¤ì(¤³¤ì¤ò¸«¤Ê¤¬¤é¥Ç¥£¥ì¥¤¤òÄ´À°¤·¤Æ¤¤¤¯) */
-static int browse_delay; /* ɽ¼¨¤¹¤ë¤Þ¤Ç¤Î»þ´Ö(100msñ°Ì)(¤³¤Î´Ö¤Ë¥é¥°¤òµÛ¼ý¤¹¤ë) */
+static long epoch_time; /* バッファ開始時刻 */
+static int browse_delay; /* 表示するまでの時間(100ms単位)(この間にラグを吸収する) */
+#ifdef CHUUKEI
+static int sd; /* ソケットのファイルディスクリプタ */
+static long time_diff; /* プレイ側との時間のずれ(これを見ながらディレイを調整していく) */
static int server_port;
static char server_name[MAX_HOSTNAME];
+#endif
+static int movie_fd;
+static int movie_mode;
+#ifdef CHUUKEI
#ifdef WINDOWS
#define close closesocket
#endif
static InetSvcRef inet_services = nil;
static EndpointRef ep = kOTInvalidEndpointRef;
#endif
-
-/* ÉÁ²è¤¹¤ë»þ¹ï¤ò³Ð¤¨¤Æ¤ª¤¯¥¥å¡¼¹½Â¤ÂÎ */
+#endif
+/* 描画する時刻を覚えておくキュー構造体 */
static struct
{
int time[FRESH_QUEUE_SIZE];
}fresh_queue;
-/* ¥ê¥ó¥°¥Ð¥Ã¥Õ¥¡¹½Â¤ÂÎ */
+/* リングバッファ構造体 */
static struct
{
char *buf;
}
#endif
-/* ANSI C¤Ë¤è¤ì¤ÐstaticÊÑ¿ô¤Ï0¤Ç½é´ü²½¤µ¤ì¤ë¤¬°ì±þ½é´ü²½¤¹¤ë */
-static errr init_chuukei(void)
+/*
+ * Original hooks
+ */
+static errr (*old_xtra_hook)(int n, int v);
+static errr (*old_curs_hook)(int x, int y);
+static errr (*old_bigcurs_hook)(int x, int y);
+static errr (*old_wipe_hook)(int x, int y, int n);
+static errr (*old_text_hook)(int x, int y, int n, TERM_COLOR a, cptr s);
+
+static void disable_chuukei_server(void)
+{
+ term *t = angband_term[0];
+#ifdef CHUUKEI
+ chuukei_server = FALSE;
+#endif /* CHUUKEI */
+ t->xtra_hook = old_xtra_hook;
+ t->curs_hook = old_curs_hook;
+ t->bigcurs_hook = old_bigcurs_hook;
+ t->wipe_hook = old_wipe_hook;
+ t->text_hook = old_text_hook;
+}
+
+/* ANSI Cによればstatic変数は0で初期化されるが一応初期化する */
+static errr init_buffer(void)
{
fresh_queue.next = fresh_queue.tail = 0;
ring.wptr = ring.rptr = ring.inlen = 0;
return (0);
}
-/* ¸½ºß¤Î»þ´Ö¤ò100msñ°Ì¤Ç¼èÆÀ¤¹¤ë */
+/* 現在の時間を100ms単位で取得する */
static long get_current_time(void)
{
#ifdef WINDOWS
- return GetTickCount() / 100;
+ return timeGetTime() / 100;
#elif defined(MACINTOSH)
return TickCount();
#else
}
-/* ¥ê¥ó¥°¥Ð¥Ã¥Õ¥¡¹½Â¤ÂÎ¤Ë buf ¤ÎÆâÍƤò²Ã¤¨¤ë */
+/* リングバッファ構造体に buf の内容を加える */
static errr insert_ringbuf(char *buf)
{
int len;
- len = strlen(buf) + 1; /* +1¤Ï½ªÃ¼Ê¸»úʬ */
+ len = strlen(buf) + 1; /* +1は終端文字分 */
- /* ¥Ð¥Ã¥Õ¥¡¤ò¥ª¡¼¥Ð¡¼ */
+ if (movie_mode)
+ {
+ fd_write(movie_fd, buf, len);
+#ifdef CHUUKEI
+ if (!chuukei_server) return 0;
+#else
+ return 0;
+#endif
+ }
+
+ /* バッファをオーバー */
if (ring.inlen + len >= RINGBUF_SIZE)
{
- chuukei_server = FALSE;
- chuukei_client = FALSE;
+#ifdef CHUUKEI
+ if (chuukei_server) disable_chuukei_server();
+ else chuukei_client = FALSE;
- prt("¥Ð¥Ã¥Õ¥¡¤¬°î¤ì¤Þ¤·¤¿¡£¥µ¡¼¥Ð¤È¤ÎÀܳ¤òÀÚÃǤ·¤Þ¤¹¡£", 0, 0);
+ prt("送受信バッファが溢れました。サーバとの接続を切断します。", 0, 0);
inkey();
close(sd);
-
+#endif
return (-1);
}
- /* ¥Ð¥Ã¥Õ¥¡¤Î½ªÃ¼¤Þ¤Ç¤Ë¼ý¤Þ¤ë */
+ /* バッファの終端までに収まる */
if (ring.wptr + len < RINGBUF_SIZE)
{
memcpy(ring.buf + ring.wptr, buf, len);
ring.wptr += len;
}
- /* ¥Ð¥Ã¥Õ¥¡¤Î½ªÃ¼¤Þ¤Ç¤Ë¼ý¤Þ¤é¤Ê¤¤(¥Ô¥Ã¥¿¥ê¼ý¤Þ¤ë¾ì¹ç¤â´Þ¤à) */
+ /* バッファの終端までに収まらない(ピッタリ収まる場合も含む) */
else
{
- int head = RINGBUF_SIZE - ring.wptr; /* Á°È¾ */
- int tail = len - head; /* ¸åȾ */
+ int head = RINGBUF_SIZE - ring.wptr; /* 前半 */
+ int tail = len - head; /* 後半 */
memcpy(ring.buf + ring.wptr, buf, head);
memcpy(ring.buf, buf + head, tail);
return (0);
}
+#ifdef CHUUKEI
void flush_ringbuf(void)
{
#ifndef MACINTOSH
fd_set fdset;
struct timeval tv;
- int writen = 0;
if (!chuukei_server) return;
while (1)
{
fd_set tmp_fdset;
- struct timeval tmp_tv;
int result;
tmp_fdset = fdset;
- tmp_tv = tv;
- /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤ò½ñ¤¹þ¤á¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
+ /* ソケットにデータを書き込めるかどうか調べる */
select(sd+1, (fd_set *)NULL, &tmp_fdset, (fd_set *)NULL, &tv);
- /* ½ñ¤¹þ¤á¤Ê¤±¤ì¤ÐÌá¤ë */
+ /* 書き込めなければ戻る */
if (FD_ISSET(sd, &tmp_fdset) == 0) break;
result = send(sd, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0);
if (result <= 0)
{
- /* ¥µ¡¼¥Ð¤È¤ÎÀܳÃÇ¡© */
- chuukei_server = FALSE;
+ /* サーバとの接続断? */
+ if (chuukei_server) disable_chuukei_server();
- prt("¥µ¡¼¥Ð¤È¤ÎÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿¡£", 0, 0);
+ prt("サーバとの接続が切断されました。", 0, 0);
inkey();
close(sd);
ring.rptr += result;
ring.inlen -= result;
- writen += result;
if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
if (ring.inlen == 0) break;
}
#else
- struct timeval tv;
- int writen = 0;
-
if (!chuukei_server) return;
if (ring.inlen == 0) return;
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
while (1)
{
- struct timeval tmp_tv;
int result;
- tmp_tv = tv;
-
- /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤ò½ñ¤¹þ¤á¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
+ /* ソケットにデータを書き込めるかどうか調べる */
result = OTSnd(ep, ring.buf + ring.rptr, ((ring.wptr > ring.rptr ) ? ring.wptr : RINGBUF_SIZE) - ring.rptr, 0);
if (result <= 0)
{
- /* ¥µ¡¼¥Ð¤È¤ÎÀܳÃÇ¡© */
- chuukei_server = FALSE;
+ /* サーバとの接続断? */
+ if (chuukei_server) disable_chuukei_server();
- prt("¥µ¡¼¥Ð¤È¤ÎÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿¡£", 0, 0);
+ prt("サーバとの接続が切断されました。", 0, 0);
inkey();
close(sd);
ring.rptr += result;
ring.inlen -= result;
- writen += result;
if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
if (ring.inlen == 0) break;
#endif
}
+
static int read_chuukei_prf(cptr prf_name)
{
char buf[1024];
if (!fp) return (-1);
- /* ½é´ü²½ */
+ /* 初期化 */
server_port = -1;
server_name[0] = 0;
browse_delay = DEFAULT_DELAY;
while (0 == my_fgets(fp, buf, sizeof(buf)))
{
- /* ¥µ¡¼¥Ð̾ */
+ /* サーバ名 */
if (!strncmp(buf, "server:", 7))
{
strncpy(server_name, buf + 7, MAX_HOSTNAME - 1);
server_name[MAX_HOSTNAME - 1] = '\0';
}
- /* ¥Ý¡¼¥ÈÈÖ¹æ */
+ /* ポート番号 */
if (!strncmp(buf, "port:", 5))
{
server_port = atoi(buf + 5);
}
- /* ¥Ç¥£¥ì¥¤ */
+ /* ã\83\87ã\82£ã\83¬ã\82¤ */
if (!strncmp(buf, "delay:", 6))
{
browse_delay = atoi(buf + 6);
my_fclose(fp);
- /* prf¥Õ¥¡¥¤¥ë¤¬´°Á´¤Ç¤Ê¤¤ */
+ /* prfファイルが完全でない */
if (server_port == -1 || server_name[0] == 0) return (-1);
return (0);
return (-1);
}
- if (init_chuukei() < 0)
+ if (init_buffer() < 0)
{
printf("Malloc error\n");
return (-1);
return (-1);
}
- epoch_time = get_current_time();
-
return (0);
#else /* MACINTOSH */
OSStatus err;
return (-1);
}
- init_chuukei();
+ init_buffer();
printf("server = %s\nport = %d\n", server_name, server_port);
sndCall.addr.len = sizeof(InetAddress);
sndCall.addr.buf = (unsigned char*) &inAddr;
- sndCall.opt.buf = nil; /* no connection options */
+ sndCall.opt.buf = nil; /* no connection options */
sndCall.opt.len = 0;
- sndCall.udata.buf = nil; /* no connection data */
+ sndCall.udata.buf = nil; /* no connection data */
sndCall.udata.len = 0;
- sndCall.sequence = 0; /* ignored by OTConnect */
+ sndCall.sequence = 0; /* ignored by OTConnect */
err = OTConnect(ep, &sndCall, NULL);
#endif
}
+#endif /* CHUUKEI */
-#ifdef SJIS
-static void sjis2euc(char *str)
-{
- int i, l;
- unsigned char c1, c2;
- int kanji = 0;
- int iseuc = 1;
- l = strlen(str);
-
- for (i = 0; i < l; i++)
- {
- c1 = str[i];
- if (c1 & 0x80) kanji = 1;
- if (c1>=0x80 && (c1 < 0xa1 || c1 > 0xfe)) iseuc = 0;
- }
-
- if (kanji && !iseuc)
- {
- unsigned char tmp[256];
-
- for (i = 0; i < l; i++)
- {
- c1 = str[i];
- if (c1 & 0x80)
- {
- i++;
- c2 = str[i];
- if (c2 >= 0x9f)
- {
- c1 = c1 * 2 - (c1 >= 0xe0 ? 0xe0 : 0x60);
- c2 += 2;
- }
- else
- {
- c1 = c1 * 2 - (c1 >= 0xe0 ? 0xe1 : 0x61);
- c2 += 0x60 + (c2 < 0x7f);
- }
- tmp[i - 1] = c1;
- tmp[i] = c2;
- }
- else
- tmp[i] = c1;
- }
- tmp[l] = 0;
- strcpy(str, tmp);
- }
-}
-
-static void euc2sjis(char *str)
-{
- int i, l;
- unsigned char c1, c2;
- int kanji = 0;
- int iseuc = 1;
- l = strlen(str);
-
- for (i = 0; i < l; i++)
- {
- c1 = str[i];
- if (c1 & 0x80) kanji = 1;
- if (c1>=0x80 && (c1 < 0xa1 || c1 > 0xfe)) iseuc = 0;
- }
- if (kanji && iseuc)
- {
- unsigned char tmp[256];
-
- for (i = 0; i < l; i++)
- {
- c1 = str[i];
- if (c1 & 0x80)
- {
- i++;
- c2 = str[i];
- if (c1 % 2)
- {
- c1 = (c1 >> 1) + (c1 < 0xdf ? 0x31 : 0x71);
- c2 -= 0x60 + (c2 < 0xe0);
- }
- else
- {
- c1 = (c1 >> 1) + (c1 < 0xdf ? 0x30 : 0x70);
- c2 -= 2;
- }
-
- tmp[i - 1] = c1;
- tmp[i] = c2;
- }
- else
- tmp[i] = c1;
- }
- tmp[l] = 0;
- strcpy(str, tmp);
- }
-}
-#endif
-
-/* str¤¬Æ±¤¸Ê¸»ú¤Î·«¤êÊÖ¤·¤«¤É¤¦¤«Ä´¤Ù¤ë */
+/* strが同じ文字の繰り返しかどうか調べる */
static bool string_is_repeat(char *str, int len)
{
char c = str[0];
return (TRUE);
}
-void send_text_to_chuukei_server(int x, int y, int len, int col, char *str)
+static errr send_text_to_chuukei_server(TERM_LEN x, TERM_LEN y, int len, TERM_COLOR col, cptr str)
{
char buf[1024];
char buf2[1024];
- if (!chuukei_server || Term != angband_term[0]) return;
-
strncpy(buf2, str, len);
buf2[len] = '\0';
}
else if(string_is_repeat(buf2, len))
{
- sprintf(buf, "n%c%c%c%c%c", x+1, y+1, len, col, buf2[0]);
+ int i;
+ for (i = len; i > 0; i -= 127)
+ {
+ sprintf(buf, "n%c%c%c%c%c", x+1, y+1, MIN(i, 127), col, buf2[0]);
+ }
}
else
{
-#ifdef SJIS
+#if defined(SJIS) && defined(JP)
sjis2euc(buf2);
#endif
sprintf(buf, "t%c%c%c%c%s", x+1, y+1, len, col, buf2);
}
insert_ringbuf(buf);
+
+ return (*old_text_hook)(x, y, len, col, str);
}
-void send_wipe_to_chuukei_server(int x, int y, int len)
+static errr send_wipe_to_chuukei_server(int x, int y, int len)
{
char buf[1024];
- if (!chuukei_server || Term != angband_term[0]) return;
-
sprintf(buf, "w%c%c%c", x+1, y+1, len);
insert_ringbuf(buf);
+
+ return (*old_wipe_hook)(x, y, len);
}
-void send_xtra_to_chuukei_server(int n)
+static errr send_xtra_to_chuukei_server(int n, int v)
{
char buf[1024];
- if (!chuukei_server || Term != angband_term[0]) return;
- sprintf(buf, "x%c", n+1);
-
- insert_ringbuf(buf);
-
- if (n == TERM_XTRA_FRESH)
+ if (n == TERM_XTRA_CLEAR || n == TERM_XTRA_FRESH || n == TERM_XTRA_SHAPE)
{
- sprintf(buf, "d%ld", get_current_time() - epoch_time);
+ sprintf(buf, "x%c", n+1);
+
insert_ringbuf(buf);
+
+ if (n == TERM_XTRA_FRESH)
+ {
+ sprintf(buf, "d%ld", get_current_time() - epoch_time);
+ insert_ringbuf(buf);
+ }
}
+
+ /* Verify the hook */
+ if (!old_xtra_hook) return -1;
+
+ return (*old_xtra_hook)(n, v);
}
-void send_curs_to_chuukei_server(int x, int y)
+static errr send_curs_to_chuukei_server(int x, int y)
{
char buf[1024];
- if (!chuukei_server || Term != angband_term[0]) return;
sprintf(buf, "c%c%c", x+1, y+1);
insert_ringbuf(buf);
+
+ return (*old_curs_hook)(x, y);
}
-static int read_sock(void)
+static errr send_bigcurs_to_chuukei_server(int x, int y)
{
char buf[1024];
- int i;
- for (i = 0;; i++)
- {
- if (recv(sd, buf+i, 1, 0) <= 0)
- return -1;
+ sprintf(buf, "C%c%c", x+1, y+1);
- if (buf[i] == '\0')
+ insert_ringbuf(buf);
+
+ return (*old_bigcurs_hook)(x, y);
+}
+
+
+/*
+ * Prepare z-term hooks to call send_*_to_chuukei_server()'s
+ */
+void prepare_chuukei_hooks(void)
+{
+ term *t0 = angband_term[0];
+
+ /* Save original z-term hooks */
+ old_xtra_hook = t0->xtra_hook;
+ old_curs_hook = t0->curs_hook;
+ old_bigcurs_hook = t0->bigcurs_hook;
+ old_wipe_hook = t0->wipe_hook;
+ old_text_hook = t0->text_hook;
+
+ /* Prepare z-term hooks */
+ t0->xtra_hook = send_xtra_to_chuukei_server;
+ t0->curs_hook = send_curs_to_chuukei_server;
+ t0->bigcurs_hook = send_bigcurs_to_chuukei_server;
+ t0->wipe_hook = send_wipe_to_chuukei_server;
+ t0->text_hook = send_text_to_chuukei_server;
+}
+
+
+/*
+ * Prepare z-term hooks to call send_*_to_chuukei_server()'s
+ */
+void prepare_movie_hooks(void)
+{
+ char buf[1024];
+ char tmp[80];
+
+ if (movie_mode)
+ {
+ movie_mode = 0;
+#ifdef CHUUKEI
+ if (!chuukei_server) disable_chuukei_server();
+#else
+ disable_chuukei_server();
+#endif
+ fd_close(movie_fd);
+ msg_print(_("録画を終了しました。", "Stopped recording."));
+ }
+ else
+ {
+ sprintf(tmp, "%s.amv", player_base);
+ if (get_string(_("ムービー記録ファイル: ", "Movie file name: "), tmp, 80))
{
- if (buf[0] == 'd')
+ int fd;
+
+ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, tmp);
+
+ fd = fd_open(buf, O_RDONLY);
+
+ /* Existing file */
+ if (fd >= 0)
{
- int timestamp = atoi(buf + 1);
- long current_time = get_current_time();
-
- /* ºÇ½é¤Î»þ´Ö¤òÊݸ¤·¤Æ¤ª¤¯ */
- if (!fresh_queue.time[0])
- {
- epoch_time = current_time;
- epoch_time += browse_delay;
- epoch_time -= timestamp;
- time_diff = current_time - timestamp;
- }
-
- fresh_queue.time[fresh_queue.tail] = timestamp;
- fresh_queue.tail ++;
-
- if (fresh_queue.tail == FRESH_QUEUE_SIZE)
- fresh_queue.tail = 0;
-
- /* ¥×¥ì¥¤Â¦¤È¤Î¥Ç¥£¥ì¥¤¤òÄ´À° */
- if (time_diff > current_time - timestamp)
- {
- long old_time_diff = time_diff;
- time_diff = current_time - timestamp;
- epoch_time -= (old_time_diff - time_diff);
- }
-
- if (fresh_queue.tail == fresh_queue.next)
- {
- /* queue°î¤ì */
- close(sd);
- exit(1);
- }
+ char out_val[160];
+
+ /* Close the file */
+ (void)fd_close(fd);
+
+ /* Build query */
+ (void)sprintf(out_val, _("現存するファイルに上書きしますか? (%s)", "Replace existing file %s? "), buf);
+ /* Ask */
+ if (!get_check(out_val)) return;
+
+ movie_fd = fd_open(buf, O_WRONLY | O_TRUNC);
+ }
+ else
+ {
+ movie_fd = fd_make(buf, 0644);
+ }
+
+ if (!movie_fd)
+ {
+ msg_print(_("ファイルを開けません!", "Can not open file."));
+ return;
}
- if (insert_ringbuf(buf) < 0)
+ movie_mode = 1;
+#ifdef CHUUKEI
+ if (!chuukei_server) prepare_chuukei_hooks();
+#else
+ prepare_chuukei_hooks();
+#endif
+ do_cmd_redraw();
+ }
+ }
+}
+
+#ifdef CHUUKEI
+static int handle_timestamp_data(int timestamp)
+{
+ long current_time = get_current_time();
+
+ /* 描画キューは空かどうか? */
+ if (fresh_queue.tail == fresh_queue.next)
+ {
+ /* バッファリングし始めの時間を保存しておく */
+ epoch_time = current_time;
+ epoch_time += browse_delay;
+ epoch_time -= timestamp;
+ time_diff = current_time - timestamp;
+ }
+
+ /* 描画キューに保存し、保存位置を進める */
+ fresh_queue.time[fresh_queue.tail] = timestamp;
+ fresh_queue.tail ++;
+
+ /* キューの最後尾に到達したら先頭に戻す */
+ fresh_queue.tail %= FRESH_QUEUE_SIZE;
+
+ if (fresh_queue.tail == fresh_queue.next)
+ {
+ /* 描画キュー溢れ */
+ prt("描画タイミングキューが溢れました。サーバとの接続を切断します。", 0, 0);
+ inkey();
+ close(sd);
+
+ return -1;
+ }
+
+ /* プレイ側とのディレイを調整 */
+ if (time_diff != current_time - timestamp)
+ {
+ long old_time_diff = time_diff;
+ time_diff = current_time - timestamp;
+ epoch_time -= (old_time_diff - time_diff);
+ }
+
+ /* Success */
+ return 0;
+}
+#endif /* CHUUKEI */
+
+static int handle_movie_timestamp_data(int timestamp)
+{
+ static int initialized = FALSE;
+
+ /* 描画キューは空かどうか? */
+ if (!initialized)
+ {
+ /* バッファリングし始めの時間を保存しておく */
+ epoch_time = get_current_time();
+ epoch_time += browse_delay;
+ epoch_time -= timestamp;
+ //time_diff = current_time - timestamp;
+ initialized = TRUE;
+ }
+
+ /* 描画キューに保存し、保存位置を進める */
+ fresh_queue.time[fresh_queue.tail] = timestamp;
+ fresh_queue.tail ++;
+
+ /* キューの最後尾に到達したら先頭に戻す */
+ fresh_queue.tail %= FRESH_QUEUE_SIZE;
+
+ /* Success */
+ return 0;
+}
+
+#ifdef CHUUKEI
+static int read_sock(void)
+{
+ static char recv_buf[RECVBUF_SIZE];
+ static int remain_bytes = 0;
+ int recv_bytes;
+ int i;
+
+ /* 前回残ったデータの後につづけて配信サーバからデータ受信 */
+ recv_bytes = recv(sd, recv_buf + remain_bytes, RECVBUF_SIZE - remain_bytes, 0);
+
+ if (recv_bytes <= 0)
+ return -1;
+
+ /* 前回残ったデータ量に今回読んだデータ量を追加 */
+ remain_bytes += recv_bytes;
+
+ for (i = 0; i < remain_bytes; i ++)
+ {
+ /* データのくぎり('\0')を探す */
+ if (recv_buf[i] == '\0')
+ {
+ /* 'd'で始まるデータ(タイムスタンプ)の場合は
+ 描画キューに保存する処理を呼ぶ */
+ if ((recv_buf[0] == 'd') &&
+ (handle_timestamp_data(atoi(recv_buf + 1)) < 0))
+ return -1;
+
+ /* 受信データを保存 */
+ if (insert_ringbuf(recv_buf) < 0)
+ return -1;
+
+ /* 次のデータ移行をrecv_bufの先頭に移動 */
+ memmove(recv_buf, recv_buf + i + 1, remain_bytes - i - 1);
+
+ remain_bytes -= (i+1);
+ i = 0;
+ }
+ }
+
+ return 0;
+}
+#endif
+
+static int read_movie_file(void)
+{
+ static char recv_buf[RECVBUF_SIZE];
+ static int remain_bytes = 0;
+ int recv_bytes;
+ int i;
+
+ recv_bytes = read(movie_fd, recv_buf + remain_bytes, RECVBUF_SIZE - remain_bytes);
+
+ if (recv_bytes <= 0)
+ return -1;
+
+ /* 前回残ったデータ量に今回読んだデータ量を追加 */
+ remain_bytes += recv_bytes;
+
+ for (i = 0; i < remain_bytes; i ++)
+ {
+ /* データのくぎり('\0')を探す */
+ if (recv_buf[i] == '\0')
+ {
+ /* 'd'で始まるデータ(タイムスタンプ)の場合は
+ 描画キューに保存する処理を呼ぶ */
+ if ((recv_buf[0] == 'd') &&
+ (handle_movie_timestamp_data(atoi(recv_buf + 1)) < 0))
return -1;
- return (i);
+
+ /* 受信データを保存 */
+ if (insert_ringbuf(recv_buf) < 0)
+ return -1;
+
+ /* 次のデータ移行をrecv_bufの先頭に移動 */
+ memmove(recv_buf, recv_buf + i + 1, remain_bytes - i - 1);
+
+ remain_bytes -= (i+1);
+ i = 0;
}
}
+
+ return 0;
}
#ifndef WINDOWS
-/* WinÈǤÎÃæÅÀ¤ÈÊɤÎƦÉå¤ò¥Ô¥ê¥ª¥É¤È¥·¥ã¡¼¥×¤Ë¤¹¤ë¡£ */
+/* Win版の床の中点と壁の豆腐をピリオドとシャープにする。*/
static void win2unix(int col, char *buf)
{
char kabe;
return (TRUE);
}
+/* プレイホストのマップが大きいときクライアントのマップもリサイズする */
+static void update_term_size(int x, int y, int len)
+{
+ int ox, oy;
+ int nx, ny;
+ Term_get_size(&ox, &oy);
+ nx = ox;
+ ny = oy;
+
+ /* 横方向のチェック */
+ if (x + len > ox) nx = x + len;
+ /* 縦方向のチェック */
+ if (y + 1 > oy) ny = y + 1;
+
+ if (nx != ox || ny != oy) Term_resize(nx, ny);
+}
+
static bool flush_ringbuf_client(void)
{
char buf[1024];
- /* ½ñ¤¯¥Ç¡¼¥¿¤Ê¤· */
+ /* 書くデータなし */
if (fresh_queue.next == fresh_queue.tail) return (FALSE);
- /* ¤Þ¤À½ñ¤¯¤Ù¤»þ¤Ç¤Ê¤¤ */
+ /* まだ書くべき時でない */
if (fresh_queue.time[fresh_queue.next] > get_current_time() - epoch_time) return (FALSE);
- /* »þ´Ö¾ðÊó(¶èÀÚ¤ê)¤¬ÆÀ¤é¤ì¤ë¤Þ¤Ç½ñ¤¯ */
+ /* 時間情報(区切り)が得られるまで書く */
while (get_nextbuf(buf))
{
char id;
- int x, y, len, col;
+ int x, y, len;
+ TERM_COLOR col;
int i;
- char tmp1, tmp2, tmp3, tmp4;
+ unsigned char tmp1, tmp2, tmp3, tmp4;
char *mesg;
sscanf(buf, "%c%c%c%c%c", &id, &tmp1, &tmp2, &tmp3, &tmp4);
switch (id)
{
- case 't': /* Ä̾ï */
-#ifdef SJIS
+ case 't': /* 通常 */
+#if defined(SJIS) && defined(JP)
euc2sjis(mesg);
#endif
+ update_term_size(x, y, len);
(void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg));
strncpy(&Term->scr->c[y][x], mesg, len);
for (i = x; i < x+len; i++)
}
break;
- case 'n': /* ·«¤êÊÖ¤· */
+ case 'n': /* 繰り返し */
for (i = 1; i < len; i++)
{
mesg[i] = mesg[0];
}
mesg[i] = '\0';
+ update_term_size(x, y, len);
(void)((*angband_term[0]->text_hook)(x, y, len, (byte)col, mesg));
strncpy(&Term->scr->c[y][x], mesg, len);
for (i = x; i < x+len; i++)
}
break;
- case 's': /* °ìʸ»ú */
+ case 's': /* 一文字 */
+ update_term_size(x, y, 1);
(void)((*angband_term[0]->text_hook)(x, y, 1, (byte)col, mesg));
strncpy(&Term->scr->c[y][x], mesg, 1);
Term->scr->a[y][x] = col;
break;
case 'w':
+ update_term_size(x, y, len);
(void)((*angband_term[0]->wipe_hook)(x, y, len));
break;
break;
case 'c':
+ update_term_size(x, y, 1);
(void)((*angband_term[0]->curs_hook)(x, y));
break;
+ case 'C':
+ update_term_size(x, y, 1);
+ (void)((*angband_term[0]->bigcurs_hook)(x, y));
+ break;
}
}
return (TRUE);
}
+#ifdef CHUUKEI
void browse_chuukei()
{
#ifndef MACINTOSH
tmp_fdset = fdset;
tmp_tv = tv;
- /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
+ /* ソケットにデータが来ているかどうか調べる */
select(sd+1, &tmp_fdset, (fd_set *)NULL, (fd_set *)NULL, &tmp_tv);
if (FD_ISSET(sd, &tmp_fdset) == 0)
{
chuukei_client = FALSE;
}
- /* Àܳ¤¬Àڤ줿¾õÂ֤ǽñ¤¯¤Ù¤¥Ç¡¼¥¿¤¬¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤¿¤é½ªÎ» */
+ /* 接続が切れた状態で書くべきデータがなくなっていたら終了 */
if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break;
}
#else
- struct timeval tv;
-
- tv.tv_sec = 0;
- tv.tv_usec = WAIT;
-
Term_clear();
Term_fresh();
Term_xtra(TERM_XTRA_REACT, 0);
while (1)
{
- struct timeval tmp_tv;
UInt32 unreadData = 0;
int n;
-
+
if (flush_ringbuf_client()) continue;
- tmp_tv = tv;
+ /* ソケットにデータが来ているかどうか調べる */
- /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
-
OTCountDataBytes(ep, &unreadData);
if(unreadData <= 0 ){
Term_xtra(TERM_XTRA_FLUSH, 0);
chuukei_client = FALSE;
}
- /* Àܳ¤¬Àڤ줿¾õÂ֤ǽñ¤¯¤Ù¤¥Ç¡¼¥¿¤¬¤Ê¤¯¤Ê¤Ã¤Æ¤¤¤¿¤é½ªÎ» */
+ /* 接続が切れた状態で書くべきデータがなくなっていたら終了 */
if (!chuukei_client && fresh_queue.next == fresh_queue.tail ) break;
}
#endif /*MACINTOSH*/
}
-
#endif /* CHUUKEI */
+
+void prepare_browse_movie_aux(cptr filename)
+{
+ movie_fd = fd_open(filename, O_RDONLY);
+
+ browsing_movie = TRUE;
+
+ init_buffer();
+}
+
+void prepare_browse_movie(cptr filename)
+{
+ char buf[1024];
+ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, filename);
+
+ prepare_browse_movie_aux(buf);
+}
+
+void browse_movie(void)
+{
+ Term_clear();
+ Term_fresh();
+ Term_xtra(TERM_XTRA_REACT, 0);
+
+ while (read_movie_file() == 0)
+ {
+ while (fresh_queue.next != fresh_queue.tail)
+ {
+ if (!flush_ringbuf_client())
+ {
+ Term_xtra(TERM_XTRA_FLUSH, 0);
+
+ /* ソケットにデータが来ているかどうか調べる */
+#ifdef WINDOWS
+ Sleep(WAIT);
+#else
+ usleep(WAIT);
+#endif
+ }
+ }
+ }
+}