openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

fish.c (25357B)


      1 /* Copyright 1998-1999, Brian J. Swetland. All rights reserved.
      2 ** Distributed under the terms of the OpenBLT License
      3 */
      4 
      5 #include <string.h>
      6 #include <stdlib.h>
      7 #include <stdarg.h>
      8 #include <i386/io.h>
      9 #include <blt/namer.h>
     10 #include <blt/syscall.h>
     11 
     12 #include "dfp.h"
     13 #include "vga.h"
     14 
     15 static int WITH_NET = 1;
     16 
     17 void keythread(void);
     18 
     19 int myX = 2;
     20 int myY = 2;
     21 
     22 int st_sent = 0;
     23 int st_recv = 0;
     24 int st_rej = 0;
     25 int st_count = 0;
     26 int sticky = 0;
     27 int collision = 0;
     28 int snooze = 5;
     29 
     30 int logsize = 15;
     31 
     32 
     33 int borg = 0;
     34 int logo = 0;
     35 int logging = 1;
     36 int recluse = 0;
     37 int ticks = 0;
     38 
     39 #define LOGGING
     40 #define TIMEOUT 8
     41 
     42 #define MAXKEYS 64
     43 static char keybuf2[MAXKEYS+4];
     44 static char *keybuf = keybuf2+2;
     45 static int keyptr = 0;
     46 
     47 int port_fish, port_net, port_console, port_net_xmit;
     48 
     49 static char kpbuf[512];
     50 static char *kp = kpbuf;
     51 static char *x;    
     52 
     53 typedef struct _msg 
     54 {
     55     struct _msg *next;
     56     char buf[65];
     57 } msg;
     58 msg *first_msg = NULL, *last_msg = NULL;
     59 int msgcount = 0;
     60 
     61 int sem_fish = 0, sem_msgs = 0;
     62 
     63 void lprintf(char *fmt,...)
     64 {
     65 #ifdef LOGGING
     66     va_list pvar;
     67     int n;
     68     msg *m = (msg *) malloc(sizeof(msg));
     69     
     70     va_start(pvar,fmt);
     71     va_snprintf(m->buf,64,fmt,pvar);
     72     va_end(pvar);
     73 
     74     m->buf[60]=0;
     75     m->next = NULL;
     76     sem_acquire(sem_msgs);
     77     msgcount++;
     78     if(last_msg){
     79         last_msg->next = m;
     80         last_msg = m;
     81     } else {
     82         first_msg = last_msg = m;
     83     }
     84     sem_release(sem_msgs);
     85 #endif
     86 }
     87 
     88 #define DEAD 0
     89 #define LIVE 1
     90 #define XMIT 2
     91 typedef struct _fish 
     92 {
     93     struct _fish *next, *prev;
     94     int x,y;
     95     int dx,dy;
     96     char name[17];
     97     char *bitmap;
     98     int state;
     99     int xt;
    100     dfp_pkt_transfer xfer;
    101     int dest;
    102 } fish;
    103 
    104 fish *first = NULL;
    105 fish *last = NULL;
    106 
    107 
    108 struct 
    109 {
    110     int live;
    111     int tx, ty;   
    112 } cnxn[4] = { {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} };
    113 
    114 #define C_UP 0
    115 #define C_DN 1
    116 #define C_LF 2
    117 #define C_RT 3
    118 #define NET_CONNECT  1
    119 #define NET_SEND     2
    120 #define NET_IP       3
    121 
    122 void settank(int tx, int ty, int live)
    123 {
    124     int i;
    125     for(i=0;i<4;i++){
    126         if(cnxn[i].tx == tx && cnxn[i].ty == ty){
    127             cnxn[i].live = live;
    128             return;
    129         }
    130     }
    131 }
    132 
    133 
    134 typedef struct 
    135 {
    136     int cmd; 
    137     int port;
    138 } net_cmd;
    139 
    140 typedef struct 
    141 {
    142     net_cmd cmd;
    143     dfp_pkt_transfer dfp;
    144 } net_fish;
    145 
    146 void newfish(int x, int y, int dx, int dy, char *n);
    147 
    148 void pingtank(int tx, int ty)
    149 {
    150 	if(WITH_NET){
    151 		net_fish f;
    152 		msg_hdr_t msg;
    153 		f.cmd.cmd = NET_SEND;
    154 		f.cmd.port = 5049;
    155 		f.dfp.base.src_tank_x = myX;
    156 		f.dfp.base.src_tank_y = myY;
    157 		f.dfp.base.dst_tank_x = tx;
    158 		f.dfp.base.dst_tank_y = ty;
    159 		f.dfp.base.size = htons(DFP_SIZE_LOCATE);
    160 		f.dfp.base.type = DFP_PKT_PING;
    161 		f.dfp.base.pad = 0;
    162 		f.dfp.base.version = htons(DFP_VERSION);
    163 		msg.flags = 0;
    164 		msg.src = port_fish;
    165 		msg.dst = port_net;
    166 		msg.size = sizeof(dfp_base)+8;
    167 		msg.data = &f;
    168 		old_port_send(&msg);
    169 	}
    170 }
    171 
    172 void initiate(dfp_pkt_transfer *send, int tx, int  ty)
    173 {
    174 	if(WITH_NET){
    175 		net_fish f;
    176 		msg_hdr_t msg;
    177 		f.cmd.cmd = NET_SEND;
    178 		f.cmd.port = 5049;
    179 		f.dfp.base.src_tank_x = myX;
    180 		f.dfp.base.src_tank_y = myY;
    181 		f.dfp.base.dst_tank_x = tx;
    182 		f.dfp.base.dst_tank_y = ty;
    183 		f.dfp.base.size = ntohs(DFP_SIZE_TRANSFER);
    184 		f.dfp.base.type = DFP_PKT_SEND_FISH;
    185 		f.dfp.base.pad = 0;
    186 		f.dfp.base.version = htons(DFP_VERSION);
    187 		memcpy(&(f.dfp.uid), &(send->uid), 6);
    188 		memcpy(&(f.dfp.fish), &(send->fish), sizeof(dfp_fish));
    189 		msg.flags = 0;
    190 		msg.src = port_fish;
    191 		msg.dst = port_net;
    192 		msg.size = DFP_SIZE_TRANSFER + 8;
    193 		msg.data = &f;
    194 		old_port_send(&msg);
    195 	}
    196 
    197 }
    198 
    199 char *types[] = { "PING", "PING", "SEND", "ACK", "NACK", "SYNC" };
    200 
    201 void dofish(dfp_pkt_transfer *dfp)
    202 {
    203     int i;
    204     
    205     net_fish f;
    206     fish *ff;
    207     char n2[17];
    208     msg_hdr_t msg;
    209     dfp->base.version = ntohs(dfp->base.version);
    210     dfp->base.size = ntohs(dfp->base.size);
    211 
    212     if(!(dfp->base.dst_tank_x == myX && dfp->base.dst_tank_y == myY)){
    213         return;
    214     }
    215 
    216     
    217   if(dfp->base.type == DFP_PKT_SYNC_FISH)  lprintf("fish: s(%d,%d) d(%d,%d) s=%d %s",
    218            dfp->base.src_tank_x, dfp->base.src_tank_y,
    219            dfp->base.dst_tank_x, dfp->base.dst_tank_y,
    220            dfp->base.size,
    221            dfp->base.type < 6 ? types[dfp->base.type] : "????"
    222            );
    223            
    224     switch(dfp->base.type){
    225     case DFP_PKT_PING :
    226         f.cmd.cmd = NET_SEND;
    227         f.cmd.port = 5049;
    228         f.dfp.base.src_tank_x = myX;
    229         f.dfp.base.src_tank_y = myY;
    230         f.dfp.base.dst_tank_x = dfp->base.src_tank_x;
    231         f.dfp.base.dst_tank_y = dfp->base.src_tank_y;
    232         f.dfp.base.size = htons(DFP_SIZE_LOCATE);
    233         f.dfp.base.type = DFP_PKT_PONG;
    234         f.dfp.base.pad = 0;
    235         f.dfp.base.version = htons(DFP_VERSION);
    236         settank(dfp->base.src_tank_x,dfp->base.src_tank_y,1);
    237         msg.flags = 0;
    238         msg.src = port_fish;
    239         msg.dst = port_net;
    240         msg.size = sizeof(dfp_base)+8;
    241         msg.data = &f;
    242         old_port_send(&msg);
    243 
    244         
    245         break;
    246                
    247     case DFP_PKT_PONG :
    248         lprintf("Pong from %d,%d",dfp->base.src_tank_x,dfp->base.src_tank_y);
    249         settank(dfp->base.src_tank_x,dfp->base.src_tank_y,1);
    250 /*        for(i=0;i<4;i++){
    251             if((cnxn[i].tx == dfp->base.src_tank_x) &&
    252                (cnxn[i].ty == dfp->base.src_tank_y)) {
    253                 cnxn[i].live = 1;
    254                 break;
    255             }
    256         }*/
    257         break;
    258 
    259     case DFP_PKT_SEND_FISH :
    260         dfp->fish.ttl = ntohs(dfp->fish.ttl);
    261         strncpy(n2,dfp->fish.name,16);
    262         n2[16]=0;
    263         if(recluse){
    264             lprintf("Ignoring \"%s\" from (%d,%d)",n2,
    265                    dfp->base.src_tank_x, dfp->base.src_tank_y);
    266             break;
    267         }
    268             /* lprintf("    : UID %X%X%X%X%X%X @(%d,%d) d(%d,%d) ttl=%d, name=\"%s\"",
    269                dfp->uid.creator_tank_x, dfp->uid.creator_tank_y,
    270                dfp->uid.timestamp[0], dfp->uid.timestamp[1],
    271                dfp->uid.timestamp[2], dfp->uid.timestamp[3],
    272                dfp->fish.x, dfp->fish.y, dfp->fish.dx, dfp->fish.dy,
    273                dfp->fish.ttl, n2);
    274                */
    275         f.cmd.cmd = NET_SEND;
    276         f.cmd.port = 5049;
    277         f.dfp.base.src_tank_x = myX;
    278         f.dfp.base.src_tank_y = myY;
    279         f.dfp.base.dst_tank_x = dfp->base.src_tank_x;
    280         f.dfp.base.dst_tank_y = dfp->base.src_tank_y;
    281         f.dfp.base.size = ntohs(DFP_SIZE_CONFIRM);
    282         f.dfp.base.type = DFP_PKT_ACK_FISH;
    283         f.dfp.base.pad = 0;
    284         f.dfp.base.version = htons(DFP_VERSION);
    285         memcpy(&(f.dfp.uid), &(dfp->uid), 6);
    286         
    287         msg.flags = 0;
    288         msg.src = port_fish;
    289         msg.dst = port_net;
    290         msg.size = DFP_SIZE_CONFIRM + 8;
    291         msg.data = &f;
    292         old_port_send(&msg);
    293         break;
    294 
    295     case DFP_PKT_ACK_FISH :
    296             /*  lprintf("    : UID %X%X%X%X%X%X",
    297                dfp->uid.creator_tank_x, dfp->uid.creator_tank_y,
    298                dfp->uid.timestamp[0], dfp->uid.timestamp[1],
    299                dfp->uid.timestamp[2], dfp->uid.timestamp[3]);
    300                */
    301         sem_acquire(sem_fish);
    302         for(ff = first; ff; ff=ff->next){
    303             if((ff->state==XMIT) &&
    304                (!memcmp(&(ff->xfer.uid),&(dfp->uid),6))){
    305                 ff->state = DEAD;
    306                 st_count--;
    307                 sem_release(sem_fish);
    308                 lprintf("Goodbye fish \"%s\" (%d,%d)",ff->name,
    309                        dfp->base.src_tank_x,dfp->base.src_tank_y);
    310                 
    311                 f.cmd.cmd = NET_SEND;
    312                 f.cmd.port = 5049;
    313                 f.dfp.base.src_tank_x = myX;
    314                 f.dfp.base.src_tank_y = myY;
    315                 f.dfp.base.dst_tank_x = dfp->base.src_tank_x;
    316                 f.dfp.base.dst_tank_y = dfp->base.src_tank_y;
    317                 f.dfp.base.size = ntohs(DFP_SIZE_TRANSFER);
    318                 f.dfp.base.type = DFP_PKT_SYNC_FISH;
    319                 f.dfp.base.pad = 0;
    320                 f.dfp.base.version = htons(DFP_VERSION);
    321                 memcpy(&(f.dfp.uid), &(ff->xfer.uid), 6);
    322                 memcpy(&(f.dfp.fish), &(ff->xfer.fish), sizeof(dfp_fish));
    323                 msg.flags = 0;
    324                 msg.src = port_fish;
    325                 msg.dst = port_net;
    326                 msg.size = DFP_SIZE_TRANSFER + 8;
    327                 msg.data = &f;
    328                 old_port_send(&msg);
    329                 st_sent++;
    330                 goto donesync;
    331             }
    332         }
    333         sem_release(sem_fish);
    334 donesync:
    335         break;
    336 
    337     case DFP_PKT_NACK_FISH :
    338         break;
    339 
    340     case DFP_PKT_SYNC_FISH :
    341         dfp->fish.ttl = ntohs(dfp->fish.ttl);
    342 
    343         strncpy(n2,dfp->fish.name,16);
    344         n2[16]=0;
    345              lprintf("    : UID %X%X%X%X%X%X @(%d,%d) d(%d,%d) ttl=%d, name=\"%s\"\n",
    346                dfp->uid.creator_tank_x, dfp->uid.creator_tank_y,
    347                dfp->uid.timestamp[0], dfp->uid.timestamp[1],
    348                dfp->uid.timestamp[2], dfp->uid.timestamp[3],
    349                dfp->fish.x, dfp->fish.y, dfp->fish.dx, dfp->fish.dy,
    350                dfp->fish.ttl, n2);
    351                
    352         newfish(dfp->fish.x, dfp->fish.y,
    353                 dfp->fish.dx, dfp->fish.dy,
    354                 n2);
    355 /*        lprintf("Welcome, \"%s\" from (%d,%d)",n2,
    356                dfp->base.src_tank_x, dfp->base.src_tank_y);*/
    357 
    358         settank(dfp->base.src_tank_x,dfp->base.src_tank_y,1);
    359     default:
    360         break;        
    361     }
    362 }
    363 
    364 void test(int x, int y)
    365 {
    366     static dfp_pkt_transfer tran;
    367     tran.fish.x = 100;
    368     tran.fish.y = 100;
    369     tran.fish.dx = 3;
    370     tran.fish.dy = 4;
    371     tran.fish.ttl = htons(1600);
    372     tran.uid.creator_tank_x = myX;
    373     tran.uid.creator_tank_y = myY;
    374     *((uint32 *) tran.uid.timestamp) = 0x10203040;
    375     
    376     strcpy(tran.fish.name,"Bitchin Fish");
    377 
    378     initiate(&tran,x,y);
    379 }
    380 
    381 unsigned char *fish_bm = 
    382     ".........XXXXXX.....XXX."
    383     ".....XXXXYYYYYYXX..XYYYX"
    384     "...XXYY.YYYYYYYYYXXYYYYX"
    385     ".XXYYYYYYYYYYYYYYYYYYYX."
    386     "...XXYYYYYYYYYYYYYXXYYYX"
    387     ".....XXXYYYYYYYXXX..XXYX"
    388     "........XXXYYYX.......XX"
    389     "...........XXXXX........"
    390 ;
    391 
    392 unsigned char *arrow_up[2] ={
    393     "....rr...."
    394     "...rrrr..."
    395     "..rrrrrr.."
    396     ".rrrrrrrr."
    397     "rrrrrrrrrr"
    398 ,
    399     "....gg...."
    400     "...gggg..."
    401     "..gggggg.."
    402     ".gggggggg."
    403     "gggggggggg"
    404 };
    405 unsigned char *arrow_dn[2] ={
    406     "rrrrrrrrrr"
    407     ".rrrrrrrr."
    408     "..rrrrrr.."
    409     "...rrrr..."
    410     "....rr...."
    411 ,
    412     "gggggggggg"
    413     ".gggggggg."
    414     "..gggggg.."
    415     "...gggg..."
    416     "....gg...."
    417 };
    418 unsigned char *arrow_lf[2] ={
    419     "....r"
    420     "...rr"
    421     "..rrr"
    422     ".rrrr"
    423     "rrrrr"
    424     "rrrrr"
    425     ".rrrr"
    426     "..rrr"
    427     "...rr"
    428     "....r"
    429 ,
    430     "....g"
    431     "...gg"
    432     "..ggg"
    433     ".gggg"
    434     "ggggg"
    435     "ggggg"
    436     ".gggg"
    437     "..ggg"
    438     "...gg"
    439     "....g"
    440 };
    441 unsigned char *arrow_rt[2] = {
    442     "r...."
    443     "rr..."
    444     "rrr.."
    445     "rrrr."
    446     "rrrrr"
    447     "rrrrr"
    448     "rrrr."
    449     "rrr.."
    450     "rr..."
    451     "r...."
    452 ,
    453     "g...."
    454     "gg..."
    455     "ggg.."
    456     "gggg."
    457     "ggggg"
    458     "ggggg"
    459     "gggg."
    460     "ggg.."
    461     "gg..."
    462     "g...."
    463 };
    464 
    465 int dist(int x0, int y0, int x1, int y1)
    466 {
    467     return((x0-x1)*(x0-x1)+(y0-y1)*(y0-y1));
    468 }
    469 
    470 void sendfish(fish *f, int tx, int ty)
    471 {
    472     f->xfer.fish.x = f->x;
    473     f->xfer.fish.y = f->y;
    474     f->xfer.fish.dx = f->dx;
    475     f->xfer.fish.dy = f->dy;
    476     f->xfer.fish.ttl = htons(1600);
    477     f->state = XMIT;
    478     f->xt = ticks+TIMEOUT;
    479     initiate(&f->xfer,tx,ty);
    480 }
    481 
    482 void prep(void)
    483 {
    484     int i;
    485     cnxn[C_LF].tx = myX - 1;
    486     cnxn[C_LF].ty = myY;
    487     cnxn[C_RT].tx = myX + 1;
    488     cnxn[C_RT].ty = myY;
    489     cnxn[C_UP].tx = myX;
    490     cnxn[C_UP].ty = myY - 1;
    491     cnxn[C_DN].tx = myX;
    492     cnxn[C_DN].ty = myY + 1;
    493     for(i=0;i<4;i++){
    494         cnxn[i].live = 0;
    495         pingtank(cnxn[i].tx,cnxn[i].ty);
    496     }
    497 }
    498 
    499 
    500 void vloop(void)
    501 {
    502     fish *f,*lf;
    503     fish *f2;
    504     
    505     int x,y,i;
    506     int xx, xy, xd;
    507     msg *m;    
    508     
    509     for(i=0;i<4;i++){
    510         cnxn[i].live = 0;
    511         pingtank(cnxn[i].tx,cnxn[i].ty);
    512     }
    513     
    514     for(;;){
    515         ticks++;
    516         if(!(ticks % 200)){
    517             lprintf("pinging now...");
    518             for(i=0;i<4;i++){
    519                 cnxn[i].live = 0;
    520                 pingtank(cnxn[i].tx,cnxn[i].ty);
    521             }
    522         }
    523 		os_sleep(snooze * 9000); /* 9ms increments */
    524         vga_fillX();
    525 #ifdef LOGGING               
    526         sem_acquire(sem_msgs);
    527         if(msgcount > logsize){
    528             msgcount--;
    529             m = first_msg;
    530             first_msg = first_msg->next;
    531             free(m);
    532         }
    533         if(logging){
    534             for(y=16,m = first_msg; (y < 161) && m; m=m->next, y +=8){
    535                 vga_blit_str(m->buf,15,y,'#');
    536             }
    537         }
    538         sem_release(sem_msgs);
    539 #endif        
    540         sem_acquire(sem_fish);
    541         for(lf=NULL,f=first;f;f=f->next){
    542             if(f->state == DEAD && lf){
    543                 lprintf("Expiring \"%s\"",f->name);
    544                 lf->next = f->next;
    545                 free(f);
    546                 f = lf;
    547                 continue;
    548             }
    549             if((f->state == XMIT) && (ticks > f->xt)) {
    550                 cnxn[f->dest].live = 0;
    551                 f->state = LIVE;
    552                 st_rej++;
    553             }
    554             if(f->state == LIVE){
    555                 xx = xy = 0;
    556                 xd = -1;
    557                 x = f->x;
    558                 y = f->y;
    559                 if(f->x < 0){
    560                     xx = 1;
    561                     if(cnxn[C_LF].live) {
    562                         xd = C_LF;
    563                         f->x = 254;
    564                     }
    565                 }
    566                 if(f->x > 255){
    567                     xx = 1;
    568                     if(cnxn[C_RT].live) {
    569                         xd = C_RT;
    570                         f->x = 1;
    571                     }                        
    572                 }
    573                 if(f->y < 0){
    574                     xy = 1;
    575                     if(cnxn[C_UP].live) {
    576                         if(xd == -1) {
    577                             xd = C_UP;
    578                             f->y = 254;
    579                         }
    580                     }
    581                 }
    582                 if(f->y > 255) {
    583                     xy = 1;
    584                     if(cnxn[C_DN].live) {
    585                         if(xd == -1) {
    586                             xd = C_DN;
    587                             f->y = 1;
    588                         }
    589                     }    
    590                 }
    591                 if(!sticky && !recluse && (xd != -1)) {
    592                     f->dest = xd;
    593                     sendfish(f,cnxn[xd].tx,cnxn[xd].ty);
    594                 }
    595                 if(xx){
    596                     f->dx = - f->dx;
    597                     f->x = x + f->dx;
    598                 }                    
    599                 if(xy){
    600                     f->dy = - f->dy;
    601                     f->y = y + f->dy;
    602                 }
    603                 if(xd != -1) continue;
    604 #ifdef XXX
    605                     /* collision ? */
    606                 {
    607                     int xc,yc;
    608                     xc = f->x + 12;
    609                     yc = f->y + 4;
    610                     
    611                     for(f2 = first; f2; f2 = f2->next){
    612                         if((f2 == f) || (f2->state != LIVE)) continue;
    613                         if(dist(xc,yc,f2->x+12,f2->y+4) < 100){
    614                             if(collision){
    615                                 f->dx = - f->dx;
    616                                 f->dy = - f->dy;
    617                             }
    618                             if(!strcmp(f->name,"killer")) {
    619                                 f2->state = DEAD;
    620                             }
    621                             if(!strcmp(f2->name,"killer")){
    622                                 f->state = DEAD;
    623                             }
    624                             break;
    625                         }
    626                     }
    627                 }
    628                     /* collision - */
    629 #endif
    630                 f->x += f->dx;
    631                 f->y += f->dy;
    632                 x = (f->x * (320-24)) / 256;
    633                 y = (f->y * (200-16)) / 256 + 8;
    634                 
    635                 if(f->dx < 0){
    636                     vga_blit_trans(f->bitmap,x,y,24,8);
    637                 } else {
    638                     vga_blit_trans_r(f->bitmap,x,y,24,8);                
    639                 }
    640                 vga_blit_str(f->name,x,y-8,'w');
    641             }
    642             lf = f;
    643         }
    644         sem_release(sem_fish);
    645 
    646 
    647         vga_blit_trans(arrow_up[cnxn[C_UP].live],320/2-5,0,10,5);
    648         vga_blit_trans(arrow_dn[cnxn[C_DN].live],320/2-5,200-9,10,5);
    649         vga_blit_trans(arrow_lf[cnxn[C_LF].live],0,100-5,5,10);
    650         vga_blit_trans(arrow_rt[cnxn[C_RT].live],320-6,100-5,5,10);
    651        /* if(logo) vga_blit_trans(blt,319-blt_w,2,blt_w,blt_h); */
    652         if(sticky) vga_blit_str("STICKY",0,0,'r');
    653         if(recluse) vga_blit_str("RECLUSIVE",8*7,0,'r');
    654         if(borg) vga_blit_str("BORG",320-(8*6),0,'r');
    655         
    656         if(keybuf[0]){
    657             vga_fill(320,10,0,179,'b');
    658             vga_blit_str(keybuf2,1,180,'w');
    659         }
    660         vga_swap_buffers();
    661     }
    662 }
    663 
    664 int bc = 0;
    665 
    666 void newfish(int x, int y, int dx, int dy, char *n)
    667 {
    668     fish *f = (fish *) malloc(sizeof(fish));
    669     
    670     char bf[16];
    671     
    672     st_recv++;
    673     if(borg) {
    674         n = bf;
    675         snprintf(n,16,"Borg (%d)",bc++);
    676         bf[15]=0;
    677     }
    678     f->x = x;
    679     f->y = y;
    680     f->dx = dx;
    681     f->dy = dy;
    682     strncpy(f->name,n,16);
    683     f->name[16]=0;
    684     f->bitmap = fish_bm;
    685     f->state = LIVE;
    686     f->xfer.uid.creator_tank_x = myX;
    687     f->xfer.uid.creator_tank_y = myY;
    688     *((uint32 *)f->xfer.uid.timestamp) = 0x1000000 + ticks;
    689         /*XXX */
    690     
    691     strcpy(f->xfer.fish.name,f->name);
    692     sem_acquire(sem_fish);
    693     f->next = first;
    694     first = f;
    695     sem_release(sem_fish);
    696     st_count++;
    697 }
    698 
    699 
    700 
    701 void vinit(void)
    702 {
    703     int i;
    704     void *vmem = 0xA0000;
    705 	area_create(64*1024, 0, &vmem, AREA_PHYSMAP);
    706 
    707     vga_set_sram(vmem);
    708     vga_set_mode(320,200,8);
    709 
    710 	vmem = malloc(64*1024);
    711 	vga_set_vram(vmem);
    712 
    713     vga_set_palette('.',0,0,255);
    714     vga_set_palette('w',255,255,255);
    715     vga_set_palette('X',255,0,0);
    716     vga_set_palette('Y',255,255,0);
    717     vga_set_palette('#',0,255,0);
    718     vga_set_palette('g',0,255,0);
    719     vga_set_palette('r',255,0,0);
    720     vga_set_palette('b',0,0,0);
    721     vga_set_palette('L',0,255,0);
    722     for(i=0;i<50;i++){
    723         vga_set_palette(128+i,0,0,12+i);
    724     }
    725     
    726     vga_fill_grad(320,200,0,0);
    727     vga_swap_buffers();
    728     
    729     lprintf("fish: vinit()");
    730 
    731     newfish(160,160,3,3,"fish");
    732     newfish(100,40,-1,2,"not fish");
    733 }
    734 
    735 void command(char *str);
    736 
    737 void fishmain(void)
    738 {	
    739     int once = 1;
    740     unsigned char data[1500];
    741     msg_hdr_t msg;
    742     int i;
    743     int size;
    744     net_cmd cmd;
    745     unsigned char ip[4];
    746 
    747     sem_fish = sem_create(1, "fish_lock");
    748     sem_msgs = sem_create(1, "msgs_lock");
    749     
    750     keybuf2[0] = '>';
    751     keybuf2[1] = ' ';
    752     
    753     if((port_net = namer_find("net",0)) < 1) WITH_NET = 0;
    754     if((port_net_xmit = namer_find("net_xmit",0)) < 1) WITH_NET = 0;
    755   
    756     port_fish = port_create(0, "fish_tell_port");
    757     namer_register(port_fish, "fish:tell");
    758 
    759     vinit();
    760 
    761     os_thread(vloop);
    762 /*    os_thread(restarter); */
    763     
    764     lprintf("fish: port=%d, console=%d, net=%d\n",
    765            port_fish, port_console, port_net);
    766 
    767 	if(WITH_NET){    
    768 		msg.flags = 0;
    769 		msg.src = port_fish;
    770 		msg.dst = port_net;
    771 		msg.size = 8;
    772 		msg.data = &cmd;
    773 		
    774 		cmd.cmd = NET_IP;
    775 		cmd.port = 0;
    776 		old_port_send(&msg);
    777 		msg.src = port_net_xmit;
    778 		msg.dst = port_fish;
    779 		msg.size = 4;
    780 		msg.data = ip;
    781 		old_port_recv(&msg);
    782 
    783 		lprintf("IP = %d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]);
    784 		
    785 		myX = (ip[3] >> 3) & 0x07;
    786 		myY = (ip[3]) & 0x07;
    787 		lprintf("tank @ %d,%d",myX, myY);
    788 		
    789 		msg.flags = 0;
    790 		msg.src = port_fish;
    791 		msg.dst = port_net;
    792 		msg.size = 8;
    793 		msg.data = &cmd;
    794 		
    795 		cmd.cmd = NET_CONNECT;
    796 		cmd.port = 5049;
    797 		old_port_send(&msg);
    798 	} else {
    799 		lprintf("no network support\n");
    800 	}
    801 
    802     prep();
    803 #if 0
    804     os_thread(keythread);
    805 #endif    
    806     for(;;){
    807         msg.flags = 0;
    808         msg.src = 0;
    809         msg.dst = port_fish;
    810         msg.size = 1500;
    811         msg.data = data;
    812 
    813         if((size = old_port_recv(&msg)) > 0){
    814 			if(WITH_NET && (msg.src == port_net_xmit)){
    815 				dofish((dfp_pkt_transfer *) data);
    816 			} else {
    817 				uint32 response = 0;
    818 				data[size]=0;
    819 				command(data);
    820 				msg.dst = msg.src;
    821 				msg.src = port_fish;
    822 				msg.size = 4;
    823 				msg.data = &response;
    824 				old_port_send(&msg);	
    825 			}
    826         }
    827     }
    828 }
    829 
    830 int main(void)
    831 {
    832 	os_thread(fishmain);
    833     return 0;
    834 }
    835 
    836 void command(char *str)
    837 {
    838     if(!strncmp(str,"tank",4)){
    839         int x,y;
    840         x = str[5]-'0';
    841         y = str[6]-'0';
    842         if(x <0 || x>9 || y<0 || x>9) return;
    843         myX = x;
    844         myY = y;
    845         prep();
    846         lprintf("relocating tank to %d,%d",myX,myY);
    847         return;
    848     }
    849     if(!strncmp(str,"stats",5)){
    850         lprintf("count: %d sent: %d recv: %d rej: %d",st_count,st_sent,st_recv,st_rej);
    851         return;
    852     }
    853     if(!strncmp(str,"sticky",6)){
    854         sticky = !sticky;
    855         lprintf("Sticky mode %s",sticky?"on":"off");
    856         return;
    857     }
    858     if(!strncmp(str,"recluse",7)){
    859         recluse = !recluse;
    860         lprintf("Recluse mode %s",recluse?"on":"off");
    861         return;
    862     }
    863     if(!strncmp(str,"panic",5)){
    864         fish *f;
    865         sem_acquire(sem_fish);
    866         for(f=first;f;f=f->next) {
    867             f->dx *= 2;
    868             f->dy *= 2;
    869         }
    870         sem_release(sem_fish);
    871         return;
    872     }
    873     if(!strncmp(str,"purge",5)){
    874         fish *f;
    875         sem_acquire(sem_fish);
    876         for(f=first;f;f=f->next) {
    877             if(f->state == LIVE) f->state = DEAD;
    878         }
    879         st_count = 0;
    880         sem_release(sem_fish);
    881         return;
    882     }
    883     if(!strncmp(str,"logo",4)){
    884         logo = !logo;
    885         return;
    886     }
    887     if(!strncmp(str,"collision",9)){
    888         collision = !collision;
    889         return;
    890     }
    891     if(!strncmp(str,"snooze ",7)){
    892         snooze = str[7]-'0';
    893         if(snooze < 3 || snooze > 9) snooze = 5;
    894         return;
    895     }
    896     if(!strncmp(str,"borg",4)){
    897         borg = !borg;
    898         lprintf("Borg mode %s",borg?"on - prepare to assimilate":"off");
    899         return;
    900     }
    901     if(!strncmp(str,"eject",5)){
    902         int i;
    903         lprintf("Ejecting all fish now!");
    904         for(i=0;i<4;i++){
    905             if(cnxn[i].live){
    906                 fish *f;
    907                 sem_acquire(sem_fish);
    908                 for(f = first; f; f=f->next){
    909                     if(f->state == LIVE){
    910                         sendfish(f,cnxn[i].tx,cnxn[i].ty);
    911                     }
    912                 }
    913                 sem_release(sem_fish);
    914                 return;
    915             }
    916         }
    917         return;
    918     }
    919 	if(!strncmp(str,"debug",5)){
    920 		os_debug();
    921 		return;
    922 	}
    923     if(!strncmp(str,"log",3)){
    924         logging = !logging;
    925         return;
    926     }
    927     if(!strncmp(str,"new ",3)) {
    928         str+=4;
    929         str[16]=0;
    930         if(str[0] == '*'){
    931             newfish(100,100,-3,-5,str+1);
    932             newfish(130,100, 3,-5,str+1);
    933             newfish(160,100,-3, 5,str+1);
    934             newfish(190,100, 3, 5,str+1);
    935             newfish(100,150,-3,-5,str+1);
    936             newfish(130,150, 3,-5,str+1);
    937             newfish(160,150,-3, 5,str+1);
    938             newfish(190,150, 3, 5,str+1);
    939         } else {
    940             newfish(160,160,-3,5,str);
    941         }
    942     }
    943     
    944 }
    945 
    946                 
    947 /* keyboard handler */
    948 
    949 #define ESC 27
    950 #define BS 8
    951 #define TAB 9
    952 #define CR 13
    953 
    954 char ScanTable [] =  {' ', ESC, '1', '2', '3', '4', '5', '6', '7', '8',
    955                       '9', '0', '-', '=', BS,  TAB, 'q', 'w', 'e', 'r',
    956                       't', 'y', 'u', 'i', 'o', 'p', '[', ']', CR,  ' ',
    957                       'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',
    958                       '\'', '~', ' ', '\\', 'z', 'x', 'c', 'v', 'b', 'n',
    959                       'm', ',', '.', '/', ' ', ' ', ' ', ' ', ' '};
    960 char ShiftTable [] = {' ', ESC, '!', '@', '#', '$', '%', '^', '&', '*',
    961                       '(', ')', '_', '+', ' ', ' ', 'Q', 'W', 'E', 'R',
    962                       'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', CR,  ' ',
    963                       'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',
    964                       '\"', '~', ' ', '|', 'Z', 'X', 'C', 'V', 'B', 'N',
    965                       'M', '<', '>', '?', ' ', ' ', ' ', ' ', ' '};
    966 #define LSHIFT 42
    967 #define RSHIFT 54
    968 
    969 void keythread(void)
    970 {
    971     int shift = 0;    
    972     int key;
    973 
    974     os_handle_irq(1);
    975 
    976     for(;;) {
    977         os_sleep_irq();
    978         key = inb(0x60);
    979         switch(key){
    980         case LSHIFT:
    981         case RSHIFT:
    982             shift = 1;
    983             break;
    984         case LSHIFT | 0x80:
    985         case RSHIFT | 0x80:
    986             shift = 0;
    987             break;
    988         default:
    989             if(key & 0x80){
    990                         /* break */
    991             } else {
    992                 if(key < 59){
    993                     key = shift ? ShiftTable[key] : ScanTable[key];
    994                     switch(key){
    995                     case CR:
    996                         if(keyptr) command(keybuf);
    997                     case ESC:
    998                         keybuf[0] = 0;
    999                         keyptr = 0;
   1000                         break;
   1001                     case BS:
   1002                         if(keyptr){
   1003                             keyptr--;
   1004                             keybuf[keyptr]=0;
   1005                         }
   1006                         break;
   1007                     default:
   1008                         if(keyptr < MAXKEYS){
   1009                             keyptr++;
   1010                             keybuf[keyptr]=0;
   1011                             keybuf[keyptr-1]=key;
   1012                         }
   1013                         break;
   1014                     }
   1015                 }
   1016             }
   1017         }
   1018     }
   1019 
   1020 }