CTRLSUBS.S (28089B)
1 * ctrlsubs 2 org = $d000 3 tr on 4 lst off 5 *------------------------------- 6 * 7 * PRINCE OF PERSIA 8 * Copyright 1989 Jordan Mechner 9 * 10 *------------------------------- 11 * 12 * Misc. subroutines relating to character control & movement 13 * 14 *------------------------------- 15 org org 16 17 jmp GETFRAME 18 jmp GETSEQ 19 jmp GETBASEX 20 jmp GETBLOCKX 21 jmp GETBLOCKXP 22 23 jmp GETBLOCKY 24 jmp GETBLOCKEJ 25 jmp ADDCHARX 26 jmp GETDIST 27 jmp GETDIST1 28 29 jmp GETABOVEBEH 30 jmp RDBLOCK 31 jmp RDBLOCK1 32 jmp SETUPSWORD 33 jmp GETSCRNS 34 35 jmp ADDGUARDOBJ 36 jmp OPJUMPSEQ 37 jmp GETEDGES 38 jmp INDEXCHAR 39 jmp QUICKFG 40 41 jmp CROPCHAR 42 jmp GETLEFT 43 jmp GETRIGHT 44 jmp GETUP 45 jmp GETDOWN 46 47 jmp CMPSPACE 48 jmp CMPBARR 49 jmp ADDKIDOBJ 50 jmp ADDSHADOBJ 51 jmp ADDREFLOBJ 52 53 jmp LOADKID 54 jmp LOADSHAD 55 jmp SAVEKID 56 jmp SAVESHAD 57 jmp SETUPCHAR 58 59 jmp GETFRAMEINFO 60 jmp INDEXBLOCK 61 jmp MARKRED 62 jmp MARKFRED 63 jmp MARKWIPE 64 65 jmp MARKMOVE 66 jmp MARKFLOOR 67 jmp UNINDEX 68 jmp QUICKFLOOR 69 jmp UNEVENFLOOR 70 71 jmp MARKHALF 72 jmp ADDSWORDOBJ 73 jmp GETBLOCKYP 74 jmp CHECKLEDGE 75 jmp GET2INFRONT 76 77 jmp CHECKSPIKES 78 jmp RECHARGEMETER 79 jmp ADDFCHARX 80 jmp FACEDX 81 jmp JUMPSEQ 82 83 jmp GETBASEBLOCK 84 jmp LOADKIDWOP 85 jmp SAVEKIDWOP 86 jmp GETOPDIST 87 jmp LOADSHADWOP 88 89 jmp SAVESHADWOP 90 jmp BOOSTMETER 91 jmp GETUNDERFT 92 jmp GETINFRONT 93 jmp GETBEHIND 94 95 jmp GETABOVE 96 jmp GETABOVEINF 97 jmp CMPWALL 98 99 *------------------------------- 100 lst 101 put eq 102 lst 103 put gameeq 104 lst 105 put movedata 106 lst 107 put seqdata 108 lst 109 put soundnames 110 lst off 111 112 *------------------------------- 113 dum locals 114 115 tempright ds 1 116 ztemp ds 2 117 tempstate ds 1 118 ]cutdir ds 1 119 120 dend 121 122 *------------------------------- 123 * Misc. data 124 125 plus1 db -1,1 126 minus1 db 1,-1 127 128 maxmaxstr = 10 ;strength meter maximum 129 130 thinner = 3 131 132 *------------------------------- 133 * 134 * R E A D B L O C K 135 * 136 * In: A = screen # 137 * X = block x (0-9 onscreen) 138 * Y = block y (0-2 onscreen) 139 * 140 * Out: A,X = objid 141 * Y = block # (0-29) 142 * BlueType, BlueSpec set 143 * tempscrn,tempblockx,tempblocky = onscreen block coords 144 * 145 * - Offscreen block values are traced to their home screen 146 * - Screen 0 is treated as a solid mass 147 * 148 *------------------------------- 149 RDBLOCK 150 sta tempscrn 151 stx tempblockx 152 sty tempblocky 153 154 RDBLOCK1 155 jsr handler ;handle offscreen references 156 157 lda tempscrn 158 beq :nullscrn ;screen 0 159 jsr calcblue ;returns BlueType/Spec 160 161 ldy tempblocky 162 lda Mult10,y 163 clc 164 adc tempblockx 165 tay 166 lda (BlueType),y 167 and #idmask 168 tax ;return result in X & A 169 rts 170 171 :nullscrn lda #block 172 tax 173 rts 174 175 *------------------------------- 176 * Handle offscreen block references (recursive) 177 178 handler lda tempblockx 179 bpl :1 180 jsr offleft 181 jmp handler 182 183 :1 cmp #10 184 bcc :2 185 jsr offrt 186 jmp handler 187 188 :2 lda tempblocky 189 bpl :3 190 jsr offtop 191 jmp handler 192 193 :3 cmp #3 194 bcc :rts 195 jsr offbot 196 jmp handler 197 198 :rts rts 199 200 offtop clc 201 adc #3 202 sta tempblocky 203 204 lda tempscrn 205 jsr GETUP 206 sta tempscrn 207 rts 208 209 offbot sec 210 sbc #3 211 sta tempblocky 212 213 lda tempscrn 214 jsr GETDOWN 215 sta tempscrn 216 rts 217 218 offleft clc 219 adc #10 220 sta tempblockx 221 222 lda tempscrn 223 jsr GETLEFT 224 sta tempscrn 225 rts 226 227 offrt sec 228 sbc #10 229 sta tempblockx 230 231 lda tempscrn 232 jsr GETRIGHT 233 sta tempscrn 234 ]rts rts 235 236 *------------------------------- 237 * 238 * Get adjacent screen numbers 239 * 240 * In: A = original screen # 241 * Out: A = adjacent screen # 242 * 243 *------------------------------- 244 GETLEFT 245 beq ]rts 246 asl 247 asl 248 tax 249 lda MAP-4,x 250 ]rts rts 251 252 GETRIGHT 253 beq ]rts 254 asl 255 asl 256 tax 257 lda MAP-3,x 258 rts 259 260 GETUP 261 beq ]rts 262 asl 263 asl 264 tax 265 lda MAP-2,x 266 rts 267 268 GETDOWN 269 beq ]rts 270 asl 271 asl 272 tax 273 lda MAP-1,x 274 rts 275 276 *------------------------------- 277 * 278 * G E T S C R E E N S 279 * 280 * Get VisScrn's 8 surrounding screens from map 281 * (Store in scrnAbove, scrnBelow, etc.) 282 * 283 *------------------------------- 284 GETSCRNS 285 lda VisScrn 286 jsr GETLEFT 287 sta scrnLeft 288 289 lda VisScrn 290 jsr GETRIGHT 291 sta scrnRight 292 293 lda VisScrn 294 jsr GETUP 295 sta scrnAbove 296 297 lda VisScrn 298 jsr GETDOWN 299 sta scrnBelow 300 301 * and diagonals 302 303 lda scrnBelow 304 jsr GETLEFT 305 sta scrnBelowL 306 307 lda scrnBelow 308 jsr GETRIGHT 309 sta scrnBelowR 310 311 lda scrnAbove 312 jsr GETLEFT 313 sta scrnAboveL 314 315 lda scrnAbove 316 jsr GETRIGHT 317 sta scrnAboveR 318 ]rts rts 319 320 *------------------------------- 321 * 322 * G E T B A S E X 323 * 324 * In: Char data; frame data 325 * 326 * Out: A = character's base X-coord 327 * 328 *------------------------------- 329 GETBASEX 330 lda Fcheck 331 and #Ffootmark 332 ;# pixels to count in from left edge of image 333 eor #$ff 334 clc 335 adc #1 ;- Fcheck 336 337 clc 338 adc Fdx ;Fdx (+ = fwd, - = bkwd) 339 340 jmp ADDCHARX ;Add to CharX in direction char is facing 341 342 *------------------------------- 343 * 344 * Add A to CharX in direction char is facing 345 * 346 * In: A = # pixels to add (+ = fwd, - = bkwd) 347 * CharX = original char X-coord 348 * CharFace = direction char is facing 349 * 350 * Out: A = new char X-coord 351 * 352 *------------------------------- 353 ADDCHARX 354 bit CharFace ;-1 = left (normal) 355 bpl :right ;0 = right (mirrored) 356 357 eor #$ff 358 clc 359 adc #1 ;A := -A 360 361 :right clc 362 adc CharX 363 rts 364 365 *------------------------------- 366 * 367 * Add A to FCharX 368 * (A range: -127 to 127) 369 * 370 * In: A; FChar data 371 * Out: FCharX 372 * 373 *------------------------------- 374 ADDFCHARX 375 sta ztemp 376 bpl :1 ;hibit clr 377 378 lda #0 379 sec 380 sbc ztemp 381 sta ztemp ;make it posititve 382 383 lda #$ff ;hibit set 384 :1 eor FCharFace 385 bmi :left 386 387 lda ztemp 388 clc 389 adc FCharX 390 sta FCharX 391 392 lda FCharX+1 393 adc #0 394 sta FCharX+1 395 rts 396 397 :left lda FCharX 398 sec 399 sbc ztemp 400 sta FCharX 401 402 lda FCharX+1 403 sbc #0 404 sta FCharX+1 405 rts 406 407 *------------------------------- 408 * 409 * In: CharFace,CharBlockX,CharBlockY,CharScrn 410 * 411 * Out: Results of RDBLOCK for block underfoot/in front/etc. 412 * 413 *------------------------------- 414 GETUNDERFT 415 ldx CharBlockX 416 ldy CharBlockY 417 lda CharScrn 418 jmp RDBLOCK 419 420 GETINFRONT 421 ldx CharFace 422 inx 423 lda CharBlockX 424 clc 425 adc plus1,x 426 sta infrontx 427 tax 428 429 ldy CharBlockY 430 lda CharScrn 431 jmp RDBLOCK 432 433 GET2INFRONT 434 ldx CharFace 435 inx 436 lda CharBlockX 437 clc 438 adc plus1,x 439 clc 440 adc plus1,x 441 tax 442 443 ldy CharBlockY 444 lda CharScrn 445 jmp RDBLOCK 446 447 GETBEHIND 448 ldx CharFace 449 inx 450 lda CharBlockX 451 clc 452 adc minus1,x 453 sta behindx 454 tax 455 456 ldy CharBlockY 457 lda CharScrn 458 jmp RDBLOCK 459 460 GETABOVE 461 ldy CharBlockY 462 dey 463 sty abovey 464 465 ldx CharBlockX 466 lda CharScrn 467 jmp RDBLOCK 468 469 GETABOVEINF 470 ldx CharFace 471 inx 472 lda CharBlockX 473 clc 474 adc plus1,x 475 sta infrontx 476 tax 477 478 ldy CharBlockY 479 dey 480 sty abovey 481 482 lda CharScrn 483 jmp RDBLOCK 484 485 GETABOVEBEH 486 ldx CharFace 487 inx 488 lda CharBlockX 489 clc 490 adc minus1,x 491 sta behindx 492 tax 493 494 ldy CharBlockY 495 dey 496 sty abovey 497 498 lda CharScrn 499 jmp RDBLOCK 500 501 *------------------------------- 502 * 503 * G E T D I S T A N C E 504 * 505 * In: Char data 506 * 507 * Out: A = # of pixels (0-13) to add to CharX to move 508 * char base X-coord to end of current block 509 * 510 *------------------------------- 511 GETDIST 512 jsr GETBASEX ;returns A = base X-coord 513 514 GETDIST1 515 jsr GETBLOCKXP ;returns A = block #, OFFSET = pixel # 516 517 lda CharFace ;0=right, -1=left 518 beq :facingright 519 520 :facingleft 521 lda OFFSET 522 rts 523 524 :facingright 525 lda #13 526 sec 527 sbc OFFSET 528 rts 529 530 *------------------------------- 531 * 532 * G E T B L O C K E D G E 533 * 534 * In: A = block # (-5 to 14) 535 * Out: A = screen X-coord of left edge 536 * 537 *------------------------------- 538 GETBLOCKEJ 539 clc 540 adc #5 541 tax 542 lda BlockEdge,x 543 rts 544 545 *------------------------------- 546 * 547 * G E T B L O C K X 548 * 549 * In: A = X-coord 550 * 551 * Out: A = # of the 14-pixel-wide block within which 552 * this pixel falls (0-9 onscreen) 553 * 554 * OFFSET = pixel within this block 555 * 556 * - Use GETBLOCKXP for objects on center plane 557 * - Use GETBLOCKX for absolute X-coords & foreground plane 558 * 559 *------------------------------- 560 GETBLOCKXP 561 sec 562 sbc #angle 563 564 GETBLOCKX 565 tay 566 567 lda PixelTable,y 568 sta OFFSET 569 570 lda BlockTable,y 571 rts 572 573 *------------------------------- 574 * 575 * G E T B L O C K Y 576 * 577 * In: A = screen Y-coord (0-255) 578 * 579 * Out: A = block y (3 = o.s.) 580 * 581 * - Use GETBLOCKYP for objects on center plane 582 * - Use GETBLOCKY for absolute Y-coords & foreground plane 583 * 584 *------------------------------- 585 GETBLOCKY 586 ldx #3 587 :loop cmp BlockTop+1,x 588 bcs :gotY 589 dex 590 bpl :loop 591 :gotY txa 592 rts 593 594 595 GETBLOCKYP 596 ldx #3 597 :loop cmp FloorY+1,x 598 bcs :gotY 599 dex 600 bpl :loop 601 :gotY txa 602 ]rts rts 603 604 *------------------------------- 605 * 606 * I N D E X B L O C K 607 * 608 * Index (tempblockx,tempblocky) 609 * 610 * Return y = block # (0-29) and cc if block is onscreen 611 * y = 0 to 9 and cs if block is on screen above 612 * y = 30 and cs if block is o.s. 613 * 614 *------------------------------- 615 INDEXBLOCK 616 ldy tempblocky 617 bmi :above 618 cpy #3 619 bcs :os 620 621 lda tempblockx 622 cmp #10 623 bcs :os ;0 <= tempblockx <= 9 624 625 clc 626 adc Mult10,y 627 628 tay ;return y = block # 629 clc ;and carry clr 630 rts 631 632 :os ldy #30 633 sec ;and carry set 634 rts 635 636 :above ldy tempblockx 637 sec 638 ]rts rts 639 640 *------------------------------- 641 * 642 * U N I N D E X 643 * 644 * In: A = block index (0-29) 645 * Out: A = blockx, X = blocky 646 * 647 *------------------------------- 648 UNINDEX 649 ldx #0 650 :loop cmp #10 651 bcc ]rts 652 sec 653 sbc #10 654 inx 655 bne :loop 656 ]rts rts 657 658 *------------------------------- 659 * 660 * G E T B A S E B L O C K 661 * 662 * In: Char data 663 * Out: CharBlockX 664 * 665 *------------------------------- 666 GETBASEBLOCK 667 jsr getbasex 668 jsr getblockxp 669 sta CharBlockX 670 ]rts rts 671 672 *------------------------------- 673 * 674 * F A C E D X 675 * 676 * In: CharFace; A = DX 677 * 678 * Out: DX if char is facing right, -DX if facing left 679 * 680 *------------------------------- 681 FACEDX 682 bit CharFace 683 bmi ]rts 684 685 eor #$ff 686 clc 687 adc #1 ;negate 688 689 ]rts rts 690 691 *------------------------------- 692 * 693 * J U M P S E Q 694 * 695 * Jump to some other point in sequence table 696 * 697 * In: A = sequence # (1-127) 698 * 699 *------------------------------- 700 JUMPSEQ 701 sec 702 sbc #1 703 asl 704 tax ;x = 2(a-1) 705 706 lda seqtab,x 707 sta CharSeq 708 709 lda seqtab+1,x 710 sta CharSeq+1 711 ]rts rts 712 713 *------------------------------- 714 * 715 * Similar routine for Opponent 716 * 717 *------------------------------- 718 OPJUMPSEQ 719 sec 720 sbc #1 721 asl 722 tax ;x = 2(a-1) 723 724 lda seqtab,x 725 sta OpSeq 726 727 lda seqtab+1,x 728 sta OpSeq+1 729 ]rts rts 730 731 *------------------------------- 732 * 733 * I N D E X C H A R 734 * 735 * In: Char data; GETEDGES results 736 * 737 * Out: FCharIndex = character block index 738 * 739 *------------------------------- 740 INDEXCHAR 741 lda CharAction 742 cmp #1 743 bne :4 744 ;If CharAction = 1 (on solid ground) 745 ;use leftblock/bottomblock 746 lda bottomblock 747 sta tempblocky 748 749 lda leftblock 750 :1 sta tempblockx 751 752 lda CharPosn 753 cmp #135 754 bcc :2 755 cmp #149 756 bcc :climbup 757 758 :2 cmp #2 759 beq :fall 760 cmp #3 761 beq :fall 762 cmp #4 763 beq :fall 764 cmp #6 765 bne :3 766 :fall 767 :climbup dec tempblockx ;if falling or climbing up 768 769 :3 jsr indexblock 770 sty FCharIndex 771 rts 772 773 * else use CharBlockX/Y 774 775 :4 lda CharBlockY 776 sta tempblocky 777 778 lda CharBlockX 779 jmp :1 780 781 *------------------------------- 782 * 783 * S E T U P C H A R 784 * 785 * Set up character for FRAMEADV 786 * 787 * In: Char data 788 * Out: FChar data 789 * 790 * Translate char data into the form "addchar" expects 791 * (Decode image #; get actual 280 x 192 screen coords) 792 * 793 *------------------------------- 794 SETUPCHAR 795 jsr zerocrop ;(can call cropchar later) 796 797 jsr GETFRAMEINFO 798 799 lda CharFace 800 sta FCharFace 801 802 jsr decodeim ;get FCharImage & Table from 803 ;encoded Fimage & Fsword data 804 lda #0 805 sta FCharX+1 806 807 lda Fdx 808 jsr addcharx ;A := CharX + Fdx 809 sec 810 sbc #ScrnLeft ;different coord system 811 sta FCharX 812 813 asl FCharX 814 rol FCharX+1 815 beq :pos 816 817 lda FCharX 818 cmp #$f0 819 bcc :pos 820 lda #$ff 821 sta FCharX+1 822 :pos ;X := 2X 823 lda Fdy 824 clc 825 adc CharY 826 sec 827 sbc #ScrnTop 828 sta FCharY 829 830 lda Fcheck 831 eor FCharFace ;Look only at the hibits 832 bmi :ok ;They don't match-->even X-coord 833 ;They match-->odd X-coord 834 lda FCharX 835 clc 836 adc #1 837 sta FCharX 838 bcc :ok 839 inc FCharX+1 840 :ok 841 ]rts rts 842 843 *------------------------------- 844 * 845 * S E T U P S W O R D 846 * 847 * In: Char & FChar data 848 * 849 * If character's sword is visible, add it to obj table 850 * 851 *------------------------------- 852 SETUPSWORD 853 lda CharID 854 cmp #2 855 bne :3 856 lda CharLife 857 bmi :2 ;live guard's sword is always visible 858 859 :3 lda CharPosn 860 cmp #229 861 bcc :1 862 cmp #238 863 bcc :2 ;sheathing 864 :1 lda CharSword 865 beq ]rts 866 :2 867 lda Fsword 868 and #$3f ;frame # 869 beq ]rts ;no sword for this frame 870 871 jsr getswordframe 872 873 ldy #0 874 lda (framepoint),y 875 beq ]rts 876 877 jsr decodeswim ;get FCharImage & Table 878 879 iny 880 lda (framepoint),y 881 sta Fdx 882 883 iny 884 lda (framepoint),y 885 sta Fdy 886 887 lda Fdx 888 jsr ADDFCHARX ;A := FCharX + Fdx 889 890 lda Fdy 891 clc 892 adc FCharY 893 sta FCharY 894 895 jmp ADDSWORDOBJ 896 897 *------------------------------- 898 * 899 * G E T F R A M E 900 * 901 * In: A = frame # (1-192) 902 * Out: framepoint = 2-byte pointer to frame def table 903 * 904 *------------------------------- 905 GETFRAME ;Kid uses main char set 906 jsr getfindex 907 lda framepoint 908 clc 909 adc #Fdef 910 sta framepoint 911 lda framepoint+1 912 adc #>Fdef 913 sta framepoint+1 914 rts 915 916 *------------------------------- 917 getaltframe1 ;Enemy uses alt set 1 918 jsr getfindex 919 lda framepoint 920 clc 921 adc #altset1 922 sta framepoint 923 lda framepoint+1 924 adc #>altset1 925 sta framepoint+1 926 rts 927 928 *------------------------------- 929 getaltframe2 ;Princess & Vizier use alt set 2 930 jsr getfindex 931 lda framepoint 932 clc 933 adc #altset2 934 sta framepoint 935 lda framepoint+1 936 adc #>altset2 937 sta framepoint+1 938 rts 939 940 *------------------------------- 941 getfindex 942 sec 943 sbc #1 944 sta ztemp 945 sta framepoint 946 947 lda #0 948 sta ztemp+1 949 sta framepoint+1 950 951 asl framepoint 952 rol framepoint+1 953 asl framepoint 954 rol framepoint+1 ;2-byte multiply by 4 955 956 lda framepoint 957 clc 958 adc ztemp 959 sta framepoint 960 961 lda framepoint+1 962 adc ztemp+1 963 sta framepoint+1 ;make it x5 964 rts 965 966 *------------------------------- 967 * 968 * getswordframe 969 * 970 * In: A = frame # 971 * Out: framepoint 972 * 973 *------------------------------- 974 getswordframe 975 sec 976 sbc #1 977 sta ztemp 978 sta framepoint 979 980 lda #0 981 sta ztemp+1 982 sta framepoint+1 983 984 asl framepoint 985 rol framepoint+1 ;x2 986 987 lda framepoint 988 clc 989 adc ztemp 990 sta framepoint 991 992 lda framepoint+1 993 adc ztemp+1 994 sta framepoint+1 ;+1 is 3 995 996 lda framepoint 997 clc 998 adc #swordtab 999 sta framepoint 1000 1001 lda framepoint+1 1002 adc #>swordtab 1003 sta framepoint+1 1004 1005 rts 1006 1007 *------------------------------- 1008 * 1009 * Decode char image 1010 * 1011 * In: Fimage, Fsword (encoded) 1012 * 1013 * Out: FCharImage (image #, 0-127) 1014 * FCharTable (table #, 0-7) 1015 * 1016 *------------------------------- 1017 decodeim 1018 lda Fimage 1019 and #%10000000 ;bit 2 of table # 1020 sta ztemp 1021 1022 lda Fsword 1023 and #%11000000 ;bits 0-1 of table # 1024 1025 lsr 1026 adc ztemp 1027 lsr 1028 lsr 1029 lsr 1030 lsr 1031 lsr 1032 sta FCharTable 1033 1034 lda Fimage 1035 and #$7f 1036 ora timebomb ;must be 0! 1037 sta FCharImage 1038 1039 rts 1040 1041 *------------------------------- 1042 * 1043 * Decode sword image 1044 * 1045 * In: A = image # 1046 * 1047 * Out: FCharImage, FCharTable 1048 * 1049 *------------------------------- 1050 decodeswim 1051 sta FCharImage ;image # 1052 1053 lda #2 ;chtable3 1054 sta FCharTable 1055 rts 1056 1057 *------------------------------- 1058 * 1059 * G E T E D G E S 1060 * 1061 * Get edges of character image 1062 * 1063 * In: FChar data as set by "setframe" 1064 * 1065 * Out: leftej/rightej/topej = boundaries of image (140-res) 1066 * leftblock, rightblock, topblock, bottomblock 1067 * CDLeftEj, CDRightEj (for coll detection) 1068 * imheight, imwidth 1069 * 1070 *------------------------------- 1071 GETEDGES 1072 lda FCharImage 1073 ldx FCharTable 1074 jsr dimchar ;return A = image width, x = height 1075 stx imheight 1076 1077 tax ;image width in bytes 1078 lda Mult7,x ;in 1/2 pixels 1079 clc 1080 adc #1 ;add 1/2 pixel 1081 lsr ;and divide by 2 1082 sta imwidth ;to get width in pixels 1083 1084 lda FCharX+1 1085 lsr 1086 lda FCharX 1087 ror 1088 clc 1089 adc #ScrnLeft ;convert back to 140-res 1090 1091 * (If facing LEFT, X-coord is leftmost pixel of LEFTMOST byte 1092 * of image; if facing RIGHT, leftmost pixel of RIGHTMOST byte.) 1093 1094 ldx CharFace 1095 bmi :ok ;facing L 1096 ;facing R 1097 sec 1098 sbc imwidth 1099 1100 :ok sta leftej 1101 clc 1102 adc imwidth 1103 sta rightej 1104 1105 lda FCharY 1106 sec 1107 sbc imheight 1108 clc 1109 adc #1 1110 1111 cmp #192 1112 bcc :ok2 1113 lda #0 1114 1115 :ok2 sta topej 1116 1117 jsr getblocky 1118 1119 cmp #3 1120 bne :1 1121 lda #-1 ;if o.s., call it -1 1122 1123 :1 sta topblock 1124 1125 lda FCharY 1126 jsr getblocky ;if o.s., call it 3 1127 sta bottomblock 1128 1129 lda leftej 1130 jsr getblockx ;leftmost affected block 1131 sta leftblock 1132 1133 lda rightej 1134 jsr getblockx ;rightmost affected block 1135 sta rightblock 1136 1137 * get leading edge (for collision detection) 1138 1139 lda #0 1140 sta ztemp 1141 1142 lda Fcheck 1143 and #Fthinmark 1144 beq :nothin 1145 1146 lda #thinner ;make character 3 bits thinner 1147 sta ztemp ;on both sides 1148 1149 :nothin lda leftej 1150 clc 1151 adc ztemp 1152 sta CDLeftEj 1153 1154 lda rightej 1155 sec 1156 sbc ztemp 1157 sta CDRightEj 1158 1159 ]rts rts 1160 1161 *=============================== 1162 * 1163 * Q U I C K F L O O R 1164 * 1165 * Mark for redraw whatever floorpieces character might be 1166 * impinging on 1167 * 1168 * In: CharData; GETEDGES results 1169 * 1170 *------------------------------- 1171 QUICKFLOOR 1172 lda CharPosn 1173 cmp #135 1174 bcc :2 1175 cmp #149 1176 bcc :climbup 1177 1178 :2 lda CharAction 1179 cmp #1 1180 bne :1 1181 1182 lda CharPosn 1183 cmp #78 1184 bcc ]rts 1185 cmp #80 1186 bcc :fall 1187 ]rts rts 1188 1189 :1 cmp #2 1190 beq :fall 1191 cmp #3 1192 beq :fall 1193 cmp #4 1194 beq :fall 1195 cmp #6 1196 bne ]rts 1197 1198 :fall lda #markfloor 1199 ldx #>markfloor 1200 bne :cont1 1201 1202 :climbup 1203 lda #markhalf 1204 ldx #>markhalf 1205 1206 * Mark floorbuf/halfbuf for up to 6 affected blocks 1207 * Start with rightblock, work left to leftblock 1208 1209 :cont1 1210 sta marksm1+1 1211 sta marksm2+1 1212 stx marksm1+2 1213 stx marksm2+2 1214 1215 lda rightblock 1216 :loop sta tempblockx 1217 1218 jsr markul 1219 1220 lda tempblockx 1221 cmp leftblock 1222 beq ]rts 1223 sec 1224 sbc #1 1225 bpl :loop 1226 1227 ]rts rts 1228 1229 * mark upper & lower blocks for this blockx 1230 1231 markul 1232 lda bottomblock 1233 sta tempblocky 1234 1235 jsr indexblock ;lower block 1236 lda #2 1237 marksm1 jsr markhalf 1238 1239 lda topblock 1240 cmp bottomblock 1241 beq ]rts 1242 sta tempblocky 1243 1244 jsr indexblock ;upper block 1245 lda #2 1246 marksm2 jmp markhalf 1247 1248 *------------------------------- 1249 * 1250 * Q U I C K F G 1251 * 1252 * Mark for redraw any f.g. elements char (or his sword) 1253 * might be impinging on 1254 * 1255 * In: Char data; left/right/top/bottomblock 1256 * 1257 *------------------------------- 1258 QUICKFG 1259 1260 * Quick fix to cover sword 1261 1262 lda CharSword 1263 cmp #2 1264 bcc :cont 1265 1266 lda CharFace 1267 bpl :faceR 1268 dec leftblock 1269 jmp :cont 1270 1271 :faceR inc rightblock 1272 1273 * Continue 1274 1275 :cont lda bottomblock 1276 :outloop 1277 sta tempblocky 1278 1279 lda rightblock 1280 :loop sta tempblockx 1281 1282 jsr indexblock 1283 lda #3 1284 jsr MARKFRED 1285 1286 lda tempblockx 1287 cmp leftblock 1288 beq :end 1289 sec 1290 sbc #1 1291 bpl :loop 1292 :end 1293 lda tempblocky 1294 cmp topblock 1295 beq ]rts 1296 sec 1297 sbc #1 1298 bpl :outloop 1299 rts 1300 1301 ]bug jmp showpage 1302 1303 *------------------------------- 1304 * 1305 * C R O P C H A R A C T E R 1306 * 1307 * In: FChar data as set by "setframe" 1308 * leftej,rightej, etc. as set by "getedges" 1309 * 1310 * Out: FCharCL/CR/CU/CD 1311 * 1312 *------------------------------- 1313 CROPCHAR 1314 1315 * If char is climbing stairs, mask door 1316 1317 lda CharPosn 1318 cmp #224 1319 bcc :nost 1320 cmp #229 1321 bcs :nost 1322 lda doortop ;set by drawexitb 1323 clc 1324 adc #2 1325 cmp FCharY 1326 bcs :bug ;temp! 1327 sta FCharCU 1328 ]rts rts 1329 :bug ldy #$F0 1330 jsr showpage 1331 :nost 1332 1333 * If char is under solid (a&b) floor, crop top 1334 1335 ldx leftblock 1336 ldy topblock 1337 lda CharScrn 1338 jsr rdblock 1339 cmp #block 1340 beq :1 1341 jsr cmpspace 1342 beq :not 1343 1344 * Special case (more lenient): if char is jumping 1345 * up to touch ceiling 1346 1347 :1 lda CharAction 1348 bne :10 1349 lda CharPosn 1350 cmp #79 1351 beq :2 1352 cmp #81 1353 bne :10 1354 beq :2 1355 1356 * Otherwise, both left & right topblocks must be solid 1357 1358 :10 ldx rightblock 1359 ldy topblock 1360 lda CharScrn 1361 jsr rdblock 1362 cmp #block 1363 beq :2 1364 jsr cmpspace 1365 beq :not 1366 1367 :2 ldx CharBlockY 1368 inx 1369 cpx #1 1370 beq :ok 1371 1372 lda BlockTop,x 1373 cmp FCharY 1374 bcs :not 1375 1376 sec 1377 sbc #floorheight 1378 cmp topej 1379 bcs :not 1380 1381 :ok lda BlockTop,x 1382 sta FCharCU 1383 sta topej 1384 :not 1385 1386 * If char is standing left of a panel, crop R 1387 * Char is considered "left" if CDLeftEj falls within 1388 * panel block 1389 1390 lda CDLeftEj 1391 jsr getblockx 1392 sta blockx 1393 1394 tax 1395 ldy CharBlockY 1396 lda CharScrn 1397 jsr rdblock 1398 1399 cmp #panelwof 1400 beq :r 1401 cmp #panelwif 1402 bne :nor 1403 1404 * Char's foot is within panel block 1405 * Special case: If character is hanging R, we don't 1406 * need to check his head 1407 1408 :r lda CharFace 1409 bmi :cont 1410 1411 lda CharAction 1412 cmp #2 1413 beq :r2 ;yes--hanging R 1414 1415 * Check block to right of char's head 1416 1417 :cont 1418 ldx blockx 1419 ldy topblock 1420 lda CharScrn 1421 jsr rdblock 1422 1423 cmp #block 1424 beq :r2 1425 cmp #panelwof 1426 beq :r2 1427 cmp #panelwif 1428 bne :nor 1429 1430 * Also a panel -- make a wall 1431 1432 :r2 lda tempblockx 1433 asl 1434 asl 1435 clc 1436 adc #4 1437 sta FCharCR 1438 rts 1439 1440 * Is char standing to L of solid block? 1441 * (i.e. does CDRightEj fall within block?) 1442 1443 :nor 1444 lda CDRightEj 1445 jsr getblockx 1446 sta blockx 1447 1448 tax 1449 ldy CharBlockY 1450 lda CharScrn 1451 jsr rdblock 1452 1453 cmp #block 1454 bne :nob 1455 1456 * Foot is under block--what about head? 1457 1458 ldx blockx 1459 ldy topblock 1460 lda CharScrn 1461 jsr rdblock 1462 1463 cmp #block 1464 bne :nob 1465 1466 * Also a panel -- make a wall 1467 1468 :yescrop 1469 lda tempscrn 1470 cmp CharScrn 1471 bne :nob 1472 1473 lda tempblockx 1474 asl 1475 asl 1476 sta FCharCR 1477 :nob 1478 rts 1479 1480 *------------------------------- 1481 * 1482 * Z E R O C R O P 1483 * 1484 *------------------------------- 1485 zerocrop 1486 lda #0 1487 sta FCharCU 1488 sta FCharCL 1489 lda #40 1490 sta FCharCR 1491 lda #192 1492 sta FCharCD 1493 rts 1494 1495 *=============================== 1496 * 1497 * C O M P A R E S P A C E 1498 * 1499 * Is it a space (can you pass thru)? 1500 * NOTE: Solid block is considered a space (it has no floor) 1501 * 1502 * In: A = objid 1503 * Out: 0 = space, 1 = floor 1504 * 1505 *------------------------------- 1506 CMPSPACE 1507 cmp #space 1508 beq :space 1509 cmp #pillartop 1510 beq :space 1511 cmp #panelwof 1512 beq :space 1513 cmp #block 1514 beq :space 1515 cmp #archtop1 1516 bcs :space 1517 1518 lda #1 1519 rts 1520 1521 :space lda #0 1522 rts 1523 1524 *------------------------------- 1525 * 1526 * C O M P A R E B A R R I E R 1527 * 1528 * Is it a barrier? 1529 * 1530 * Return A = 0 if clear, else A = barrier code # 1531 * 1532 *------------------------------- 1533 CMPBARR 1534 cmp #panelwif 1535 beq :b1 1536 cmp #panelwof 1537 beq :b1 1538 cmp #gate 1539 bne :2 1540 1541 :b1 lda #1 ;panel/gate 1542 rts 1543 1544 :2 cmp #mirror 1545 beq :yes3 1546 1547 cmp #slicer 1548 bne :3 1549 1550 :yes3 lda #3 ;mirror/slicer 1551 rts 1552 1553 :3 cmp #block 1554 bne :4 1555 1556 lda #4 ;block 1557 rts 1558 :4 1559 :clear lda #0 1560 :rts rts 1561 1562 :barr lda #1 1563 ]rts rts 1564 1565 *------------------------------- 1566 * 1567 * Is it a wall? Return 0 if yes, 1 if no 1568 * (Solid block, or panel if you're facing L) 1569 * 1570 *------------------------------- 1571 CMPWALL 1572 cmp #block 1573 beq :yes 1574 ldx CharFace 1575 bpl :no 1576 cmp #panelwif 1577 beq :yes 1578 cmp #panelwof 1579 beq :yes 1580 :no lda #1 1581 rts 1582 :yes lda #0 1583 rts 1584 1585 *------------------------------- 1586 * 1587 * Add kid/reflection/shadowman/guard to object table 1588 * 1589 * In: FChar data 1590 * 1591 *------------------------------- 1592 ADDKIDOBJ 1593 lda #TypeKid 1594 jmp addcharobj 1595 1596 *------------------------------- 1597 ADDREFLOBJ 1598 lda #TypeReflect 1599 jmp addcharobj 1600 1601 *------------------------------- 1602 ADDSHADOBJ 1603 lda #TypeShad 1604 jmp addcharobj 1605 1606 *------------------------------- 1607 ADDGUARDOBJ 1608 lda #TypeGd 1609 jmp addcharobj 1610 1611 *------------------------------- 1612 * 1613 * Add sword to object table 1614 * In: FChar data for character holding sword 1615 * 1616 *------------------------------- 1617 ADDSWORDOBJ 1618 lda #TypeSword 1619 jmp addcharobj 1620 1621 *------------------------------- 1622 * 1623 * G E T S E Q 1624 * 1625 * Get next byte from seqtable & advance CharSeq 1626 * (2-byte pointer to sequence table) 1627 * 1628 *------------------------------- 1629 GETSEQ 1630 ldy #0 1631 lda (CharSeq),y 1632 pha 1633 1634 inc CharSeq 1635 bne :done 1636 inc CharSeq+1 1637 1638 :done pla 1639 rts 1640 1641 *------------------------------- 1642 * 1643 * G E T F R A M E I N F O 1644 * 1645 * Get frame info for char (based on CharPosn) 1646 * 1647 *------------------------------- 1648 GETFRAMEINFO 1649 lda CharPosn 1650 jsr GETFRAME ;set framepoint 1651 1652 jsr usealtsets ;if appropriate 1653 1654 ldy #0 1655 lda (framepoint),y 1656 sta Fimage 1657 1658 iny 1659 lda (framepoint),y 1660 sta Fsword 1661 1662 iny 1663 lda (framepoint),y 1664 sta Fdx 1665 1666 iny 1667 lda (framepoint),y 1668 sta Fdy 1669 1670 iny 1671 lda (framepoint),y 1672 sta Fcheck 1673 1674 ]rts rts 1675 1676 *------------------------------- 1677 * 1678 * Use alternate character image sets 1679 * (if appropriate) 1680 * 1681 * In: Char data; framepoint 1682 * Out: framepoint 1683 * 1684 *------------------------------- 1685 usealtsets 1686 ldx CharID 1687 beq ]rts ;kid uses main set, enemy uses alt set 1 1688 cpx #24 1689 beq ]rts ;mouse uses main set 1690 cpx #5 1691 bcs :usealt2 ;princess & vizier use alt set 2 1692 1693 lda CharPosn 1694 cpx #2 1695 bcc :1 1696 cmp #102 1697 bcc ]rts 1698 cmp #107 1699 bcs :1 1700 ;frames 102-106 (falling): substitute 172-176 altset 1701 clc 1702 adc #70 1703 1704 :1 cmp #150 1705 bcc ]rts 1706 cmp #190 1707 bcs ]rts 1708 ;frames 150-189: use altset 1709 sec 1710 sbc #149 1711 jmp getaltframe1 1712 1713 :usealt2 1714 lda CharPosn 1715 jmp getaltframe2 1716 1717 *=============================== 1718 * 1719 * M A R K 1720 * 1721 * In: A = mark value (usually 2) 1722 * Results of INDEXBLOCK: 1723 * Y = block #; carry set or clear 1724 * 1725 * Out: Preserve A, Y, carry 1726 * 1727 *------------------------------- 1728 ]os cpy #10 ;top line from scrn above? 1729 bcs ]rts ;no 1730 sta topbuf,y 1731 sec ;preserve cs 1732 ]rts rts 1733 1734 MARKRED 1735 bcs ]os 1736 sta redbuf,y 1737 rts 1738 1739 MARKFRED 1740 bcs ]rts 1741 sta fredbuf,y 1742 rts 1743 1744 MARKWIPE 1745 bcs ]rts 1746 pha 1747 lda wipebuf,y 1748 beq :2 1749 lda height 1750 cmp whitebuf,y ;if wipebuf is already marked, 1751 bcc :1 ;use larger of 2 whitebuf values 1752 :2 lda height 1753 sta whitebuf,y 1754 :1 pla 1755 sta wipebuf,y 1756 clc ;return with cc 1757 rts 1758 1759 MARKMOVE 1760 bcs ]os 1761 sta movebuf,y 1762 rts 1763 1764 MARKFLOOR 1765 bcs ]os 1766 sta floorbuf,y 1767 rts 1768 1769 MARKHALF 1770 bcs ]os 1771 sta halfbuf,y 1772 rts 1773 1774 *------------------------------- 1775 * 1776 * Z E R O R E D 1777 * 1778 * zero redraw buffers 1779 * 1780 *------------------------------- 1781 ZERORED 1782 lda #0 1783 1784 ldy #29 1785 1786 :loop sta redbuf,y 1787 sta fredbuf,y 1788 sta floorbuf,y 1789 sta wipebuf,y 1790 sta movebuf,y 1791 sta objbuf,y 1792 sta halfbuf,y 1793 1794 dey 1795 bpl :loop 1796 1797 ldy #9 1798 :dloop sta topbuf,y 1799 dey 1800 bpl :dloop 1801 1802 rts 1803 1804 *------------------------------- 1805 * 1806 * C H E C K L E D G E 1807 * 1808 * In: blockid = block that must be clear; 1809 * A = RDBLOCK results for block that must be ledge 1810 * 1811 * Out: A = 1 if grabbable, 0 if not 1812 * 1813 *------------------------------- 1814 CHECKLEDGE 1815 sta ztemp 1816 1817 lda (BlueSpec),y 1818 sta tempstate 1819 1820 lda blockid ;must be clear 1821 1822 cmp #block 1823 beq :no 1824 1825 cmp #panelwof ;CMPSPACE considers panel w/o floor 1826 bne :cont ;to be clear-- 1827 1828 bit CharFace ;but it isn't if char wants to grab 1829 bpl :no ;floorpiece to right 1830 :cont 1831 jsr cmpspace 1832 bne :no 1833 1834 * Clear above -- is there a ledge in front? 1835 1836 lda ztemp ;must be a solid floorpiece 1837 ;with exposed ledge 1838 cmp #loose 1839 bne :notloose 1840 1841 bit tempstate 1842 bne :no ;floor is already loose 1843 1844 :notloose 1845 cmp #panelwif 1846 bne :cont2 ;panel w/floor can be grabbed 1847 ;only if facing right 1848 bit CharFace 1849 bmi :no 1850 1851 :cont2 jsr cmpspace 1852 beq :no 1853 1854 :yes lda #1 1855 rts 1856 1857 :no lda #0 1858 ]rts rts 1859 1860 *------------------------------- 1861 * 1862 * C H E C K S P I K E S 1863 * 1864 * Spikes spring out when char passes over them (at any 1865 * height). 1866 * 1867 *------------------------------- 1868 CHECKSPIKES 1869 lda rightej 1870 jsr getblockxp 1871 bmi ]rts 1872 sta tempright 1873 1874 * for blockx = leftblock to rightblock 1875 1876 lda leftej 1877 jsr getblockxp 1878 :loop sta blockx 1879 1880 jsr sub 1881 1882 lda blockx 1883 cmp tempright 1884 beq ]rts 1885 clc 1886 adc #1 1887 jmp :loop 1888 1889 sub sta tempblockx 1890 lda CharBlockY 1891 sta tempblocky 1892 lda CharScrn 1893 sta tempscrn 1894 :loop jsr rdblock1 1895 1896 cmp #spikes 1897 bne :again 1898 jmp trigspikes 1899 1900 :again jsr cmpspace 1901 bne ]rts 1902 1903 lda tempscrn 1904 beq ]rts ;null scrn 1905 cmp CharScrn 1906 bne ]rts ;wait till he's on same screen 1907 1908 inc tempblocky 1909 jmp :loop ;check 1 level below 1910 1911 *=============================== 1912 * 1913 * Load/save kid/shad vars 1914 * 1915 *------------------------------- 1916 numvars = 16 1917 1918 LOADKID 1919 ldx #numvars-1 1920 1921 :loop lda Kid,x 1922 sta Char,x 1923 1924 dex 1925 bpl :loop 1926 ]rts rts 1927 1928 SAVEKID 1929 ldx #numvars-1 1930 1931 :loop lda Char,x 1932 sta Kid,x 1933 1934 dex 1935 bpl :loop 1936 ]rts rts 1937 1938 LOADSHAD 1939 ldx #numvars-1 1940 1941 :loop lda Shad,x 1942 sta Char,x 1943 1944 dex 1945 bpl :loop 1946 ]rts rts 1947 1948 1949 SAVESHAD 1950 ldx #numvars-1 1951 1952 :loop lda Char,x 1953 sta Shad,x 1954 1955 dex 1956 bpl :loop 1957 rts 1958 1959 * Load kid w/ opponent 1960 1961 LOADKIDWOP 1962 ldx #numvars-1 1963 1964 :loop lda Kid,x 1965 sta Char,x 1966 1967 lda Shad,x 1968 sta Op,x 1969 1970 dex 1971 bpl :loop 1972 rts 1973 1974 SAVEKIDWOP 1975 ldx #numvars-1 1976 1977 :loop lda Char,x 1978 sta Kid,x 1979 1980 lda Op,x 1981 sta Shad,x 1982 1983 dex 1984 bpl :loop 1985 rts 1986 1987 * Load shadowman w/ opponent 1988 1989 LOADSHADWOP 1990 ldx #numvars-1 1991 1992 :loop lda Shad,x 1993 sta Char,x 1994 1995 lda Kid,x 1996 sta Op,x 1997 1998 dex 1999 bpl :loop 2000 rts 2001 2002 SAVESHADWOP 2003 ldx #numvars-1 2004 2005 :loop lda Char,x 2006 sta Shad,x 2007 2008 lda Op,x 2009 sta Kid,x 2010 2011 dex 2012 bpl :loop 2013 rts 2014 2015 *------------------------------- 2016 * 2017 * Recharge strength meter to max 2018 * 2019 *------------------------------- 2020 RECHARGEMETER 2021 lda MaxKidStr 2022 sec 2023 sbc KidStrength 2024 sta ChgKidStr 2025 ]rts rts 2026 2027 *------------------------------- 2028 * 2029 * Boost strength meter max by 1 and recharge 2030 * 2031 *------------------------------- 2032 BOOSTMETER 2033 lda MaxKidStr 2034 cmp #maxmaxstr 2035 bcs :1 2036 2037 clc 2038 adc #1 2039 sta MaxKidStr 2040 2041 :1 jmp RECHARGEMETER 2042 2043 *------------------------------- 2044 * 2045 * Get distance between char & opponent 2046 * (# pixels char must move fwd to reach opponent) 2047 * If dist is greater than 127, return 127 (+ or -) 2048 * 2049 *------------------------------- 2050 estwidth = 13 ;rough est of char width 2051 2052 GETOPDIST 2053 lda CharScrn 2054 cmp OpScrn 2055 bne :safe 2056 2057 * First, get A = OpX-CharX (abs. value <= 127) 2058 2059 lda OpX 2060 cmp CharX 2061 bcc :neg 2062 sec 2063 sbc CharX 2064 bpl :got 2065 lda #127 2066 bpl :got 2067 2068 :neg lda CharX 2069 sec 2070 sbc OpX 2071 bpl :1 2072 lda #127 2073 :1 eor #$ff 2074 clc 2075 adc #1 ;negate 2076 2077 * If CharFace = left, negate 2078 2079 :got ldx CharFace 2080 bpl :cont 2081 eor #$ff 2082 clc 2083 adc #1 2084 2085 * If chars are facing in opposite directions, 2086 * adjust by estimate of width of figure 2087 2088 :cont tax 2089 lda CharFace 2090 eor OpFace 2091 bpl :done 2092 txa 2093 cmp #127-estwidth 2094 bcs :done2 2095 clc 2096 adc #estwidth 2097 :done2 tax 2098 rts 2099 2100 :safe ldx #127 ;arbitrary large dist. 2101 :done txa ;return value in A 2102 ]rts rts 2103 2104 *------------------------------- 2105 * 2106 * Adjust CharY for uneven floor 2107 * 2108 *------------------------------- 2109 UNEVENFLOOR 2110 jsr getunderft 2111 cmp #dpressplate 2112 bne ]rts 2113 inc CharY 2114 ]rts rts 2115 2116 *------------------------------- 2117 lst 2118 ds 1 2119 usr $a9,19,$200,*-org 2120 lst off