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 }