1 ; 2 ; swutil - SW assembler utilities 3 ; 4 ; Copyright (C) 1984-2003 David L. Clark. 5 ; This program is free software; you can redistribute it and/or modify it under 6 ; the terms of the GNU General Public License as published by the Free Software 7 ; Foundation; either version 2 of the License, or (at your option) any later 8 ; version. This program is distributed in the hope that it will be useful, 9 ; but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 10 ; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 ; more details. You should have received a copy of the GNU General Public 12 ; License along with this program; if not, write to the Free Software Foundation, 13 ; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 14 ; 15 ; Author: Dave Clark 16 ; 17 ; Modification History: 18 ; 84-02-23 Development 19 ; 84-06-12 PCjr Speed-up 20 ; 84-06-15 Joystick support 21 ; 87-03-10 Microsoft compiler 22 ; 87-03-04 Missile and starburst support 23 ; 87-03-05 Remap missile and starburst keys 24 ; 87-04-09 Fix to non-IBM keyboard. 25 ; 94-12-18 C6 Compiler 26 ; 2003-01-27 GNU General Public License 27 ; 28 29 30 % .MODEL model,lang 31 INCLUDE mixed.inc 32 33 .CODE 34 35 36 include segments.h 37 include sw.ha 38 39 public swbreak 40 public swgetc 41 public swgetjoy 42 public swputc 43 public swflush 44 public swkeyint 45 public swposcur 46 public swcolour 47 public swshfprt 48 public swprint 49 public swsetblk 50 public swtick 51 public movexy 52 public setdxdy 53 public soundmul 54 public sounddiv 55 public dsseg 56 public csseg 57 58 extrn swtickc:near 59 extrn ctlbreak:near 60 extrn history:near 61 extrn swsound:near 62 extrn sound:near 63 64 65 66 ;------------------------------------------------------------------------------ 67 68 swbreak: 69 push DS 70 push BX 71 push BP 72 73 mov BP,SP ; setup DS from stack 74 mov BX,[BP+06] 75 mov DS,BX 76 77 mov ctlbflag,1 ; flag control break 78 79 pop BP ; restore registers 80 pop BX 81 pop DS 82 83 add SP,8 ; skip swbreak DS and old routine 84 iret ; return to interrupted process 85 86 87 ;----------------------------------------------------------------------------- 88 89 swkeyint: 90 sti ; allow interrupts 91 92 push BP ; save registers 93 push DS ; 94 mov BP,SP ; set DS to sw data segment 95 mov BP,[BP+4] ; 96 mov DS,BP ; 97 mov byte ptr keyflag,1 ; flag keystroke having occurred 98 99 cmp word ptr ibmkeybd,0 ; IBM keyboard? 100 jne kii ; YES - skip 101 pop DS ; NO - use old key int routine 102 pop BP ; 103 add SP,2 ; 104 iret ; 105 106 kii: push AX ; save registers 107 push BX 108 push CX 109 push DX 110 push ES 111 push SI 112 push DI 113 114 mov ES,BP ; set ES to data space 115 mov byte ptr paused,0 ; flag no longer in paused mode 116 117 cmp word ptr _systype,PCDOS ; running under DOS on PC 118 je kir ; YES- read key from port 119 mov BL,AL ; NO - key already in AL 120 jmp ki0 ; 121 122 kir: in AL,60H ; read scan code 123 mov BL,AL ; save it 124 in AL,61H ; read control port 125 mov AH,AL ; save it 126 or AL,80H ; reset keyboard 127 out 61H,AL 128 mov AL,AH ; restore old control port 129 out 61H,AL ; keyboard now reset 130 131 ki0: cmp BL,55 ; print screen key? 132 jne ki1 ; NO - continue 133 int 5 ; YES- perform print screen int 134 jmp kiret ; leave 135 136 ki1: cmp BL,99H ; release of P key ( pause ) 137 jne ki15 ; NO - continue 138 mov byte ptr paused,1 ; YES- flag in pause mode 139 cmp _systype,PCDOS ; running under DOS on PC? 140 jne ki11 ; NO - skip 141 mov AL,20H ; YES- signal end of interrupt 142 out 20H,AL ; 143 ki11: cmp byte ptr soundflg,1 ; sound on? 144 jne ki13 ; 145 xor AX,AX ; YES- turn off sound 146 push AX ; 147 push AX ; 148 call sound ; 149 add SP,4 ; 150 call swsound ; 151 mov byte ptr soundflg,0 ; 152 ki12: test byte ptr paused,1 ; loop until next keyboard 153 jnz ki12 ; interrupt 154 mov byte ptr soundflg,1 ; turn sound on 155 jmp ki5 ; leave 156 157 ki13: test byte ptr paused,1 ; NO - loop until next keyboard 158 jnz ki13 ; interrupt 159 jmp ki5 ; leave 160 161 ki15: cmp BL,70 ; break key? 162 jne ki2 ; NO - continue 163 int 1BH ; YES- perform break int, don't leave 164 165 166 ki2: mov CX,12 ; length of scan code table 167 mov AL,BL ; scan code to be searched 168 and AL,7FH ; strip off break code 169 lea DI,scantable ; scan code table address 170 mov SI,DI ; save it 171 cld ; clear direction flag 172 repnz scasb ; search table for scan code 173 jnz kiret ; leave if not found 174 175 dec DI ; back DI off 1 byte 176 sub DI,SI ; offset into scan code table 177 shl DI,1 ; offset into scan mask table 178 lea SI,scanmasks ; address of mask table 179 add SI,DI ; address of mask 180 mov AX,[SI] ; load mask 181 cli ; prevent interrupts 182 183 test BL,80H ; break code? 184 jz ki3 185 test prevkey,AX ; YES-was key up on last input 186 not AX ; invert flag 187 jz ki25 ; NO - skip 188 and nextkey,AX ; YES- set bit off on next input 189 ki25: and currkey,AX ; set off bit in current 190 jmp kiret 191 192 ki3: or currkey,AX ; NO -set bit in current key word 193 or nextkey,AX ; set bit in next key word 194 195 kiret: cmp _systype,PCDOS ; running under DOS on PC? 196 jne ki5 ; NO - skip 197 198 cli ; prevent interrupts 199 mov AL,20H ; signal end of interrupt 200 out 20H,AL 201 202 ki5: pop DI ; restore registers 203 pop SI 204 pop ES 205 pop DX 206 pop CX 207 pop BX 208 pop AX 209 pop DS 210 pop BP 211 add SP,8 ; cleanup stack 212 iret 213 214 ;------------------------------------------------------------------------------ 215 216 217 218 ; swgetc() 219 ; 220 ; get a character from the keyboard. The ascii character 221 ; returned is in in AL, the scan code in AH. Routine 222 ; will return 0 if no character is available. 223 ; 224 225 swgetc: 226 cmp word ptr inplay,0 ; Currently in play? 227 jnz getc2 ; YES- jump to new keyboard code 228 call getbio ; NO - perform BIOS get character 229 call history ; post to history 230 ret ; 231 232 getc2: cmp word ptr ibmkeybd,0 ; Using IBM lookalike keyboard? 233 jz getc3 ; NO - jump to non-IBM code 234 cli ; turn off interrupts 235 push nextkey ; save word to be returned 236 mov AX,currkey ; reset to current keyboard status 237 mov nextkey,AX ; 238 pop AX ; return current keyboard word 239 mov prevkey,AX ; save it 240 sti ; allow interrupts 241 jmp getc7 ; go to joystick code 242 243 getc3: push DI ; save registers 244 push SI 245 call getbio ; get a character in AX 246 cmp AX,0 ; anything read? 247 jz getc5 ; NO - leave 248 249 mov SI,DS ; point ES to data 250 mov ES,SI ; 251 lea DI,lkeytable ; search lower case table for key mask 252 call getcm 253 jz getc5 ; character mask found 254 lea DI,ukeytable ; search upper case table 255 call getcm 256 jz getc5 ; character mask found 257 258 xor AX,AX ; no valid key pressed 259 260 getc5: push AX ; save return mask 261 call ctlbreak ; control break pressed? 262 cmp AX,0 ; 263 jz getc6 ; NO - skip 264 mov AX,K_BREAK ; YES- load control break mask 265 266 getc6: pop SI ; pop key mask 267 or AX,SI ; or with possible ctlbreak mask 268 pop SI ; restore registers 269 pop DI 270 271 getc7: cmp word ptr joystick,0 ; using joystick? 272 jz getcret ; NO - leave 273 push AX ; YES- save keyboard status 274 mov AX,nextjoy ; reset joystick words 275 mov prevjoy,AX ; 276 mov AX,currjoy ; 277 mov nextjoy,AX ; 278 pop AX ; restore keyboard status 279 or AX,prevjoy ; include joystick status 280 281 getcret:call history ; post to history 282 ret ; return 283 284 285 286 getcm: 287 mov SI,DS ; point ES to data 288 mov ES,SI ; 289 mov CX,12 ; length of key table 290 mov SI,DI ; save address of table 291 cld ; clear direction flag 292 repnz scasb ; search table for scan code 293 jnz getcmr ; leave if not found 294 295 dec DI ; back DI off 1 byte 296 sub DI,SI ; offset into key table 297 shl DI,1 ; offset into scan mask table 298 lea SI,scanmasks ; address of mask table 299 add SI,DI ; address of mask 300 mov AX,[SI] ; load mask 301 xor SI,SI ; turn on zero bit 302 getcmr: ret 303 304 305 306 getbio: 307 mov AH,01H ; Character available function code 308 int 16H ; KEYBOARD_IO interrupt 309 jnz getb1 ; character available? 310 xor AX,AX ; NO - return with 0 311 ret 312 getb1: 313 mov AH,00H ; Read character function code 314 int 16H ; KEYBOARD_IO interrupt 315 ret 316 317 318 319 320 ; 321 ; swgetjoy(); 322 ; 323 324 JOYHIGH equ 0780H 325 JOYLOW equ 0280H 326 JOYMAX equ 0A00H 327 328 swgetjoy: 329 cmp word ptr joystick,0 ; Using joysticks? 330 jz swjret ; NO - leave 331 332 mov AX,0 ; get joystick 0 in DX 333 call getjoy 334 mov DX,AX 335 mov AX,1 ; get joystick 1 in AX 336 call getjoy 337 338 lea BX,joymasks+8 339 cmp AX,JOYLOW ; get index into table 012 340 jg swj1 ; in BX 345 341 sub BX,6 ; 678 342 jmp swjx 343 swj1: cmp AX,JOYHIGH 344 jl swjx 345 add BX,6 346 swjx: cmp DX,JOYLOW 347 jg swj2 348 sub BX,2 349 jmp swj3 350 swj2: cmp DX,JOYHIGH 351 jl swj3 352 add BX,2 353 354 swj3: mov BX,[BX] ; joystick mask in BX 355 356 mov DX,201H ; get button status 357 in AL,DX 358 test AL,10H ; button 1 pushed? 359 jnz swj4 ; NO -skip 360 or BX,K_SHOT ; YES-shoot 361 swj4: test AL,20H ; button 2 pushed? 362 jnz swj5 ; NO - skip 363 or BX,K_BOMB ; YES- drop bomb 364 365 swj5: mov currjoy,BX ; update current joystick status 366 or nextjoy,BX ; turn on bits in next status 367 mov AX,BX ; invert mask 368 not AX 369 and AX,prevjoy ; previously on to turn off 370 not AX ; invert for and 371 and nextjoy,AX ; turn off if previosly on 372 373 swjret: ret 374 375 376 getjoy: 377 push BX 378 push CX 379 push DX 380 cli ; disable interrupts 381 382 mov CX,AX ; joystick requested 383 mov CH,1 ; initial joystick mask 384 shl CH,CL ; actual joystick mask 385 386 mov DX,201H ; adapter address 387 in AL,DX ; is joystick bit already up? 388 test AL,CH 389 jz gj0 ; NO - continue 390 391 mov AX,JOYMAX ; YES- return high value 392 jmp gjret 393 394 gj0: mov byte ptr keyflag,0 ; set off keyboard int flag 395 mov AL,00H ; Read timer 0 396 out 43H,AL 397 in AL,40H ; read LSB 398 mov BL,AL 399 in AL,40H ; read MSB 400 mov BH,AL 401 402 out DX,AL ; trigger games controller read 403 404 gj1: in AL,DX ; get adapter status 405 test AL,CH ; bit still high 406 jnz gj1 ; yes, try again 407 408 mov AL,00H ; Read timer 0 409 out 43H,AL 410 in AL,40H ; read LSB 411 mov AH,AL 412 in AL,40H ; read MSB 413 xchg AL,AH 414 415 cmp byte ptr keyflag,0 ; keyboard interrupt occured? 416 je gj2 ; NO - skip 417 mov AX,(JOYHIGH-JOYLOW)/2 ; YES - return mid range 418 jmp gjret ; 419 420 gj2: sub BX,AX ; elapsed time 421 mov AX,BX ; return it. 422 423 gjret: sti ; enable interrupts 424 pop DX 425 pop CX 426 pop BX 427 ret 428 429 430 ; swflush() 431 ; 432 ; flush the keyboard buffer. 433 ; 434 435 swflush: 436 mov AX,inplay ; Currently in play? 437 and AX,ibmkeybd ; and IBM like keyboard? 438 jnz swfret ; YES - ignore request 439 440 swflp: mov AH,01H ; Character available function code 441 int 16H ; KEYBOARD_IO interrupt 442 jnz flush1 ; character available? 443 444 swfret: xor AX,AX ; NO - return with 0 445 ret 446 447 flush1: 448 mov AH,00H ; Read character function code 449 int 16H ; KEYBOARD_IO interrupt 450 jmp swflp ; loop back until nothing left 451 452 453 454 455 ; swputc( c ) 456 ; 457 ; output a character 458 ; 459 460 swputc: 461 push BP ; save frame pointer 462 mov BP,SP ; access stack pointer 463 464 mov AL,4[BP] ; get character to output 465 cmp AL,9 ; horizontal tab? 466 jne swpc1 ; NO - skip 467 push CX ; YES- save registers 468 push DX ; 469 mov AH,3 ; read cursor position 470 xor BH,BH ; 471 int 10H ; 472 add DL,8 ; goto next tab 473 and DL,0F8H ; 474 mov AH,2 ; 475 int 10H ; 476 pop DX ; restore registers 477 pop CX ; 478 jmp swpc2 ; leave 479 480 swpc1: mov BL,textclr ; set colour and page 481 xor BH,BH ; 482 mov AH,0EH ; output character 483 int 10H ; 484 485 cmp word ptr hires,1 ; hi resolution screen? 486 jne swpc2 ; NO - skip 487 cmp byte ptr 4[BP],' ' ; YES- control character? 488 jb swpc2 ; YES- skip 489 mov AX,0E20H ; NO - output blank 490 int 10H ; 491 492 swpc2: pop BP ; restore registers 493 ret 494 495 496 497 ; swposcur( x, y ) - Position the character cursor to the 498 ; character position (x,y) 499 500 swposcur: 501 push BP ; save frame pointer 502 mov BP,SP ; access stack pointer 503 504 mov DH,6[BP] ; y coordinate 505 mov DL,4[BP] ; x coordinate 506 xor BH,BH ; page 0 507 508 cmp word ptr hires,1 ; hi resolution screen? 509 jne swpos1 ; NO - skip 510 shl DL,1 ; YES- double x coordinate 511 swpos1: mov AH,02H ; position cursor 512 int 10H ; 513 514 pop BP 515 ret 516 517 518 519 520 ; swcolour( x ) - Set the text display colour. 521 522 swcolour: 523 push BP ; save frame pointer 524 mov BP,SP ; access stack pointer 525 mov AL,4[BP] ; save colour 526 mov textclr,AL ; save colour 527 pop BP 528 ret 529 530 531 ; swshfprt() - new interrupt server for shift print screen 532 533 swshfprt: 534 push DS ; save registers 535 push BP 536 push BX 537 538 mov BP,SP ; setup DS from DS on stack 539 mov BX,[BP+6] 540 mov DS,BX 541 542 mov word ptr printflg,1 ; flag print screen pressed 543 mov BX,[BP+8] ; save old print screen location 544 mov printip,BX 545 mov BX,[BP+10] 546 mov printcs,BX 547 548 pop BX ; restore registers 549 pop BP 550 pop DS 551 add SP,8 ; cleanup stack 552 iret 553 554 ; swprint() - perform a shift print screen function 555 556 swprint: 557 pushf ; duplicate shift print int 558 call dword ptr printip 559 ret ; return 560 561 562 ;------------------------------------------------------------------------------ 563 564 565 566 swtick: 567 push DS 568 push ES 569 push AX 570 push BX 571 push CX 572 push DX 573 push SI 574 push DI 575 push BP 576 577 mov BP,SP ; setup DS,ES from DS on stack 578 mov BX,[BP+18] 579 mov DS,BX 580 mov ES,BX 581 582 cmp byte ptr paused,1 ; currently paused? 583 je swtck1 ; YES - skip 584 call swtickc ; NO - call SW tick processing 585 586 swtck1: pop BP ; restore registers 587 pop DI 588 pop SI 589 pop DX 590 pop CX 591 pop BX 592 pop AX 593 pop ES 594 pop DS 595 596 add SP,2 ; skip swtick DS on stack 597 iret ; transfer to old tick routine 598 599 600 ;------------------------------------------------------------------------------ 601 602 603 604 swsetblk: 605 push bp 606 mov bp,sp 607 push es 608 mov ax,6[bp] ;get the extra seg 609 mov es,ax 610 cld ;and clear the direction flag 611 mov di,4[bp] ;the address to set 612 mov cx,8[bp] ;the number of bytes to set 613 mov al,10[bp] ;the value to set 614 rep stosb ;set the area 615 pop es 616 pop bp 617 ret 618 619 620 ;------------------------------------------------------------------------------ 621 622 623 624 OB equ @AB 625 X equ @AB+2 626 Y equ @AB+4 627 628 629 movexy: 630 push BP ; save frame pointer 631 mov BP,SP ; access stack pointer 632 push SI 633 push DI 634 635 mov DI,OB[BP] ; object pointer 636 637 mov AX,OB_X[DI] ; load registers 638 mov SI,OB_LX[DI] 639 mov CX,OB_DX[DI] 640 mov DX,OB_LDX[DI] 641 642 add SI,DX ; new X 643 adc AX,CX 644 645 mov OB_X[DI],AX 646 mov OB_LX[DI],SI 647 mov BX,X[BP] ; return new X 648 mov [BX],AX 649 650 mov AX,OB_Y[DI] ; load registers 651 mov SI,OB_LY[DI] 652 mov CX,OB_DY[DI] 653 mov DX,OB_LDY[DI] 654 655 add SI,DX ; new Y 656 adc AX,CX 657 658 mov OB_Y[DI],AX 659 mov OB_LY[DI],SI 660 mov BX,Y[BP] ; return new Y 661 mov [BX],AX 662 663 pop DI ; restore registers 664 pop SI 665 pop BP 666 ret 667 668 669 670 671 OB equ @AB 672 X equ @AB+2 673 Y equ @AB+4 674 675 676 setdxdy: 677 push BP ; save frame pointer 678 mov BP,SP ; access stack pointer 679 680 mov BX,OB[BP] ; object pointer 681 682 mov CX,X[BP] ; X increment *256 683 mov AL,CH 684 cbw ; X increment in AX 685 mov OB_DX[BX],AX ; save it. 686 mov AH,CL 687 xor AL,AL ; X remainder in AX 688 mov OB_LDX[BX],AX ; save it. 689 690 mov CX,Y[BP] ; Y increment *256 691 mov AL,CH 692 cbw ; Y increment in AX 693 mov OB_DY[BX],AX ; save it. 694 mov AH,CL 695 xor AL,AL ; Y remainder in AX 696 mov OB_LDY[BX],AX ; save it. 697 698 pop BP 699 ret 700 701 702 ;------------------------------------------------------------------------------ 703 ; 704 ; sound routine arithmetic 705 ; 706 707 soundmul: 708 push BP 709 mov BP,SP 710 711 mov AX,4[BP] 712 mul word ptr 6[BP] 713 mov BX,DX 714 715 mul word ptr 8[BP] 716 717 mov AX,BX 718 mov BX,DX 719 mul word ptr 8[BP] 720 721 add AX,BX 722 723 pop BP 724 ret 725 726 727 sounddiv: 728 push BP 729 mov BP,SP 730 731 mov AX,4[BP] 732 mov DX,6[BP] 733 div word ptr 8[BP] 734 735 pop BP 736 ret 737 738 739 ;------------------------------------------------------------------------------ 740 ; 741 ; dsseg(); 742 ; csseg(); 743 ; 744 ; segment returning functions 745 ; 746 747 748 dsseg: 749 mov AX,DS 750 ret 751 752 csseg: 753 mov AX,CS 754 ret 755 756 757 758 ;------------------------------------------------------------------------------ 759 760 .DATA 761 762 public ctlbflag 763 764 extrn joystick:word ; joystick being used flag 765 extrn ibmkeybd:word ; IBM-like keyboard being used 766 extrn inplay:word ; game is in play flag 767 extrn printflg:word ; print screen requested 768 extrn soundflg:word ; sound flag 769 extrn hires:word ; hi resolution flag 770 771 ctlbflag dw 0 ; control break flag 772 textclr db 3 ; current text colour 773 prevkey dw 0 ; previous keyboard return word 774 currkey dw 0 ; current keyboard return word 775 nextkey dw 0 ; next keyboard return word 776 prevjoy dw 0 ; previous joystick return word 777 currjoy dw 0 ; current joystick return word 778 nextjoy dw 0 ; next joystick return word 779 keyflag db 0 ; keyboard interrupt has occured 780 paused db 0 ; paused mode flag 781 782 scantable db 45,44,51,53,52,57,48,35,31,70,47,46 ; scan code table 783 scanmasks dw K_ACCEL,K_DEACC,K_FLAPU,K_FLAPD,K_FLIP ; scan mask table 784 dw K_SHOT, K_BOMB, K_HOME, K_SOUND,K_BREAK 785 dw K_MISSILE, K_STARBURST 786 lkeytable db "xz,/. bhs vc" ; lower case keystroke table 787 ukeytable db "XZ BHS VC" ; upper case keystroke table 788 joymasks dw K_FLIP,K_FLAPD,K_FLIP,K_DEACC,0,K_ACCEL ; jostick scan masks 789 dw K_FLIP,K_FLAPU,K_FLIP 790 791 printip dw 0 ; shift-print-screen server offset 792 printcs dw 0 ; segment 793 794 extrn _systype:word ; operating system 795 796 end 797 ÿ