OSDN Git Service

branch-hexの変更をコミット。
[hengband/hengband.git] / src / chuukei.c
index e1f217f..fdbd00d 100644 (file)
@@ -2,12 +2,14 @@
 
 #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
+#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 epoch_time;  /* ¥Ð¥Ã¥Õ¥¡³«»Ï»þ¹ï */
 static long time_diff;   /* ¥×¥ì¥¤Â¦¤È¤Î»þ´Ö¤Î¤º¤ì(¤³¤ì¤ò¸«¤Ê¤¬¤é¥Ç¥£¥ì¥¤¤òÄ´À°¤·¤Æ¤¤¤¯) */
 static int browse_delay; /* É½¼¨¤¹¤ë¤Þ¤Ç¤Î»þ´Ö(100msñ°Ì)(¤³¤Î´Ö¤Ë¥é¥°¤òµÛ¼ý¤¹¤ë) */
+#ifdef CHUUKEI
 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
@@ -47,7 +61,7 @@ static char server_name[MAX_HOSTNAME];
 static InetSvcRef inet_services = nil;
 static EndpointRef ep                  = kOTInvalidEndpointRef;
 #endif
-
+#endif
 /* ÉÁ²è¤¹¤ë»þ¹ï¤ò³Ð¤¨¤Æ¤ª¤¯¥­¥å¡¼¹½Â¤ÂΠ*/
 static struct
 {
@@ -77,8 +91,30 @@ int recv(int s, char *buffer, size_t buflen, int flags)
 }
 #endif
 
+/*
+ * 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, byte 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_chuukei()
+static errr init_buffer(void)
 {
        fresh_queue.next = fresh_queue.tail = 0;
        ring.wptr = ring.rptr = ring.inlen = 0;
@@ -93,7 +129,7 @@ static errr init_chuukei()
 static long get_current_time(void)
 {
 #ifdef WINDOWS
-       return GetTickCount() / 100;
+       return timeGetTime() / 100;
 #elif defined(MACINTOSH)
        return TickCount();
 #else
@@ -111,17 +147,28 @@ static errr insert_ringbuf(char *buf)
        int len;
        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);
        }
 
@@ -148,12 +195,12 @@ static errr insert_ringbuf(char *buf)
        return (0);
 }
 
+#ifdef CHUUKEI
 void flush_ringbuf(void)
 {
 #ifndef MACINTOSH
        fd_set fdset;
        struct timeval tv;
-       int writen = 0;
 
        if (!chuukei_server) return;
 
@@ -168,11 +215,9 @@ void flush_ringbuf(void)
        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);
@@ -185,7 +230,7 @@ void flush_ringbuf(void)
                if (result <= 0)
                {
                        /* ¥µ¡¼¥Ð¤È¤ÎÀܳÃÇ¡© */
-                       chuukei_server = FALSE;
+                       if (chuukei_server) disable_chuukei_server();
 
                        prt("¥µ¡¼¥Ð¤È¤ÎÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿¡£", 0, 0);
                        inkey();
@@ -196,36 +241,26 @@ void flush_ringbuf(void)
 
                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);
                        inkey();
@@ -236,7 +271,6 @@ void flush_ringbuf(void)
 
                ring.rptr += result;
                ring.inlen -= result;
-               writen += result;
 
                if (ring.rptr == RINGBUF_SIZE) ring.rptr = 0;
                if (ring.inlen == 0) break;
@@ -244,12 +278,13 @@ void flush_ringbuf(void)
 #endif
 }
 
+
 static int read_chuukei_prf(cptr prf_name)
 {
        char buf[1024];
        FILE *fp;
 
-       path_build(buf, 1024, ANGBAND_DIR_XTRA, prf_name);
+       path_build(buf, sizeof(buf), ANGBAND_DIR_XTRA, prf_name);
        fp = my_fopen(buf, "r");
 
        if (!fp) return (-1);
@@ -259,12 +294,13 @@ static int read_chuukei_prf(cptr prf_name)
        server_name[0] = 0;
        browse_delay = DEFAULT_DELAY;
 
-       while (0 == my_fgets(fp, buf, 1024))
+       while (0 == my_fgets(fp, buf, sizeof(buf)))
        {
                /* ¥µ¡¼¥Ð̾ */
                if (!strncmp(buf, "server:", 7))
                {
-                       strncpy(server_name, buf + 7, MAX_HOSTNAME);
+                       strncpy(server_name, buf + 7, MAX_HOSTNAME - 1);
+                       server_name[MAX_HOSTNAME - 1] = '\0';
                }
 
                /* ¥Ý¡¼¥ÈÈÖ¹æ */
@@ -306,7 +342,7 @@ int connect_chuukei_server(char *prf_name)
                return (-1);
        }
 
-       if (init_chuukei() < 0)
+       if (init_buffer() < 0)
        {
                printf("Malloc error\n");
                return (-1);
@@ -337,7 +373,7 @@ int connect_chuukei_server(char *prf_name)
        }
 
        ask.sin_family = AF_INET;
-       ask.sin_port = htons(server_port);
+       ask.sin_port = htons((unsigned short)server_port);
 
 #ifndef WINDOWS
        if ((sd=socket(PF_INET,SOCK_STREAM, 0)) < 0)
@@ -356,8 +392,6 @@ int connect_chuukei_server(char *prf_name)
                return (-1);
        }
 
-       epoch_time = get_current_time();
-
        return (0);
 #else  /* MACINTOSH */
        OSStatus err;
@@ -373,7 +407,7 @@ int connect_chuukei_server(char *prf_name)
                return (-1);
        }
        
-       init_chuukei();
+       init_buffer();
        
        printf("server = %s\nport = %d\n", server_name, server_port);
 
@@ -413,15 +447,15 @@ int connect_chuukei_server(char *prf_name)
                        bind = (err == noErr);
            }
            if (err == noErr){
-               OTInitInetAddress(&inAddr, server_port, host_addr);
+               OTInitInetAddress(&inAddr, server_port, host_addr);
                        
                        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);
                        
@@ -457,102 +491,7 @@ int connect_chuukei_server(char *prf_name)
 
 #endif
 }
-
-#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
+#endif /* CHUUKEI */
 
 /* str¤¬Æ±¤¸Ê¸»ú¤Î·«¤êÊÖ¤·¤«¤É¤¦¤«Ä´¤Ù¤ë */
 static bool string_is_repeat(char *str, int len)
@@ -577,13 +516,11 @@ static bool string_is_repeat(char *str, int len)
        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(int x, int y, int len, byte col, cptr str)
 {
        char buf[1024];
        char buf2[1024];
 
-       if (!chuukei_server || Term != angband_term[0]) return;
-
        strncpy(buf2, str, len);
        buf2[len] = '\0';
 
@@ -593,7 +530,11 @@ void send_text_to_chuukei_server(int x, int y, int len, int col, char *str)
        }
        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
        {
@@ -604,105 +545,334 @@ void send_text_to_chuukei_server(int x, int y, int len, int col, char *str)
        }
 
        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);
+
+       insert_ringbuf(buf);
+
+       return (*old_bigcurs_hook)(x, y);
+}
+
 
-               if (buf[i] == '\0')
+/*
+ * 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);
+#ifdef JP
+               msg_print("Ï¿²è¤ò½ªÎ»¤·¤Þ¤·¤¿¡£");
+#else
+               msg_print("Stopped recording.");
+#endif
+       }
+       else
+       {
+               sprintf(tmp, "%s.amv", player_base);
+#ifdef JP
+               if (get_string("¥à¡¼¥Ó¡¼µ­Ï¿¥Õ¥¡¥¤¥ë: ", tmp, 80))
+#else
+               if (get_string("Movie file name: ", tmp, 80))
+#endif
                {
-                       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)
+                       {
+                               char out_val[160];
+
+                               /* Close the file */
+                               (void)fd_close(fd);
+
+                               /* Build query */
+#ifdef JP
+                               (void)sprintf(out_val, "¸½Â¸¤¹¤ë¥Õ¥¡¥¤¥ë¤Ë¾å½ñ¤­¤·¤Þ¤¹¤«? (%s)", buf);
+#else
+                               (void)sprintf(out_val, "Replace existing file %s? ", buf);
+#endif
+
+                               /* Ask */
+                               if (!get_check(out_val)) return;
+
+                               movie_fd = fd_open(buf, O_WRONLY | O_TRUNC);
+                       }
+                       else
                        {
-                               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);
-                               }
+                               movie_fd = fd_make(buf, 0644);
+                       }
 
+                       if (!movie_fd)
+                       {
+#ifdef JP
+                               msg_print("¥Õ¥¡¥¤¥ë¤ò³«¤±¤Þ¤»¤ó¡ª");
+#else
+                               msg_print("Can not open file.");
+#endif
+                               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;
+
+                       /* ¼õ¿®¥Ç¡¼¥¿¤òÊݸ */
+                       if (insert_ringbuf(recv_buf) < 0) 
                                return -1;
-                       return (i);
+
+                       /* ¼¡¤Î¥Ç¡¼¥¿°Ü¹Ô¤òrecv_buf¤ÎÀèƬ¤Ë°ÜÆ° */
+                       memmove(recv_buf, recv_buf + i + 1, remain_bytes - i - 1);
+
+                       remain_bytes -= (i+1);
+                       i = 0;
                }
        }
+
+       return 0;
 }
 
 
 #ifndef WINDOWS
 /* WinÈǤÎÃæÅÀ¤ÈÊɤÎƦÉå¤ò¥Ô¥ê¥ª¥É¤È¥·¥ã¡¼¥×¤Ë¤¹¤ë¡£*/
-void win2unix(int col, char *buf)
+static void win2unix(int col, char *buf)
 {
        char kabe;
        if ( col == 9 ) kabe = '%';
@@ -741,6 +911,23 @@ static bool get_nextbuf(char *buf)
        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];
@@ -757,7 +944,7 @@ static bool flush_ringbuf_client(void)
                char id;
                int x, y, len, 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);
@@ -778,7 +965,8 @@ static bool flush_ringbuf_client(void)
 #ifdef SJIS
                        euc2sjis(mesg);
 #endif
-                       (void)((*angband_term[0]->text_hook)(x, y, len, col, mesg));
+                       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++)
                        {
@@ -792,7 +980,8 @@ static bool flush_ringbuf_client(void)
                                mesg[i] = mesg[0];
                        }
                        mesg[i] = '\0';
-                       (void)((*angband_term[0]->text_hook)(x, y, len, col, mesg));
+                       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++)
                        {
@@ -801,12 +990,14 @@ static bool flush_ringbuf_client(void)
                        break;
 
                case 's': /* °ìʸ»ú */
-                       (void)((*angband_term[0]->text_hook)(x, y, 1, col, mesg));
+                       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;
 
@@ -816,8 +1007,13 @@ static bool flush_ringbuf_client(void)
                        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;
                }
        }
 
@@ -826,6 +1022,7 @@ static bool flush_ringbuf_client(void)
        return (TRUE);
 }
 
+#ifdef CHUUKEI
 void browse_chuukei()
 {
 #ifndef MACINTOSH
@@ -869,27 +1066,19 @@ void browse_chuukei()
                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;
+               if (flush_ringbuf_client()) continue;
 
                /* ¥½¥±¥Ã¥È¤Ë¥Ç¡¼¥¿¤¬Íè¤Æ¤¤¤ë¤«¤É¤¦¤«Ä´¤Ù¤ë */
-               
+
                OTCountDataBytes(ep, &unreadData);
                if(unreadData <= 0 ){
                        Term_xtra(TERM_XTRA_FLUSH, 0);
@@ -905,5 +1094,46 @@ void browse_chuukei()
        }
 #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
+                       }
+               }
+       }
+}