SYZYGY.SRC (21405B)
1 option binary ; Let's compile this for a non-HP computer... 2 align off ; And let's save some space with even-addresses allowed 3 4 ; From rtrevino@cpocd5.intel.com 5 ; 6 ; Several people have requested the source to syzygy, so here it is. 7 ; Actually it's the listing file. It would have been posted sooner, 8 ; but I wanted to add *some* comments at least, etc. Hopefully whoever 9 ; sent mail to me will see it. Anyways, I guess we can all expect to 10 ; see tons more chip-48 programs posted now, as there is so much interest 11 ; in source code! :-) They are actually quite easy to write. 12 ; 13 ; Roy 14 ; 15 ; PS - has anyone used the shift instructions in chip48? The documentation 16 ; does not correlate with the "opcodes". How do they really work? 17 18 ; 19 ; SYZYGY is (c) copyright 1990 by Roy Trevino (RTT) 20 ; 21 ; Noncommercial distribution allowed, provided that this 22 ; copyright message is preserved, and any modified versions 23 ; are clearly marked as such. 24 ; 25 ; SYZYGY, via CHIP-48, makes use of undocumented low-level features 26 ; of the HP48SX calculator, and may or may not cause loss of data, 27 ; excessive battery drainage, and/or damage to the calculator 28 ; hardware. The Author takes no responsibility whatsoever for 29 ; any damage caused by the use of this program. 30 ; 31 ; THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR 32 ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 33 ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 ; PURPOSE. 35 ; 36 ; 37 ; Register usage (primary usage, may be others): 38 ; 39 ; v0 - scratch 40 ; v1 - x position of head 41 ; v2 - y position of head 42 ; v3 - current direction of head 43 ; v4 - pointer to segment table entry for head 44 ; v5 - previous direction of head 45 ; v6 - x position of tail 46 ; v7 - y position of tail 47 ; v8 - direction of tail 48 ; v9 - pointer to segment table entry for tail 49 ; va - count of points being added to length 50 ; vb - x position of target 51 ; vc - y position of target 52 ; vd - flags if target is on or off 53 ; ve - random on time for target 54 ; vf - carry/borrow/collision detect 55 56 57 up = #3 ; (9) key for up 58 down = #6 ; (6) key for down 59 left = #7 ; (1) key for left 60 right = #8 ; (2) key for right 61 62 ; 63 ; Start of a circular table to track each segment of the syzygy, 64 ; which consists of a direction and a length. 65 ; 66 ; The start of the table is at #800 instead of a label at the bottom 67 ; of the program (ie. base: end) because it seems to run faster 68 ; that way. 69 ; 70 71 base = #800 ; base of segment table 72 73 74 jp start 75 76 ; copyright notice 77 dw #8d8d ; ->-> 78 dw #20a9 ; (c) 79 dw #3139 ; 19 80 dw #3930 ; 90 81 dw #2052 ; R 82 dw #5454 ; TT 83 dw #208e ; <- 84 dw #8e00 ; <- 85 start: 86 call drawbord 87 call drawtitle 88 waitkp1: 89 ld v0,#f ; wait for (+) (keep border) 90 sknp v0 91 jp starty 92 ld v0,#e ; wait for (-) (borderless) 93 sknp v0 94 jp startn 95 jp waitkp1 96 starty: 97 call drawtitle ; erase title (keep border) 98 jp initgame 99 startn: 100 cls ; erase everything (borderless) 101 jp initgame 102 ; 103 ; initialization routines 104 ; 105 initgame: 106 ; 107 ; initial head position near middle of screen 108 ; 109 rnd v1,#1f ; x-pos = rnd(16,47) 110 add v1,#10 111 rnd v2,#f ; y-pos = rnd(8,23) 112 add v2,#8 113 rnd v3,#3 ; direction = rnd(0,3) 114 ld v5,v3 ; last head direction 115 ; 116 ; compute initial tail position 117 ; 118 ld v6,v1 ; start out same as head 119 ld v7,v2 120 ld v8,v3 ; tail direction 121 122 sne v8,#0 ; up 123 add v7,#1 124 sne v8,#1 ; down 125 add v7,#ff 126 sne v8,#2 ; left 127 add v6,#1 128 sne v8,#3 ; right 129 add v6,#ff 130 ; 131 ; draw initial syzygy, save initial segment to table 132 ; 133 ld i,dot 134 drw v1,v2,#1 ; draw head 135 drw v6,v7,#1 ; draw tail 136 137 ld v4,#f0 ; init ptr to head vector 138 ld v9,#f1 ; init ptr to tail vector 139 140 ld i,base ; save direction 141 add i,v4 142 ld v0,v3 143 ld [i],v0 144 add v4,#1 ; increment head ptr 145 ld i,base ; save segment count 146 add i,v4 147 ld v0,#1 148 ld [i],v0 149 150 ; 151 ; compute coordinates and value of first target 152 ; plus set up flag and time until target 153 ; 154 call rndtarg 155 156 157 ld va,#0 ; additional length 158 159 ; 160 ; initial addition to syzygy for test purposes 161 ; 162 add va,#0 163 ; 164 ; main loop begins here 165 ; 166 loop: 167 ld v0,dt ; check if a target is due 168 se v0,#0 169 jp endtarg 170 se vd,#0 171 jp targoff 172 173 ld v0,#0 ; draw target 174 ld f,v0 175 drw vb,vc,#5 176 177 se vf,#1 ; if on body, erase immediately 178 jp targon 179 drw vb,vc,#5 180 call rndtarg ; set up new target 181 ld dt,v0 ; no delay though 182 jp endtarg ; process at least one move 183 184 targon: 185 ld dt,ve ; set up on-time 186 ld vd,#1 ; set flag to denote on 187 ld ve,#0 ; number of points unless hit 188 jp endtarg 189 190 targoff: 191 ld v0,ve ; erase old target 192 ld f,v0 193 drw vb,vc,#5 194 195 call rndtarg ; set up new target 196 197 endtarg: 198 ld v0,up ; check for user input 199 sknp v0 200 ld v3,#0 ; new direction 201 202 ld v0,down 203 sknp v0 204 ld v3,#1 205 206 ld v0,left 207 sknp v0 208 ld v3,#2 209 210 ld v0,right 211 sknp v0 212 ld v3,#3 213 ; 214 ; compute next head position 215 ; 216 sne v3,#0 ; up 217 add v2,#ff 218 sne v3,#1 ; down 219 add v2,#1 220 sne v3,#2 ; left 221 add v1,#ff 222 sne v3,#3 ; right 223 add v1,#1 224 ; 225 ; draw next head position 226 ; 227 ld i,dot 228 drw v1,v2,#1 229 ; 230 ; check for collision 231 ; 232 se vf,#1 233 jp chkhead 234 ; 235 ; if collision is due to target, add points (else die) 236 ; this also means no doubling back on self 237 ; 238 se vd,#1 ; check if target is even on 239 jp endgame 240 241 ld v0,#3f ; mask off extra x and y bits 242 and v1,v0 243 ld v0,#1f 244 and v2,v0 245 246 ld v0,vb ; check if < target on left 247 subn v0,v1 248 se vf,#1 249 jp endgame 250 251 ld v0,vb ; check if > target on right 252 add v0,#3 253 sub v0,v1 254 se vf,#1 255 jp endgame 256 257 ld v0,vc ; check if < target on top 258 subn v0,v2 259 se vf,#1 260 jp endgame 261 262 ld v0,vc ; check if > target on bottom 263 add v0,#4 264 sub v0,v2 265 se vf,#1 266 jp endgame 267 ; 268 ; if made it this far, add points, erase target, etc 269 ; 270 ld v0,#4 ; beep (actually, a "bip") 271 ld st,v0 272 273 rnd ve,#7 ; award rnd(2,9) points 274 add ve,#2 ; 275 add va,ve ; add points 276 277 ld i,dot ; temporarily erase head 278 drw v1,v2,#1 279 ld v0,#0 ; erase target 280 ld f,v0 281 drw vb,vc,#5 282 ld v0,ve ; draw points instead 283 ld f,v0 284 drw vb,vc,#5 285 286 ld v0,#30 ; delay for a while 287 ld dt,v0 288 targwait: 289 ld v0,dt 290 se v0,#0 291 jp targwait 292 293 ld i,dot 294 drw v1,v2,#1 ; redraw head 295 ; 296 ; if direction changed, create a new segment record 297 ; 298 chkhead: 299 sne v3,v5 300 jp conthead 301 302 add v4,#1 ; new segment record 303 ld i,base 304 add i,v4 305 ld v0,v3 ; save direction 306 ld [i],v0 307 add v4,#1 ; point to counter 308 ld i,base ; initialize segment count to 309 add i,v4 310 ld v0,#0 311 ld [i],v0 312 313 ld v5,v3 ; reset previous direction 314 315 conthead: 316 ld i,base ; simply add to current record 317 add i,v4 318 ld v0,[i] 319 add v0,#1 ; increment head count 320 ld [i],v0 321 ; 322 ; don't erase tail if adding points to length 323 ; 324 sne va,#0 325 jp contpts ; if pts = 0, continue normally 326 327 ld v0,#c ; delay just a little to compensate 328 delhead: 329 add v0,#ff 330 se v0,#0 331 jp delhead 332 333 add va,#ff ; decrement and loop 334 jp loop 335 336 contpts: 337 ; 338 ; erase last tail position 339 ; 340 ld i,dot 341 drw v6,v7,#1 342 343 ; 344 ; compute next tail position 345 ; 346 sne v8,#0 ; up 347 add v7,#ff 348 sne v8,#1 ; down 349 add v7,#1 350 sne v8,#2 ; left 351 add v6,#ff 352 sne v8,#3 ; right 353 add v6,#1 354 355 ld i,base ; get tail segment record 356 add i,v9 357 ld v0,[i] 358 add v0,#ff ; decrement tail count 359 ld [i],v0 ; save 360 se v0,#0 ; if zero, get new record 361 jp loop 362 363 add v9,#1 ; new segment record 364 ld i,base ; get new direction 365 add i,v9 366 ld v0,[i] 367 ld v8,v0 368 add v9,#1 ; point to new count 369 ; 370 ; end of main loop 371 ; 372 jp loop 373 ; 374 ; endgame routines 375 ; 376 endgame: 377 ld v0,#d ; beep 378 ld st,v0 379 380 ld v0,#b ; wait for (space) keypress 381 endkp: 382 skp v0 383 jp endkp 384 ; 385 ; finish up tail to count points: digits are in vd:vc:vb format 386 ; note that it is theoretically possible to get 64*32=2048 points, 387 ; while three digits will only hold 999. Unlikely but possible. 388 ; 389 ld vb,#1 ; one's digit 390 ld vc,#0 ; ten's digit 391 ld vd,#0 ; hundred's digit 392 393 endtail: 394 ; 395 ; increment score 396 ; 397 add vb,#1 398 se vb,#a 399 jp endtailcont 400 ld vb,#0 401 add vc,#1 402 se vc,#a 403 jp endtailcont 404 ld vc,#0 405 add vd,#1 406 ; 407 ; compute next tail position to add up score 408 ; 409 endtailcont: 410 ld i,dot ; erase last tail position 411 drw v6,v7,#1 412 413 sne v8,#0 ; up 414 add v7,#ff 415 sne v8,#1 ; down 416 add v7,#1 417 sne v8,#2 ; left 418 add v6,#ff 419 sne v8,#3 ; right 420 add v6,#1 421 422 ld i,base ; get tail segment record 423 add i,v9 424 ld v0,[i] 425 add v0,#ff ; decrement tail count 426 ld [i],v0 ; save 427 se v0,#0 ; if zero, get new record 428 jp endtail 429 430 sne v9,v4 ; done when pointers are equal 431 jp drawscore 432 433 add v9,#1 ; new segment record 434 ld i,base ; get new direction 435 add i,v9 436 ld v0,[i] 437 ld v8,v0 438 add v9,#1 ; point to new count 439 jp endtail 440 ; 441 ; draw score 442 ; 443 drawscore: 444 cls 445 ld v6,#11 ; draw border 446 ld v7,#9 447 ld v8,#2f 448 ld v9,#17 449 ld i,vbar 450 drw v6,v7,#e 451 drw v8,v7,#e 452 add v7,#ff 453 ld i,hbar 454 drw v6,v7,#1 455 drw v6,v9,#1 456 add v6,#8 457 drw v6,v7,#1 458 drw v6,v9,#1 459 add v6,#8 460 drw v6,v7,#1 461 drw v6,v9,#1 462 add v6,#8 463 ld i,hbar2 464 drw v6,v7,#1 465 drw v6,v9,#1 466 467 ld i,sc ; show score (not high score yet) 468 ld v6,#13 469 ld v7,#11 470 call showscore 471 ; 472 ; figure out if it's the high score, save it if it is 473 ; 474 ld i,high_score ; recover old high score into v3v2v1 475 ld v3,[i] 476 477 sne v3,vd ; if =, check next digit 478 jp conthigh1 479 ld v0,v3 ; if borrow, it's a new high score! 480 sub v0,vd 481 se vf,#1 482 jp savehigh 483 jp drawhigh 484 485 conthigh1: 486 sne v2,vc ; etc. as above for other digits 487 jp conthigh2 488 ld v0,v2 489 sub v0,vc 490 se vf,#1 491 jp savehigh 492 jp drawhigh 493 494 conthigh2: 495 ld v0,v1 496 sub v0,vb 497 se vf,#0 498 jp drawhigh 499 500 savehigh: 501 ld i,high_score 502 ld v3,vd ; save new high score 503 ld v2,vc 504 ld v1,vb 505 ld [i],v3 506 ; 507 ; draw the high score 508 ; 509 drawhigh: 510 ld i,high_score 511 ld v3,[i] 512 ld v6,#13 513 add v7,#f9 514 ld vd,v3 515 ld vc,v2 516 ld vb,v1 517 ld i,hi 518 call showscore 519 ; 520 ; random memory wasting stuff goes here 521 ; 522 waitkp2: 523 524 rnd v1,#3f ; get random position 525 rnd v2,#1f 526 527 ld v0,#d ; check left 528 sub v0,v1 529 se vf,#0 530 jp drawrand 531 532 ld v0,#30 ; check right 533 subn v0,v1 534 se vf,#0 535 jp drawrand 536 537 ld v0,#3 ; check top 538 sub v0,v2 539 se vf,#0 540 jp drawrand 541 542 ld v0,#18 ; check bottom 543 subn v0,v2 544 se vf,#0 545 jp drawrand 546 jp chkkp2 547 548 drawrand: 549 rnd v3,#0f ; draw random number 550 ld f,v3 551 drw v1,v2,#5 552 553 chkkp2: 554 ld v0,#f ; check for keypress 555 sknp v0 556 jp conty 557 ld v0,#e 558 sknp v0 559 jp contn 560 jp waitkp2 561 562 conty: 563 cls 564 call drawbord 565 jp initgame 566 contn: 567 cls 568 jp initgame 569 ; 570 ; function showscore: 571 ; digits in vd:vc:vb, descriptor in i, initial coords in v6,v7 572 ; 573 showscore: 574 drw v6,v7,#5 575 ld i,col 576 add v6,#2 577 drw v6,v7,#4 578 ld f,vd 579 add v6,#a 580 drw v6,v7,#5 581 ld f,vc 582 add v6,#5 583 drw v6,v7,#5 584 ld f,vb 585 add v6,#5 586 drw v6,v7,#5 587 588 ret 589 ; 590 ; function drawbord: 591 ; draw border, try to do it fast 592 ; 593 drawbord: 594 ld i,hbar 595 ld v1,#0 ; left 596 ld v2,#0 ; right 597 ld v6,#1f ; lower 598 horiz1: 599 drw v1,v2,#1 ; draw x,0 600 drw v1,v6,#1 ; draw x,31 601 add v1,#8 602 se v1,#40 ; same as 0 603 jp horiz1 604 605 ld i,vbar 606 ld v2,#1 607 ld v5,#3f 608 drw v1,v2,#f 609 drw v5,v2,#f 610 add v2,#f 611 drw v1,v2,#f 612 drw v5,v2,#f 613 614 ret 615 ; 616 ; function drawtitle: draws game title 617 ; 618 drawtitle: 619 ld v1,#c 620 ld v2,#7 621 ld i,Title_s 622 drw v1,v2,#a 623 ld i,Title_y 624 add v1,#6 625 drw v1,v2,#a 626 ld i,Title_z 627 add v1,#6 628 drw v1,v2,#a 629 ld i,Title_y 630 add v1,#6 631 drw v1,v2,#a 632 ld i,Title_g 633 add v1,#6 634 drw v1,v2,#a 635 ld i,Title_y 636 add v1,#6 637 drw v1,v2,#a 638 639 ld v1,#e 640 ld v2,#18 641 ld i,Title_v 642 drw v1,v2,#3 643 ld i,vers 644 add v1,#8 645 add v2,#ff 646 drw v1,v2,#4 647 add v1,#9 648 add v2,#fe 649 ld i,Title_r 650 drw v1,v2,#6 651 add v1,#6 652 add v2,#1 653 ld i,Title_tt 654 drw v1,v2,#5 655 656 ret 657 ; 658 ; function rndtarg: 659 ; returns coords as (vb,vc) 660 ; 0 in vd 661 ; time until target in dt 662 ; on-time value ve 663 ; 664 rndtarg: 665 ; 666 ; x-pos = rnd(1,59) 667 ; 668 ld vd,#c5 ; -#3b (-59d) 669 rndx: rnd vb,#3f ; rnd (0,63) 670 ld ve,vb 671 add ve,vd ; check if > 58 672 sne vf,#1 673 jp rndx ; try again if too big 674 675 add vb,#1 676 ; 677 ; y-pos = rnd(1,26) 678 ; 679 680 ld vd,#e6 ; -#1a (-26d) 681 rndy: rnd vc,#1f 682 ld ve,vc 683 add ve,vd 684 sne vf,#1 685 jp rndy 686 add vc,#1 687 ld vd,#0 ; flag marking new target 688 rnd ve,#3f ; random off delay (64 - 127) 689 add ve,#40 690 ld dt,ve 691 rnd ve,#3f ; random on delay (64 - 127) 692 add ve,#40 693 ret 694 695 dot: dw #8000 ; dot for syzygy 696 hbar: dw #ff00 ; horizontal border segment 697 hbar2: dw #fe00 698 vbar: dw #8080 ; vertical border segment 699 dw #8080 700 dw #8080 701 dw #8080 702 dw #8080 703 dw #8080 704 dw #8080 705 dw #8080 706 ; 707 ; True memory wasting stuff goes here (but why not?) 708 ; 709 Title_s: ; s character 710 db $...11111 711 db $...1.... 712 db $...1.... 713 db $...1.... 714 db $...11111 715 db $.......1 716 db $.......1 717 db $.......1 718 db $.......1 719 db $...11111 720 721 Title_y: ; y character 722 db $...1...1 723 db $...1...1 724 db $...1...1 725 db $...1...1 726 db $...11111 727 db $.....1.. 728 db $.....1.. 729 db $.....1.. 730 db $.....1.. 731 db $.....1.. 732 733 Title_z: ; z character 734 db $...11111 735 db $.......1 736 db $......1. 737 db $......1. 738 db $.....1.. 739 db $.....1.. 740 db $....1... 741 db $....1... 742 db $...1.... 743 db $...11111 744 745 Title_g: ; g character 746 db $...11111 747 db $...1...1 748 db $...1.... 749 db $...1.... 750 db $...1.... 751 db $...1..11 752 db $...1...1 753 db $...1...1 754 db $...1...1 755 db $...11111 756 757 Title_v: ; v character for version 758 db $.....1.1 759 db $.....1.1 760 db $......1. 761 db $........ 762 763 vers: ; version number characters 764 db $.111...1 765 db $.1.1...1 766 db $.1.1...1 767 db $.111.1.1 768 769 770 Title_r: ; R character for signature 771 db $....11.. 772 db $...1..1. 773 db $...1111. 774 db $...1.1.. 775 db $...1..1. 776 db $....1..1 777 778 Title_tt: ; tt characters for signature 779 db $...1.1.. 780 db $..11111. 781 db $...1.1.1 782 db $...1.1.1 783 db $..1.1.1. 784 db $........ 785 786 787 sc: ; sc characters for score 788 db $.111.111 789 db $.1...1.. 790 db $..1..1.. 791 db $...1.1.. 792 db $.111.111 793 db $........ 794 795 hi: ; hi character for high score 796 db $.1.1.111 797 db $.1.1..1. 798 db $.111..1. 799 db $.1.1..1. 800 db $.1.1.111 801 db $........ 802 803 col: dw #0001 ; : character for scores 804 dw #0001 805 806 high_score: 807 dw #0000 ; high score storage 808 dw #0000