This repository has been archived by the owner. It is now read-only.
Permalink
Cannot retrieve contributors at this time
5066 lines (4555 sloc)
122 KB
| ; Cute Mouse Driver - a tiny mouse driver | |
| ; | |
| ; Copyright (c) 1997-2002 Nagy Daniel <nagyd@users.sourceforge.net> | |
| ; | |
| ; BIOS wheel mouse support: Ported from Konstantin Koll's public | |
| ; domain code into Cute Mouse by Eric Auer 2007 (places marked -X-) | |
| ; | |
| ; This program is free software; you can redistribute it and/or modify | |
| ; it under the terms of the GNU General Public License as published by | |
| ; the Free Software Foundation; either version 2 of the License, or | |
| ; (at your option) any later version. | |
| ; | |
| ; This program is distributed in the hope that it will be useful, | |
| ; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| ; GNU General Public License for more details. | |
| ; | |
| ; You should have received a copy of the GNU General Public License | |
| ; along with this program; if not, write to the Free Software | |
| ; Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA | |
| ; -X- no longer: 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| ; | |
| ; NOTE: memcopy and MOVSEG_ have "assume..." as side effects! | |
| ; %pagesize 255 | |
| ; %noincl | |
| ;%macs | |
| ; %nosyms | |
| ;%depth 0 | |
| ; %linum 0 | |
| ;%pcnt 0 | |
| ;%bin 0 | |
| ; warn | |
| ; locals | |
| CTMVER equ <"2.1"> ; major driver version | |
| CTMRELEASE equ <"2.1 beta4"> ; full driver version with suffixes | |
| driverversion equ 705h ; imitated Microsoft driver version | |
| ; at least 705h because our int 33 function _26 operates in 7.05+ style | |
| FASTER_CODE = 0 ; optimize by speed instead size | |
| OVERFLOW_PROTECT = 0 ; prevent variables overflow | |
| FOOLPROOF = 1 ; check driver arguments validness | |
| USE28 = 0 ; include code for INT 33/0028 function | |
| USERIL = 0 ; include code for INT 10/Fn EGA functions | |
| ; %define PS2DEBUG 1 ; print debug messages for PS2serv calls | |
| .286 | |
| ;.386 | |
| ;------------------------------------------------------------------------ | |
| include asmlib/asm.mac | |
| ; *** include asmlib/hll.mac ; if_ loop_ countloop_ etc - TASM specific | |
| include asmlib/code.def | |
| include asmlib/code.mac | |
| include asmlib/macro.mac | |
| include asmlib/BIOS/area0.def ; ** int11 flags and various 40:xx gfx info | |
| ; HW_PS2 equ 4 ; bit set in int 11h returned AX if PS/2 mouse present | |
| ; VIDEO_control VIDEO_switches VIDEO_width VIDEO_pageoff VIDEO_mode | |
| ; VIDEO_switches VIDSW_feature0 VIDSW_display VIDEO_ptrtable@ | |
| ; VPARAM_SEQC VIDEO_paramtbl@ VIDEO_lastrow VIDEO_pageno | |
| include asmlib/convert/digit.mac ; ** only count2x uses digits in ASCII | |
| include asmlib/convert/count2x.mac ; ** only used as _word_hex for I/O port | |
| include asmlib/DOS/MCB.def ; ** small, used to set ownerid and name | |
| include asmlib/DOS/PSP.def ; ** only DOS_exit env_seg cmdline_len PSP_TSR used | |
| ; include asmlib/DOS/file.mac ; was only used once - DOSCloseFile | |
| include asmlib/DOS/mem.mac | |
| ; include asmlib/hard/PIC8259A.def ; only PIC1_OCW2, PIC1_IMR const used: | |
| PIC1_OCW2 equ 20h | |
| PIC1_IMR equ 21h | |
| include asmlib/hard/UART.def | |
| USE_286 equ <(@CPU and 4)> | |
| USE_386 equ <(@CPU and 8)> | |
| _ARG_DI_ equ <word ptr [bp]> | |
| _ARG_SI_ equ <word ptr [bp+2]> | |
| _ARG_BP_ equ <word ptr [bp+4]> | |
| if USE_286 | |
| _ARG_BX_ equ <word ptr [bp+8]> | |
| _ARG_DX_ equ <word ptr [bp+10]> | |
| _ARG_CX_ equ <word ptr [bp+12]> | |
| _ARG_AX_ equ <word ptr [bp+14]> | |
| _ARG_ES_ equ <word ptr [bp+16]> | |
| _ARG_DS_ equ <word ptr [bp+18]> | |
| ; arg offset: far pointer plus 8+2 words (push 2 segs, pusha) | |
| _ARG_OFFS_ = 24 | |
| PUSHALL equ <pusha> | |
| POPALL equ <popa> | |
| else ; USE_286 | |
| _ARG_BX_ equ <word ptr [bp+6]> | |
| _ARG_DX_ equ <word ptr [bp+8]> | |
| _ARG_CX_ equ <word ptr [bp+10]> | |
| _ARG_AX_ equ <word ptr [bp+12]> | |
| _ARG_ES_ equ <word ptr [bp+14]> | |
| _ARG_DS_ equ <word ptr [bp+16]> | |
| _ARG_OFFS_ = 22 | |
| PUSHALL macro | |
| push ax | |
| push cx | |
| push dx | |
| push bx | |
| push bp | |
| push si | |
| push di | |
| endm | |
| POPALL macro | |
| pop di | |
| pop si | |
| pop bp | |
| pop bx | |
| pop dx | |
| pop cx | |
| pop ax | |
| endm | |
| endif ; USE_286 | |
| nl equ <13,10> | |
| eos equ <0> | |
| POINT struc | |
| X dw 0 | |
| Y dw 0 | |
| POINT ends | |
| PS2serv macro serv:req,errlabel ; :vararg | |
| mov ax,serv | |
| %ifdef PS2DEBUG | |
| push ax | |
| mov al,'<' | |
| int 29h | |
| pop ax | |
| push ax | |
| and al,15 ; assume ax is c20n, only show low nibble | |
| add al,30h ; convert to digit | |
| int 29h | |
| mov al,'/' | |
| int 29h | |
| mov al,bh ; low nibble of bh is interesting, too | |
| add al,30h ; (func 7: es bx is pointer) | |
| int 29h | |
| pop ax | |
| %endif ; ifdef PS2DEBUG | |
| int 15h | |
| %ifdef PS2DEBUG | |
| pushf | |
| push ax | |
| mov al,20h ; space | |
| adc al,0 ; if carry, exclamation mark | |
| int 29h | |
| pop ax | |
| push ax | |
| mov al,ah | |
| add al,30h ; usually ah is only 0..9 status | |
| int 29h | |
| mov al,'/' | |
| int 29h | |
| mov al,bh ; func 1, 4: device id (1: bl is aa if okay) | |
| add al,30h ; can be ff+30 or aa+30 now :-p | |
| int 29h | |
| mov al,'>' | |
| int 29h | |
| pop ax | |
| popf | |
| %endif ; ifdef PS2DEBUG | |
| ifnb <errlabel> | |
| jc errlabel | |
| test ah,ah | |
| jnz errlabel | |
| endif | |
| endm | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ SEGMENTS DEFINITION ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ; .model use16 tiny | |
| assume ss:nothing | |
| @TSRcode equ <DGROUP> | |
| @TSRdata equ <DGROUP> | |
| ; TSR ends at TSRend, roughly line 3000 of the 4000 lines of ctmouse | |
| TSRcref equ <offset @TSRcode> ; offset relative TSR code group | |
| TSRdref equ <offset @TSRdata> ; - " - data | |
| coderef equ <offset @code> ; offset relative main code group | |
| dataref equ <offset @data> ; - " - data | |
| .code | |
| org 0 | |
| TSRstart label byte | |
| org 100h ; .COM style program | |
| start: jmp real_start | |
| TSRavail label byte ; initialized data may come from here | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ UNINITIALIZED DATA ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;!!! WARNING: don't init variables in uninitialized section because | |
| ; they will not be present in the executable image | |
| org PSP_TSR-3*16 ; reuse part of PSP | |
| spritebuf db 3*16 dup (?) ; copy of screen sprite in modes 4-6 | |
| ;----- application state ----- | |
| ;!!! WARNING: variables order between RedefArea and szDefArea must be | |
| ; syncronized with variables order after DefArea | |
| even | |
| SaveArea = $ | |
| RedefArea = $ | |
| mickey8 POINT ? ; mickeys per 8 pixel ratios | |
| ;;*doublespeed dw ? ; double-speed threshold (mickeys/sec) | |
| senscoeff POINT ? ; mickeys sensitivity, ~[1/3..3.0]*256 | |
| sensval POINT ? ; original 001A sensitivity values-1 | |
| startscan dw ? ; screen mask/cursor start scanline | |
| endscan dw ? ; cursor mask/cursor end scanline | |
| ;----- hotspot, screenmask and cursormask must follow as is ----- | |
| hotspot POINT ? ; cursor bitmap hot spot | |
| screenmask db 2*16 dup (?) ; user defined screen mask | |
| cursormask db 2*16 dup (?) ; user defined cursor mask | |
| nocursorcnt db ? ; 0=cursor enabled, else hide counter | |
| ;;*nolightpen? db ? ; 0=emulate light pen | |
| even | |
| szDefArea = $ - RedefArea ; initialized by softreset_21 | |
| rangemax POINT ? ; horizontal/vertical range max | |
| upleft POINT ? ; upper left of update region | |
| lowright POINT ? ; lower right of update region | |
| pos POINT ? ; virtual cursor position | |
| granpos POINT ? ; granulated virtual cursor position | |
| UIR@ dd ? ; user interrupt routine address | |
| even | |
| ClearArea = $ | |
| sensround POINT ? ; rounding error in applying | |
| ; sensitivity for mickeys | |
| rounderr POINT ? ; same in conversion mickeys to pixels | |
| even | |
| szClearArea1 = $ - ClearArea ; cleared by setpos_04 | |
| rangemin POINT ? ; horizontal/vertical range min | |
| even | |
| szClearArea2 = $ - ClearArea ; cleared by setupvideo | |
| cursortype db ? ; 0 - software, else hardware | |
| callmask db ? ; user interrupt routine call mask | |
| mickeys POINT ? ; mouse move since last access | |
| BUTTLASTSTATE struc | |
| counter dw ? | |
| lastrow dw ? | |
| lastcol dw ? | |
| BUTTLASTSTATE ends | |
| buttpress BUTTLASTSTATE ?,?,? | |
| buttrelease BUTTLASTSTATE ?,?,? | |
| wheel BUTTLASTSTATE ? ; wheel counter since last access | |
| wheelUIR db ? ; wheel counter for UIR | |
| even | |
| szClearArea3 = $ - ClearArea ; cleared by softreset_21 | |
| szSaveArea = $ - SaveArea | |
| if USERIL ; -X- | |
| ;----- registers values for RIL ----- | |
| ;!!! WARNING: registers order and RGROUPDEF contents must be fixed | |
| even | |
| VRegsArea = $ | |
| regs_SEQC db 5 dup (?) | |
| reg_MISC db ? | |
| regs_CRTC db 25 dup (?) | |
| regs_ATC db 21 dup (?) | |
| regs_GRC db 9 dup (?) | |
| reg_FC db ? | |
| reg_GPOS1 db ? | |
| reg_GPOS2 db ? | |
| DefVRegsArea = $ | |
| def_SEQC db 5 dup (?) | |
| def_MISC db ? | |
| def_CRTC db 25 dup (?) | |
| def_ATC db 21 dup (?) | |
| def_GRC db 9 dup (?) | |
| def_FC db ? | |
| def_GPOS1 db ? | |
| def_GPOS2 db ? | |
| szVRegsArea = $ - DefVRegsArea | |
| ; ERRIF (szVRegsArea ne 64 or $-VRegsArea ne 2*64) "VRegs area contents corrupted!" | |
| else | |
| crtc dw ? ; 3d4 or 3b4 | |
| endif ; -X- USERIL | |
| ;----- old interrupt vectors ----- | |
| oldint33 dd ? ; old INT 33 handler address | |
| oldIRQaddr dd ? ; old IRQ handler address | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ INITIALIZED DATA ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| even | |
| TSRdata label byte | |
| ; ERRIF (TSRdata lt TSRavail) "TSR uninitialized data area too small!" | |
| DefArea = $ | |
| POINT <8,16> ; mickey8 | |
| POINT <1*256,1*256> ; senscoeff | |
| POINT <49,49> ; sensval | |
| ;;* dw 64 ; doublespeed | |
| dw 77FFh,7700h ; startscan, endscan | |
| POINT <0,0> ; hotspot | |
| dw 0011111111111111b ; screenmask | |
| dw 0001111111111111b | |
| dw 0000111111111111b | |
| dw 0000011111111111b | |
| dw 0000001111111111b | |
| dw 0000000111111111b | |
| dw 0000000011111111b | |
| dw 0000000001111111b | |
| dw 0000000000111111b | |
| dw 0000000000011111b | |
| dw 0000000111111111b | |
| dw 0000000011111111b | |
| dw 0011000011111111b | |
| dw 1111100001111111b | |
| dw 1111100001111111b | |
| dw 1111110011111111b | |
| dw 0000000000000000b ; cursormask | |
| dw 0100000000000000b | |
| dw 0110000000000000b | |
| dw 0111000000000000b | |
| dw 0111100000000000b | |
| dw 0111110000000000b | |
| dw 0111111000000000b | |
| dw 0111111100000000b | |
| dw 0111111110000000b | |
| dw 0111110000000000b | |
| dw 0110110000000000b | |
| dw 0100011000000000b | |
| dw 0000011000000000b | |
| dw 0000001100000000b | |
| dw 0000001100000000b | |
| dw 0000000000000000b | |
| db 1 ; nocursorcnt | |
| ;;* db 0 ; nolightpen? | |
| db 0 ; JWASM would use 0fch, "CLD" as pad byte?? | |
| even | |
| ; ERRIF ($-DefArea ne szDefArea) "Defaults area contents corrupted!" | |
| ;----- driver and video state begins here ----- | |
| even | |
| granumask POINT <-1,-1> | |
| textbuf label word | |
| buffer@ dd ? ; pointer to screen sprite copy | |
| cursor@ dw -1,0 ; cursor sprite offset in videoseg; | |
| ; -1=cursor not drawn | |
| videoseg equ <cursor@[2]> ; 0=not supported video mode | |
| UIRunlock db 1 ; 0=user intr routine is in progress | |
| videolock db 1 ; drawing: 1=ready,0=busy,-1=busy+queue | |
| newcursor db 0 ; 1=force cursor redraw | |
| ;----- table of pointers to registers values for RIL ----- | |
| REGSET struc | |
| rgroup dw ? | |
| regnum db ? | |
| regval db ? | |
| REGSET ends | |
| db 0 ; JWASM would use 0fch, "CLD" as pad byte?? | |
| even | |
| dw (vdata1end-vdata1)/(size REGSET) | |
| vdata1 REGSET <10h,1>,<10h,3>,<10h,4>,<10h,5>,<10h,8>,<08h,2> | |
| vdata1end label word | |
| dw (vdata2end-vdata2)/(size REGSET) | |
| vdata2 REGSET <10h,1,0>,<10h,4,0>,<10h,5,1>,<10h,8,0FFh>,<08h,2,0Fh> | |
| vdata2end label byte | |
| RGROUPDEF struc | |
| port@ dw ? | |
| regs@ dw ? | |
| def@ dw ? | |
| regscnt db 1 | |
| rmodify? db 0 | |
| RGROUPDEF ends | |
| if USERIL ; -X- | |
| even | |
| videoregs@ label RGROUPDEF | |
| RGROUPDEF <3D4h,regs_CRTC,def_CRTC,25> ; CRTC | |
| RGROUPDEF <3C4h,regs_SEQC,def_SEQC,5> ; Sequencer | |
| RGROUPDEF <3CEh,regs_GRC, def_GRC, 9> ; Graphics controller | |
| RGROUPDEF <3C0h,regs_ATC, def_ATC, 20> ; VGA attrib controller | |
| RGROUPDEF <3C2h,reg_MISC, def_MISC> ; VGA misc output and input | |
| RGROUPDEF <3DAh,reg_FC, def_FC> ; Feature Control | |
| RGROUPDEF <3CCh,reg_GPOS1,def_GPOS1> ; Graphics 1 Position | |
| RGROUPDEF <3CAh,reg_GPOS2,def_GPOS2> ; Graphics 2 Position | |
| endif ; -X- USERIL | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ IRQ HANDLERS ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| IRQhandler proc | |
| assume ds:nothing,es:nothing | |
| cld | |
| push ds | |
| push es | |
| PUSHALL | |
| MOVSEG ds,cs,,@TSRdata | |
| ; CODE_ MOV_CX IOdone,<db ?,0> ; processed bytes counter | |
| OPCODE_MOV_CX | |
| IOdone db ?,0 | |
| ; -X- IRQproc label byte ; "mov al,OCW2<OCW2_EOI>" | |
| ; -X- j PS2proc ; if serial mode | |
| ; -X- out PIC1_OCW2,al ; {20h} end of interrupt | |
| ; out_ PIC1_OCW2,%OCW2<OCW2_EOI> | |
| mov al,20h | |
| out PIC1_OCW2,al | |
| ; CODE_ MOV_DX IO_address,<dw ?> ; UART IO address | |
| OPCODE_MOV_DX | |
| IO_address dw ? | |
| push dx | |
| movidx dx,LSR_index | |
| in al,dx ; {3FDh} LSR: get status | |
| xchg bx,ax ; OPTIMIZE: instead MOV BL,AL | |
| pop dx | |
| movidx dx,RBR_index | |
| in al,dx ; {3F8h} flush receive buffer | |
| test bl,mask LSR_break+mask LSR_FE+mask LSR_OE | |
| ; if_ nz ; if break/framing/overrun | |
| jz @@irqhandlerz | |
| xor cx,cx ; errors then restart | |
| mov [IOdone],cl ; sequence: clear counter | |
| ; end_ | |
| @@irqhandlerz: | |
| shr bl,LSR_RBF+1 | |
| ; if_ carry ; process data if data ready | |
| jnc @@irqhandlernc | |
| call_ mouseproc,MSMproc ; never PS/2 | |
| ; end_ | |
| @@irqhandlernc: | |
| jmp rethandler | |
| IRQhandler endp | |
| assume ds:@TSRdata | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Enable PS/2 | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX, BX, DX, ES | |
| ; Call: INT 15/C2xx, -X- setRateTSR | |
| ; -X- @disablePS2, INT 21/25 --> no longer (re)hooks IRQ | |
| ; | |
| enablePS2 proc | |
| ; -X- call @disablePS2 ; unhooked IRQ | |
| MOVSEG es,cs,,@TSRcode | |
| mov bx,TSRcref:PS2handler ; -X- real handler now | |
| PS2serv 0C207h ; set mouse handler in ES:BX | |
| mov bh,1 | |
| PS2serv 0C200h ; set mouse on (bh=1) | |
| ; -X- DOSSetIntr 68h+12,,,@TSRcode:IRQhandler | |
| mov bh,5 ; -X- 100, KoKo uses 3 (60) | |
| call setRateTSR ; -X- | |
| ret | |
| ; -X- PS2dummy: retf | |
| enablePS2 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Disable PS/2 | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: oldIRQaddr | |
| ; Modf: AX, BX, DX, ES | |
| ; Call: INT 15/C2xx, -X- setRateTSR | |
| ; -X- INT 21/25 --> no longer unhooks IRQ (irq 12, int 74) | |
| ; | |
| disablePS2 proc | |
| @disablePS2: xor bx,bx | |
| PS2serv 0C200h ; set mouse off (bh=0) | |
| MOVSEG es,bx,,nothing | |
| PS2serv 0C207h ; clear mouse handler (ES:BX=0) | |
| mov bh,5 ; -X- KoKo uses 15/C201 here | |
| call setRateTSR ; -X- | |
| ret | |
| disablePS2 endp | |
| assume ds:@TSRdata ; added...? | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; -X- A "light" version for the TSR... In: BH=0..6 for 20,40,60,80,100,200 | |
| ; Set mouse sampling rate to "RATES[BH]" samples per second | |
| setRateTSR proc | |
| PS2serv 0C202h ; set rate, ignore errors | |
| ret | |
| setRateTSR endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; -X- this handler is called by the BIOS, it is no IRQ handler :-) | |
| PS2handler proc | |
| assume ds:nothing,es:nothing | |
| push ds | |
| push es | |
| PUSHALL | |
| MOVSEG ds,cs,,@TSRdata | |
| mov bp,sp | |
| PS2WHEELCODE label byte ; jump to wheel or plain: test 0/-1 | |
| ; test sp,0 ; 2 byte opcode, sp always NZ here | |
| ; jnz PS2WHEEL | |
| j @@PS2PLAIN | |
| ; stack for non-wheel mice: ... - - Y - X - BTN - | |
| ; stack for wheel mice: ... - - W - Y - BTN X | |
| ; flags: (yext) (xext) ysign xsign 1 btn3 btn1 btn2 | |
| ; ("ext" flag could be used to trigger "xor value,100h") | |
| @@PS2PLAIN: ; old cutemouse 1.9 PS/2 handler, non-wheel | |
| ; note: ctmouse 1.9 code uses only sign, not ext | |
| mov al,[bp+_ARG_OFFS_+6] ; buttons and flags | |
| if USE_286 | |
| mov bl,al ; backup, xchg will restore | |
| shl al,3 ; CF=Y sign bit, MSB=X sign | |
| else | |
| mov cl,3 | |
| mov bl,al ; backup, xchg will restore | |
| shl al,cl ; CF=Y sign bit, MSB=X sign | |
| endif | |
| ; sbb ch,ch ; extend Y sign bit | |
| db 1ah, 0edh ; JWASM and TASM use opposite encoding | |
| cbw ; extend X sign bit | |
| mov al,[bp+_ARG_OFFS_+4] ; AX=X movement | |
| xchg bx,ax ; X to BX, buttons to AL | |
| mov cl,[bp+_ARG_OFFS_+2] ; CX=Y movement | |
| ; wheelmask is 0 now, so no wheel data is expected in AH | |
| j @@PS2DONE | |
| ; stack for non-wheel mice: ... - - Y - X - BTN - | |
| ; stack for wheel mice: ... - - W - Y - BTN X | |
| ; flags: (yext) (xext) ysign xsign 1 btn3 btn1 btn2 | |
| ; "ext" flag can be used to trigger "xor value,100h" | |
| PS2WHEEL:: ; handler based on public domain code from Konstantin Koll | |
| ; old KoKo code used only ext, not sign, ok on all but Alps | |
| mov al,[bp+_ARG_OFFS_+6] ; buttons and flags | |
| if USE_286 | |
| mov bl,al ; backup, xchg will restore | |
| shl al,3 ; CF=Y sign bit, MSB=X sign | |
| else | |
| mov cl,3 | |
| mov bl,al ; backup, xchg will restore | |
| shl al,cl ; CF=Y sign bit, MSB=X sign | |
| endif | |
| ; sbb ch,ch ; extend Y sign bit | |
| db 1ah, 0edh ; JWASM and TASM use opposite encoding | |
| cbw ; extend X sign bit | |
| mov al,[bp+_ARG_OFFS_+7] ; AX=X movement <-- | |
| xchg bx,ax ; X to BX, buttons to AL | |
| mov cl,[bp+_ARG_OFFS_+4] ; CX=Y movement <-- | |
| mov ah,[bp+_ARG_OFFS_+2] ; AH=Wheel data <-- | |
| ; reverseY does not seem to support 9th bit, must skip that | |
| @@PS2DONE: call reverseY ; AL flags AH wheel BX X CX Y | |
| POPALL | |
| pop es | |
| pop ds | |
| retf | |
| PS2handler endp | |
| assume ds:@TSRdata ; added...? | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Enable serial interrupt in PIC | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: IO_address | |
| ; Modf: AX, DX, SI, IOdone, MSLTbuttons | |
| ; Call: INT 21/25 | |
| ; | |
| enableUART proc | |
| ;----- set new IRQ handler | |
| mov dx,TSRcref:IRQhandler ; -X- IRQintnum 0 means none | |
| ; CODE_ MOV_AX IRQintnum,<db 0,25h> ; INT number of selected IRQ | |
| OPCODE_MOV_AX | |
| IRQintnum db 0,25h | |
| int 21h ; set INT in DS:DX | |
| ;----- set communication parameters | |
| mov si,[IO_address] | |
| movidx dx,LCR_index,si | |
| ; out_ dx,%LCR{LCR_DLAB=1} ; {3FBh} LCR: DLAB on | |
| ; mov al,%LCR{LCR_DLAB=1} ; {3FBh} LCR: DLAB on | |
| mov al,80h | |
| out dx,al | |
| ; xchg dx,si ; 1200 baud rate | |
| xchg si,dx ; JWASM and TASM use opposite encoding | |
| mov ax,96 | |
| ; outw dx,96 ; {3F8h},{3F9h} divisor latch | |
| out dx,ax | |
| ; xchg dx,si | |
| xchg si,dx ; JWASM and TASM use opposite encoding | |
| ; CODE_ MOV_AX | |
| OPCODE_MOV_AX | |
| LCRset db 00000010b ; LCR <0,,LCR_noparity,0,2> ; {3FBh} LCR: DLAB off, 7/8N1 | |
| db 00001111b ; MCR <,,,1,1,1,1> ; {3FCh} MCR: DTR/RTS/OUTx on | |
| out dx,ax | |
| ;----- prepare UART for interrupts | |
| movidx dx,RBR_index,si,LCR_index | |
| in al,dx ; {3F8h} flush receive buffer | |
| movidx dx,IER_index,si,RBR_index | |
| ; out_ dx,%IER{IER_DR=1},%FCR<>; {3F9h} IER: enable DR intr | |
| ; {3FAh} FCR: disable FIFO | |
| ; mov al,%IER{IER_DR=1} | |
| ; mov ah,%FCR<> | |
| mov ax,1 | |
| out dx,ax | |
| dec ax ; OPTIMIZE: instead MOV AL,0 | |
| mov [IOdone],al | |
| mov [MSLTbuttons],al | |
| ;----- | |
| in al,PIC1_IMR ; {21h} get IMR | |
| ; CODE_ AND_AL notPIC1state,<db ?> ; clear bit to enable interrupt | |
| OPCODE_AND_AL | |
| notPIC1state db ? | |
| out PIC1_IMR,al ; {21h} enable serial interrupts | |
| ret | |
| enableUART endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Disable serial interrupt of PIC | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: IO_address, oldIRQaddr | |
| ; Modf: AX, DX | |
| ; Call: INT 21/25 | |
| ; | |
| disableUART proc | |
| in al,PIC1_IMR ; {21h} get IMR | |
| ; CODE_ OR_AL PIC1state,<db ?> ; set bit to disable interrupt | |
| OPCODE_OR_AL | |
| PIC1state db ? | |
| out PIC1_IMR,al ; {21h} disable serial interrupts | |
| ;----- | |
| ;!!! MS/Logitech ID bytes (4Dh)+PnP data looks as valid mouse packet, which | |
| ; moves mouse; to prevent unnecessary send of PnP data after disabling | |
| ; driver with following enabling, below DTR and RTS remained active | |
| movidx dx,LCR_index,[IO_address] ; {3FBh} LCR: DLAB off | |
| ; out_ dx,%LCR<>,%MCR<,,,0,,1,1> ; {3FCh} MCR: DTR/RTS on, OUT2 off | |
| ; mov al,%LCR<> | |
| ; mov ah,%MCR<,,,0,,1,1> | |
| mov ax,300h | |
| out dx,ax | |
| movidx dx,IER_index,,LCR_index | |
| ;mov al,IER<> | |
| out dx,al ; {3F9h} IER: interrupts off | |
| ;----- restore old IRQ handler | |
| push ds | |
| mov ax,word ptr [IRQintnum] ; AH=25h | |
| lds dx,[oldIRQaddr] | |
| assume ds:nothing | |
| int 21h ; set INT in DS:DX | |
| pop ds | |
| ret | |
| disableUART endp | |
| assume ds:@TSRdata | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Process the Microsoft/Logitech packet bytes | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| MSLTproc proc | |
| ; CODE_ MOV_DL MSLTbuttons,<db ?> ; buttons state for MS3/LT/WM | |
| OPCODE_MOV_DL | |
| MSLTbuttons db ? | |
| test al,01000000b ; =40h ; synchro check | |
| ; if_ nz ; if first byte | |
| jz @@msltz | |
| mov [IOdone],1 ; request next 2/3 bytes | |
| mov [MSLT_1],al | |
| MSLTCODE1 label byte ; "ret" if not LT/WM | |
| xchg ax,cx ; OPTIMIZE: instead MOV AL,CL | |
| sub al,3 ; if first byte after 3 bytes | |
| jz @@LTWMbutton3 ; then release middle button | |
| ret | |
| ; end_ | |
| @@msltz: | |
| ; if_ ncxz ; skip nonfirst byte at start | |
| jcxz @@msltcxz | |
| inc [IOdone] ; request next byte | |
| loop @@MSLT_3 | |
| mov [MSLT_X],al ; keep X movement LO | |
| ; end_ | |
| @@msltcxz: | |
| @@LTret: ret | |
| @@MSLT_3: loop @@LTWM_4 | |
| ;mov cl,0 | |
| ; CODE_ MOV_BX MSLT_1,<db ?,0> ; mouse packet first byte | |
| OPCODE_MOV_BX | |
| MSLT_1 db ?,0 | |
| ror bx,2 | |
| ; xchg cl,bh ; bits 1-0: X movement HI | |
| xchg bh,cl ; TASM and JWASM use opposite encoding | |
| ror bx,2 ; bits 5-4: LR buttons | |
| or al,bh ; bits 3-2: Y movement HI | |
| cbw | |
| xchg cx,ax ; CX=Y movement | |
| ; CODE_ OR_AL MSLT_X,<db ?> | |
| OPCODE_OR_AL | |
| MSLT_X db ? | |
| cbw | |
| xchg bx,ax ; BX=X movement | |
| ;cbw ; clear wheel value | |
| xor al,dl | |
| and al,00000011b ; =3 ; LR buttons change mask | |
| mov dh,al | |
| or dh,bl ; nonzero if LR buttons state | |
| or dh,cl ; changed or mouse moved | |
| MSLTCODE2 label byte | |
| j @@MSLTupdate ; "jnz" if MS3 | |
| or al,00000100b ; =4 ; empty event toggles button | |
| j @@MSLTupdate | |
| @@LTWM_4: ;mov ch,0 | |
| mov [IOdone],ch ; request next packet | |
| MSLTCODE3 label byte ; if LT "mov cl,3" else | |
| @@LTWMbutton3: mov cl,3 ; if WM "mov cl,2" else "ret" | |
| mov ah,al | |
| shr al,cl | |
| xor al,dl | |
| and ax,111100000100b ; =0F04h | |
| if FASTER_CODE | |
| jz @@LTret ; exit if button 3 not changed | |
| endif | |
| xor bx,bx | |
| xor cx,cx | |
| @@MSLTupdate: xor al,dl ; new buttons state | |
| mov [MSLTbuttons],al | |
| j swapbuttons | |
| MSLTproc endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Process the Mouse Systems packet bytes | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| MSMproc proc | |
| jcxz @@MSM_1 | |
| cbw | |
| dec cx | |
| jz @@MSM_2 | |
| dec cx | |
| jz @@MSM_3 | |
| loop @@MSM_5 | |
| @@MSM_4: add ax,[MSM_X] | |
| @@MSM_2: mov [MSM_X],ax | |
| j @@MSMnext | |
| @@MSM_1: xor al,10000111b ; =87h ; sync check: AL should | |
| test al,11111000b ; =0F8h ; be equal to 10000lmr | |
| ; if_ zero | |
| jnz @@msmnz | |
| test al,00000110b ; =6 ; check the L and M buttons | |
| ; if_ odd ; if buttons not same | |
| jpe @@msmeven | |
| xor al,00000110b ; =6 ; swap them | |
| ; end_ | |
| @@msmeven: | |
| mov [MSM_buttons],al ; bits 2-0: MLR buttons | |
| ;j @@MSMnext | |
| @@MSM_3: mov [MSM_Y],ax | |
| @@MSMnext: inc [IOdone] ; request next byte | |
| ; end_ | |
| @@msmnz: | |
| ret | |
| @@MSM_5: ;mov ch,0 | |
| mov [IOdone],ch ; request next packet | |
| ; CODE_ ADD_AX MSM_Y,<dw ?> | |
| OPCODE_ADD_AX | |
| MSM_Y dw ? | |
| ; CODE_ MOV_BX MSM_X,<dw ?> | |
| OPCODE_MOV_BX | |
| MSM_X dw ? | |
| xchg cx,ax ; OPTIMIZE: instead MOV CX,AX | |
| ; CODE_ MOV_AL MSM_buttons,<db ?> | |
| OPCODE_MOV_AL | |
| MSM_buttons db ? | |
| ;j reverseY ; reverseY is next line anyway | |
| MSMproc endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Update mouse status | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: AL (new buttons state, 2 or 3 LSB used) | |
| ; AH (wheel movemement) | |
| ; BX (X mouse movement) | |
| ; CX (Y mouse movement) | |
| ; Out: none | |
| ; Use: callmask, granpos, mickeys, UIR@ | |
| ; Modf: AX, CX, DX, BX, SI, DI, wheel, wheelUIR, UIRunlock | |
| ; Call: updateposition, updatebutton, refreshcursor | |
| ; | |
| reverseY proc | |
| neg cx ; reverse Y movement | |
| ;j swapbuttons | |
| reverseY endp | |
| swapbuttons proc | |
| test al,00000011b ; =3 ; check the L and R buttons | |
| ; if_ odd ; if buttons not same | |
| jpe @@swapeven | |
| ; CODE_ XOR_AL swapmask,<db 00000011b> ; 0 if (PS2 xor LEFTHAND) | |
| OPCODE_XOR_AL | |
| swapmask db 00000011b | |
| ; end_ | |
| @@swapeven: | |
| ;j mouseupdate | |
| swapbuttons endp | |
| mouseupdate proc | |
| ; CODE_ AND_AX | |
| OPCODE_AND_AX | |
| buttonsmask db 00000111b ; =8 | |
| wheelmask db 0 | |
| xchg di,ax ; keep btn, wheel state in DI | |
| ;----- update mickey counters and screen position | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| ; MOVREG_ bx,<offset X> | |
| xor bx,bx ; MOVREG optimizes mov bx,offset POINT.X into this | |
| call updateposition | |
| xchg ax,cx | |
| ; MOVREG_ bl,<offset Y> ; OPTIMIZE: BL instead BX | |
| mov bl,offset POINT.Y | |
| call updateposition | |
| or cl,al ; bit 0=mickeys change flag | |
| ;----- update wheel movement | |
| mov ax,[mickeys.Y] | |
| xchg ax,di ; retrieve button, wheel info | |
| xchg dx,ax ; OPTIMIZE: instead MOV DX,AX | |
| mov al,dh ; wheel: signed 4 bit value | |
| xor al,00001000b ; =8 | |
| sub al,00001000b ; =8 ; sign extension AL[0:3]->AL | |
| ; if_ nz ; if wheel moved | |
| jz @@wheelz | |
| cbw | |
| mov si,TSRdref:wheel | |
| add [si + offset BUTTLASTSTATE.counter],ax ; wheel counter | |
| add [wheelUIR],al ; same, but used for the UIR | |
| mov al,10000000b ; =80h ; bit 7=wheel movement flag | |
| xor bx,bx | |
| call @lastpos | |
| ; end_ | |
| @@wheelz: | |
| ;----- update buttons state | |
| mov dh,dl ; DH=buttons new state | |
| xchg dl,[buttstatus] | |
| xor dl,dh ; DL=buttons change state | |
| if FASTER_CODE | |
| ; if_ nz | |
| jz @@btnfastz | |
| endif | |
| xor bx,bx ; buttpress array index | |
| mov al,00000010b ; mask for button 1 | |
| call updatebutton | |
| mov al,00001000b ; mask for button 2 | |
| call updatebutton | |
| mov al,00100000b ; mask for button 3 | |
| call updatebutton | |
| if FASTER_CODE | |
| ; end_ | |
| @@btnfastz: | |
| endif | |
| ;----- call User Interrupt Routine (CX=events mask) | |
| dec [UIRunlock] | |
| ; if_ zero ; if user proc not running | |
| jnz @@uirnz | |
| and cl,[callmask] | |
| ; if_ nz ; if there is a user events | |
| jz @@maskz | |
| ; CODE_ MOV_BX buttstatus,<db 0,0> ; buttons status | |
| OPCODE_MOV_BX | |
| buttstatus db 0,0 | |
| xchg bh,[wheelUIR] | |
| mov ax,[granpos.X] | |
| mov dx,[granpos.Y] | |
| xchg ax,cx | |
| mov si,[mickeys.X] | |
| ;mov di,[mickeys.Y] | |
| push ds | |
| sti | |
| call [UIR@] | |
| pop ds | |
| ; end_ | |
| @@maskz: | |
| call refreshcursor | |
| ; end_ | |
| @@uirnz: | |
| ;----- | |
| inc [UIRunlock] | |
| ret | |
| mouseupdate endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: AX (mouse movement) | |
| ; BX (offset X/offset Y) | |
| ; Out: AX (1 - mickey counter changed) | |
| ; Use: mickey8, rangemax, rangemin, granumask, senscoeff | |
| ; Modf: DX, SI, sensround, mickeys, rounderr, pos, granpos | |
| ; | |
| updateposition proc | |
| test ax,ax | |
| jz @@uposret | |
| mov si,ax | |
| ; if_ sign | |
| jns @@upns | |
| neg ax | |
| ; end_ | |
| @@upns: | |
| ;----- apply sensitivity (SI=movement, AX=abs(SI)) | |
| mov dx,word ptr senscoeff[bx] ; ~[1/3..3.0]*256 | |
| ; cmp ax,4 ; JWASM uses "signed byte" variant | |
| db 03dh, 4, 0 ; "cmp ax, word 4" | |
| ; if_ be | |
| ja @@upa | |
| mov ax,si | |
| cmp dh,1 ; skip [-4..4] movements | |
| jae @@newmickeys ; when sensitivity >= 1.0 | |
| imul dx ; =mickeys*sensitivity | |
| ; else_ | |
| jmp short @@upbe | |
| @@upa: | |
| ; cmp ax,12 ; JWASM uses "signed byte" variant | |
| db 03dh, 12, 0 ; "cmp ax, word 12" | |
| ; if_ ae | |
| if FASTER_CODE | |
| jb @@up2b | |
| mov ax,dx | |
| shl ax,1 | |
| add ax,dx ; =sensitivity*3 | |
| ; else_ | |
| jmp short @@up2ae | |
| @@up2b: | |
| mul dx | |
| shr ax,2 ; =sensitivity*min(12,abs(mickeys))/4 | |
| ; end_ | |
| @@up2ae: | |
| else | |
| jb @@up2ae | |
| mov ax,12 | |
| ; end_ | |
| @@up2ae: | |
| mul dx | |
| shr ax,2 ; =sensitivity*min(12,abs(mickeys))/4 | |
| endif | |
| imul si ; DX:AX=mickeys*newsensitivity | |
| ; end_ | |
| @@upbe: | |
| add al,byte ptr sensround[bx] | |
| mov byte ptr sensround[bx],al | |
| mov al,ah ; remove 256 multiplier from | |
| mov ah,dl ; sensitivity: AX=DX:AX/256 | |
| ; adc ax,0 ; add carry from previous adding | |
| db 15h, 0, 0 ; JWASM uses signed byte variant, same length | |
| ;----- apply mickeys per 8 pixels ratio to calculate cursor position | |
| @@newmickeys: add word ptr mickeys[bx],ax | |
| if FASTER_CODE | |
| mov si,word ptr mickey8[bx] | |
| cmp si,8 | |
| if_ ne | |
| shl ax,3 | |
| dec si | |
| andif_ gt | |
| add ax,word ptr rounderr[bx] | |
| inc si | |
| cwd | |
| idiv si | |
| mov word ptr rounderr[bx],dx | |
| test ax,ax | |
| jz @@uposdone | |
| end_ | |
| else | |
| shl ax,3 | |
| add ax,word ptr rounderr[bx] | |
| cwd | |
| idiv word ptr mickey8[bx] | |
| mov word ptr rounderr[bx],dx | |
| endif | |
| add ax,word ptr pos[bx] | |
| ;----- cut new position by virtual ranges and save | |
| @savecutpos:: mov dx,word ptr rangemax[bx] | |
| cmp ax,dx | |
| jge @@cutpos | |
| mov dx,word ptr rangemin[bx] | |
| cmp ax,dx | |
| ; if_ le | |
| jg @@cpg | |
| @@cutpos: xchg ax,dx ; OPTIMIZE: instead MOV AX,DX | |
| ; end_ | |
| @@cpg: | |
| mov word ptr pos[bx],ax ; new position | |
| and al,byte ptr granumask[bx] | |
| mov word ptr granpos[bx],ax ; new granulated position | |
| @@uposdone: mov ax,1 | |
| @@uposret: ret | |
| updateposition endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: AL (unrolled press bit mask) | |
| ; CL (unrolled buttons change state) | |
| ; DL (buttons change state) | |
| ; DH (buttons new state) | |
| ; BX (buttpress array index) | |
| ; Out: CL | |
| ; DX (shifted state) | |
| ; BX (next index) | |
| ; Use: granpos | |
| ; Modf: AX, SI, buttpress, buttrelease | |
| ; | |
| updatebutton proc | |
| shr dx,1 | |
| ; if_ carry ; if button changed | |
| jnc @@ubnc | |
| mov si,TSRdref:buttpress | |
| test dl,dl | |
| ; if_ ns ; if button not pressed | |
| js @@ubs | |
| add al,al ; indicate that it released | |
| mov si,TSRdref:buttrelease | |
| ; end_ | |
| @@ubs: | |
| inc word ptr [si + bx + offset BUTTLASTSTATE.counter] | |
| @lastpos:: or cl,al | |
| mov ax,[granpos.Y] | |
| mov [si + bx + offset BUTTLASTSTATE.lastrow],ax | |
| mov ax,[granpos.X] | |
| mov [si + bx + offset BUTTLASTSTATE.lastcol],ax | |
| ; end_ | |
| @@ubnc: | |
| add bx,size BUTTLASTSTATE ; next button | |
| ret | |
| updatebutton endp | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ END OF IRQ HANDLERS ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ INT 10 HANDLER ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| if USERIL ; -X- | |
| even | |
| RILtable dw TSRcref:RIL_F0 ; RIL functions | |
| dw TSRcref:RIL_F1 | |
| dw TSRcref:RIL_F2 | |
| dw TSRcref:RIL_F3 | |
| dw TSRcref:RIL_F4 | |
| dw TSRcref:RIL_F5 | |
| dw TSRcref:RIL_F6 | |
| dw TSRcref:RIL_F7 | |
| endif ; -X- USERIL | |
| int10handler proc | |
| assume ds:nothing,es:nothing | |
| cld | |
| test ah,ah ; set video mode? | |
| jz @@setmode | |
| cmp ah,11h ; font manipulation function | |
| je @@setnewfont | |
| cmp ax,4F02h ; VESA set video mode? | |
| je @@setmode | |
| if USERIL ; -X- | |
| cmp ah,0F0h ; RIL func requested? | |
| jb @@jmpold10 | |
| cmp ah,0F7h | |
| jbe @@RIL | |
| cmp ah,0FAh | |
| je @@RIL_FA | |
| endif ; -X- USERIL | |
| @@jmpold10: jmp_far oldint10 | |
| @@setnewfont: cmp al,10h | |
| jb @@jmpold10 | |
| cmp al,20h | |
| jae @@jmpold10 | |
| ;j @@setmode | |
| ;===== set video mode or activate font | |
| @@setmode: push ax | |
| mov ax,2 | |
| pushf ;!!! Logitech MouseWare | |
| push cs ; Windows driver workaround | |
| call handler33 ; hide mouse cursor | |
| pop ax | |
| pushf | |
| call [oldint10] | |
| push ds | |
| push es | |
| PUSHALL | |
| MOVSEG ds,cs,,@TSRdata | |
| mov [nocursorcnt],1 ; normalize hide counter | |
| call setupvideo | |
| @@exitINT10: jmp rethandler | |
| if USERIL ; -X- | |
| ;===== RIL | |
| @@RIL: push ds es | |
| PUSHALL | |
| MOVSEG ds,cs,,@TSRdata | |
| mov bp,sp | |
| mov al,ah | |
| and ax,0Fh ;!!! AH must be 0 for RIL_* | |
| mov si,ax | |
| add si,si | |
| call RILtable[si] | |
| j @@exitINT10 | |
| ;----- | |
| @@RIL_FA: MOVSEG es,cs,,@TSRcode ; RIL FA - Interrogate driver | |
| mov bx,TSRcref:RILversion | |
| else ; -X- | |
| assume ds:nothing ; -X- | |
| assume es:nothing ; -X- | |
| endif ; -X- USERIL | |
| iret | |
| int10handler endp | |
| if USERIL ; -X- | |
| assume ds:@TSRdata | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F0 - Read one register | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: DX (group index) | |
| ; BX (register #) | |
| ; Out: BL (value) | |
| ; Use: videoregs@ | |
| ; Modf: AL, SI | |
| ; Call: none | |
| ; | |
| RIL_F0 proc | |
| mov si,dx | |
| mov si,videoregs@[si].regs@ | |
| cmp dx,20h | |
| ; if_ below ; if not single register | |
| jae @@rilf0ae | |
| add si,bx | |
| ; end_ | |
| @@rilf0ae: | |
| lodsb | |
| mov byte ptr [_ARG_BX_],al | |
| ret | |
| RIL_F0 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F1 - Write one register | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: DX (group index) | |
| ; BL (value for single reg) | |
| ; BL (register # otherwise) | |
| ; BH (value otherwise) | |
| ; Out: BL (value) | |
| ; Use: none | |
| ; Modf: AX | |
| ; Call: RILwrite | |
| ; | |
| RIL_F1 proc | |
| mov ah,bl | |
| cmp dx,20h | |
| jae RILwrite ; jump if single registers | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| mov byte ptr [_ARG_BX_],ah | |
| ;j RILwrite | |
| RIL_F1 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: DX (group index) | |
| ; AL (register # for regs group) | |
| ; AH (value to write) | |
| ; Out: none | |
| ; Use: videoregs@ | |
| ; Modf: AL, DX, BX, DI | |
| ; Call: RILoutAH, RILgroupwrite | |
| ; | |
| RILwrite proc | |
| xor bx,bx | |
| mov di,dx | |
| cmp dx,20h | |
| mov dx,videoregs@[di].port@ | |
| mov videoregs@[di].rmodify?,dl ; OPTIMIZE: DL instead 1 | |
| mov di,videoregs@[di].regs@ | |
| ; if_ below ; if not single register | |
| jae @@rilwae | |
| mov bl,al | |
| ; end_ | |
| @@rilwae: | |
| mov [di+bx],ah | |
| jae RILoutAH | |
| ;j RILgroupwrite | |
| RILwrite endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: DX (IO port) | |
| ; AL (register #) | |
| ; AH (value to write) | |
| ; Out: none | |
| ; Use: videoregs@ | |
| ; Modf: none | |
| ; Call: none | |
| ; | |
| RILgroupwrite proc | |
| cmp dl,0C0h | |
| ; if_ ne ; if not ATTR controller | |
| jz @@rilgwz | |
| out dx,ax ; <--- | |
| ret | |
| ; end_ | |
| @@rilgwz: | |
| push ax dx | |
| mov dx,videoregs@[(size RGROUPDEF)*5].port@ | |
| in al,dx ; <--- ; {3DAh} force address mode | |
| pop dx ax | |
| out dx,al ; <--- ; {3C0h} select ATC register | |
| RILoutAH: xchg al,ah | |
| out dx,al ; <--- ; {3C0h} modify ATC register | |
| xchg al,ah | |
| ret | |
| RILgroupwrite endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F2 - Read register range | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CH (starting register #) | |
| ; CL (# of registers) | |
| ; DX (group index: 0,8,10h,18h) | |
| ; ES:BX (buffer, CL bytes size) | |
| ; Out: none | |
| ; Use: videoregs@ | |
| ; Modf: AX, CX, SI, DI | |
| ; Call: none | |
| ; | |
| RIL_F2 proc | |
| assume es:nothing | |
| mov di,bx | |
| mov si,dx | |
| mov si,videoregs@[si].regs@ | |
| mov al,ch | |
| ;mov ah,0 | |
| add si,ax | |
| RILmemcopy: ; -X- sti | |
| mov ch,0 | |
| shr cx,1 | |
| rep movsw | |
| adc cx,cx | |
| rep movsb | |
| ret | |
| RIL_F2 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F3 - Write register range | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CH (starting register #) | |
| ; CL (# of registers, >0) | |
| ; DX (group index: 0,8,10h,18h) | |
| ; ES:BX (buffer, CL bytes size) | |
| ; Out: none | |
| ; Use: videoregs@ | |
| ; Modf: AX, CX, DX, BX, DI | |
| ; Call: RILgroupwrite | |
| ; | |
| RIL_F3 proc | |
| assume es:nothing | |
| mov di,dx | |
| mov dx,videoregs@[di].port@ | |
| mov videoregs@[di].rmodify?,dl ; OPTIMIZE: DL instead 1 | |
| mov di,videoregs@[di].regs@ | |
| RILgrouploop: xor ax,ax | |
| xchg al,ch | |
| add di,ax | |
| ; countloop_ | |
| @@rilf3loop: | |
| mov ah,es:[bx] | |
| mov [di],ah | |
| inc bx | |
| inc di | |
| call RILgroupwrite | |
| inc ax ; OPTIMIZE: AX instead AL | |
| ; end_ | |
| loop @@rilf3loop | |
| ret | |
| RIL_F3 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F4 - Read register set | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (# of registers, >0) | |
| ; ES:BX (table of registers records) | |
| ; Out: none | |
| ; Use: videoregs@ | |
| ; Modf: AL, CX, BX, DI | |
| ; Call: none | |
| ; | |
| RIL_F4 proc | |
| assume es:nothing | |
| ; -X- sti | |
| mov di,bx | |
| ; countloop_ | |
| @@rilf4loop: | |
| mov bx,es:[di] | |
| movadd di,,2 | |
| mov bx,videoregs@[bx].regs@ | |
| mov al,es:[di] | |
| inc di | |
| xlat | |
| stosb | |
| ; end_ | |
| loop @@rilf4loop | |
| ret | |
| RIL_F4 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F5 - Write register set | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (# of registers, >0) | |
| ; ES:BX (table of registers records) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX, CX, DX, SI | |
| ; Call: RILwrite | |
| ; | |
| RIL_F5 proc | |
| assume es:nothing | |
| mov si,bx | |
| ; countloop_ | |
| @@rilf5loop: | |
| lods word ptr es:[si] | |
| xchg dx,ax ; OPTIMIZE: instead MOV DX,AX | |
| lods word ptr es:[si] | |
| call RILwrite | |
| ; end_ | |
| loop @@rilf5loop | |
| ret | |
| RIL_F5 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F7 - Define registers default | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: DX (group index) | |
| ; ES:BX (table of one-byte entries) | |
| ; Out: none | |
| ; Use: videoregs@ | |
| ; Modf: CL, SI, DI, ES, DS | |
| ; Call: RILmemcopy | |
| ; | |
| RIL_F7 proc | |
| assume es:nothing | |
| mov si,bx | |
| mov di,dx | |
| mov cl,videoregs@[di].regscnt | |
| mov videoregs@[di].rmodify?,cl ; OPTIMIZE: CL instead 1 | |
| mov di,videoregs@[di].def@ | |
| push es ds | |
| pop es ds | |
| j RILmemcopy | |
| RIL_F7 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; RIL F6 - Revert registers to default | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: videoregs@ | |
| ; Modf: AX, CX, DX, BX, SI, DI, ES | |
| ; Call: RILgrouploop | |
| ; | |
| RIL_F6 proc | |
| MOVSEG es,ds,,@TSRdata | |
| mov si,TSRdref:videoregs@+(size RGROUPDEF)*8 | |
| @@R6loop: sub si,size RGROUPDEF | |
| xor cx,cx | |
| xchg cl,[si].rmodify? | |
| jcxz @@R6next | |
| mov bx,[si].def@ | |
| mov di,[si].regs@ | |
| mov dx,[si].port@ | |
| mov cl,[si].regscnt | |
| ;mov ch,0 | |
| loop @@R6group | |
| mov al,[bx] | |
| stosb | |
| out dx,al ; <--- | |
| ;j @@R6next ; OPTIMIZE: single regs | |
| j @@R6loop ; handled first | |
| @@R6group: inc cx ; OPTIMIZE: CX instead CL | |
| ;mov ch,0 | |
| call RILgrouploop | |
| @@R6next: cmp si,TSRdref:videoregs@ | |
| ja @@R6loop | |
| ret | |
| RIL_F6 endp | |
| endif ; -X- USERIL | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ END OF INT 10 HANDLER ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Draw mouse cursor | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| drawcursor proc | |
| mov cx,[videoseg] | |
| jcxz @@drawret ; exit if nonstandard mode | |
| xor cx,cx | |
| cmp [nocursorcnt],cl ; OPTIMIZE: CL instead 0 | |
| jnz restorescreen ; jump if cursor disabled | |
| mov ax,[granumask.Y] | |
| xchg cl,[newcursor] ; remove redraw request | |
| ; CX=force cursor request | |
| inc ax | |
| mov bx,[granpos.Y] ; cursor position Y | |
| mov ax,[granpos.X] ; cursor position X | |
| jz graphcursor ; jump if graphics mode | |
| ;===== text mode cursor | |
| mov si,8 ; OPTIMIZE: instead -[granumask.Y] | |
| call checkifseen | |
| jc restorescreen ; jump if not in seen area | |
| call gettxtoffset | |
| cmp di,[cursor@] | |
| ; if_ eq ; exit if position not changed | |
| jnz @@drnz | |
| jcxz @@drawret ; and cursor not forced | |
| ; end_ | |
| @@drnz: | |
| push di | |
| call restorescreen | |
| ;MOVSEG es,[videoseg],,nothing | |
| pop di | |
| cmp [cursortype],ch ; OPTIMIZE: CH instead 0 | |
| ; if_ nz | |
| jz @@drz | |
| ;----- position hardware text mode cursor | |
| shr di,1 | |
| if USERIL ; -X- | |
| mov dx,videoregs@[0].port@ ; CRTC port | |
| else | |
| mov dx,[crtc] ; 3d4 or 3b4 | |
| endif ; -X- USERIL | |
| mov ax,di | |
| ; out_ dx,0Fh,al ; cursor position lo | |
| mov ah,al | |
| mov al,0fh | |
| out dx,ax | |
| xchg ax,di ; OPTIMIZE: instead MOV AX,DI | |
| ; out_ dx,0Eh,ah ; cursor position hi | |
| mov al,0eh | |
| out dx,ax | |
| ret | |
| ; end_ | |
| @@drz: | |
| ;----- draw software text mode cursor | |
| mov [cursor@],di | |
| mov ax,es:[di] ; save char under cursor | |
| mov textbuf[2],ax | |
| and ax,[startscan] | |
| xor ax,[endscan] | |
| stosw ; draw to new position | |
| mov textbuf[0],ax | |
| @@drawret: ret | |
| drawcursor endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Restore old screen contents | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| restorescreen proc | |
| les di,dword ptr [cursor@] | |
| assume es:nothing | |
| inc di | |
| ; if_ nz ; if cursor drawn | |
| jz @@rsz | |
| sub [cursor@],di ; OPTIMIZE: instead MOV -1 | |
| mov ax,[granumask.Y] | |
| dec di | |
| inc ax | |
| ; if_ zero | |
| jnz @@rsnz | |
| ;----- graphics mode | |
| call restoresprite | |
| jmp restorevregs | |
| ; end_ | |
| @@rsnz: | |
| ;----- text mode | |
| mov si,TSRdref:textbuf | |
| lodsw | |
| cmp ax,es:[di] | |
| ; if_ eq ; if screen not changed | |
| jnz @@rsnz2 | |
| movsw ; restore old text char/attrib | |
| ; end_ | |
| @@rsnz2: | |
| ; end_ | |
| @@rsz: | |
| @drawret:: ret | |
| restorescreen endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Draw graphics mode mouse cursor | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| graphcursor proc | |
| sub ax,[hotspot.X] ; virtual X | |
| sub bx,[hotspot.Y] ; virtual Y | |
| mov si,16 ; cursor height | |
| push ax | |
| call checkifseen | |
| pop ax | |
| jc restorescreen ; jump if not in seen area | |
| xchg ax,bx | |
| xor dx,dx | |
| neg ax | |
| ; if_ lt | |
| jge @@gcge | |
| neg ax | |
| xchg ax,dx | |
| ; end_ | |
| @@gcge: | |
| mov [spritetop],ax | |
| mov ax,[screenheight] | |
| cmp si,ax | |
| ; if_ ge | |
| jl @@gclt | |
| xchg si,ax ; OPTIMIZE: instead MOV SI,AX | |
| ; end_ | |
| @@gclt: | |
| sub si,dx ; =spriteheight | |
| push si ; =min(16-ax,screenheight-dx) | |
| call getgroffset | |
| pop dx | |
| ; cx=force request, bx=X, di=line offset, si=nextrow, dx=spriteheight | |
| add di,bx | |
| les ax,dword ptr [cursor@] | |
| assume es:nothing | |
| inc ax | |
| ; if_ nz ; if cursor drawn | |
| jz @@cpz | |
| ; CODE_ CMP_DI cursorpos,<dw ?> | |
| OPCODE_CMP_DI | |
| cursorpos dw ? | |
| ; if_ eq | |
| jnz @@cpnz2 | |
| cmp dx,[spriteheight] | |
| ; andif_ eq ; exit if position not changed | |
| jnz @@cpnz2 | |
| jcxz @drawret ; and cursor not forced | |
| ; end_ | |
| @@cpnz2: | |
| push bx | |
| push dx | |
| push di | |
| dec ax | |
| xchg di,ax ; OPTIMIZE: instead MOV DI,AX | |
| call restoresprite | |
| ;MOVSEG es,[videoseg],,nothing | |
| pop di | |
| pop dx | |
| ; else_ | |
| jmp short @@cpnz | |
| @@cpz: | |
| push bx | |
| call updatevregs | |
| ; end_ | |
| @@cpnz: | |
| pop bx | |
| ; bx=X, di=line offset+bx, si=nextrow, dx=spriteheight, es=videoseg | |
| mov [cursorpos],di | |
| mov [spriteheight],dx | |
| mov [nextrow],si | |
| sub di,bx | |
| push dx | |
| ;----- precompute sprite parameters | |
| push bx | |
| mov cl,[bitmapshift] | |
| mov dx,[cursorwidth] | |
| sar bx,cl ; left sprite offset (signed) | |
| mov ax,[scanline] | |
| add dx,bx ; right sprite offset | |
| cmp dx,ax | |
| ; if_ ae | |
| jb @@pspb | |
| xchg dx,ax ; DX=min(DX,scanline) | |
| ; end_ | |
| @@pspb: | |
| pop ax ; =cursorX | |
| sub cl,3 ; mode 0Dh=1, other=0 | |
| and ax,[granumask.X] ; fix for mode 4/5 | |
| sar ax,cl ; sprite shift for non 13h modes | |
| neg bx ; sprite shift for 13h mode | |
| ; if_ lt ; if left sprite offset>0 | |
| jge @@pspge | |
| add dx,bx | |
| sub di,bx | |
| mov bl,0 | |
| and al,7 ; shift in byte (X%8) | |
| ; end_ | |
| @@pspge: | |
| inc bx ; OPTIMIZE: BX instead BL | |
| sub al,8 ; if cursorX>0 | |
| mov bh,al ; ...then BH=-(8-X%8) | |
| push bx ; ...else BH=-(8-X)=-(8+|X|) | |
| ;----- save screen sprite and draw cursor at new cursor position | |
| mov [spritewidth],dx | |
| mov [cursor@],di | |
| mov al,0D6h ; screen source | |
| call copysprite ; save new sprite | |
| ; CODE_ MOV_BX spritetop,<dw ?> | |
| OPCODE_MOV_BX | |
| spritetop dw ? | |
| pop cx | |
| pop ax ; CL/CH=sprite shift | |
| ; AX=[spriteheight] | |
| ; SI=[nextrow] | |
| add bx,bx ; mask offset | |
| ; countloop_ ,ax | |
| @@spriteloop: | |
| push ax | |
| push cx | |
| push bx | |
| push si | |
| push di | |
| mov si,[spritewidth] | |
| mov dx,word ptr screenmask[bx] | |
| mov bx,word ptr cursormask[bx] | |
| call makerow | |
| pop di | |
| pop si | |
| pop bx | |
| pop cx | |
| pop ax | |
| add di,si | |
| xor si,[nextxor] ; for interlaced mode? | |
| movadd bx,,2 | |
| ; end_ | |
| dec ax | |
| jnz @@spriteloop | |
| ;----- | |
| ;j restorevregs | |
| graphcursor endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Restore graphics card video registers | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| restorevregs proc | |
| mov bx,TSRdref:vdata1 | |
| j @writevregs | |
| restorevregs endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Save & update graphics card video registers | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| updatevregs proc | |
| mov bx,TSRdref:vdata1 | |
| mov ah,0F4h ; read register set | |
| call @registerset | |
| mov bx,TSRdref:vdata2 | |
| @writevregs:: mov ah,0F5h ; write register set | |
| @registerset:: ; if planar videomode [0Dh-12h] then "push es" else "ret" | |
| db ? | |
| MOVSEG es,ds,,@TSRdata | |
| mov cx,[bx-2] | |
| int 10h | |
| pop es | |
| ret | |
| updatevregs endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| restoresprite proc | |
| call updatevregs | |
| mov al,0D7h ; screen destination | |
| ;j copysprite ; restore old sprite | |
| restoresprite endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Copy screen sprite back and forth | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: AL (0D6h/0D7h-screen source/dest.) | |
| ; ES:DI (pointer to video memory) | |
| ; Out: CX = 0 | |
| ; BX = 0 | |
| ; Use: buffer@ (small in DS for CGA, larger for MCGA, in a000 for EGA...) | |
| ; Modf: AX, DX | |
| ; Call: none | |
| ; | |
| copysprite proc C uses si di ds es ; TASM inserts PUSH here! | |
| assume es:nothing | |
| cmp al,0D6h | |
| pushf ; whether to swap pointers | |
| mov NEXTOFFSCODE[1],al | |
| ; CODE_ MOV_AX nextrow,<dw ?> ; ax = next row offset | |
| OPCODE_MOV_AX | |
| nextrow dw ? | |
| ; CODE_ MOV_BX spriteheight,<dw ?> ; bx = sprite height in lines | |
| OPCODE_MOV_BX | |
| spriteheight dw ? | |
| push ax | |
| mov al,0BEh ; 1 for CGA / MCGA: MOV SI | |
| cmp [bitmapshift],1 ; 1 for MCGA mode 13h | |
| jz @blitmode | |
| cmp byte ptr videoseg[1],0A0h | |
| jne @blitmode ; jump if CGA | |
| mov al,0E8h ; 0 for EGA / VGA: CALL | |
| @blitmode: mov BLITCODE[1],al | |
| cmp al,0E8h | |
| jnz @blitram ; if not EGA / VGA, skip GRC | |
| call backup3ce ; backup 3ce/f regs | |
| push dx | |
| mov dx,3ceh | |
| mov ax,word ptr SEQ5[1] ; mode reg, ax=nn05 | |
| and ah,0f4h ; read mode 0/1 plane/match... | |
| or ah,1 ; write mode 1: from latch :-) | |
| out dx,ax | |
| mov dx,3ceh | |
| mov ax,0003h ; operator: COPY all planes :-) | |
| out dx,ax | |
| pop dx | |
| @blitram: pop ax | |
| lds si,[buffer@] | |
| assume ds:nothing | |
| popf ; whether to swap pointers | |
| ; if_ eq | |
| jnz @@blitnz | |
| push ds | |
| push es | |
| pop ds | |
| pop es ; DS:SI=screen | |
| ; xchg si,di ; ES:DI=buffer | |
| xchg di,si ; JWASM and TASM use opposite encoding | |
| ; end_ | |
| @@blitnz: | |
| ; countloop_ ,bx | |
| @@spritewloop: | |
| ; CODE_ MOV_CX spritewidth,<dw ?> ; seen part of sprite in bytes | |
| OPCODE_MOV_CX | |
| spritewidth dw ? | |
| movsub dx,ax,cx ; mov dx,ax sub dx,cx | |
| ; instead of movsb inside a000:x, one could possibly do | |
| ; out 3ce,4 read/stosb out 3ce,104 read/stosb out 3ce,204 | |
| ; read/stosb out 3ce,304 movsb -> copy planewise on EGA/VGA | |
| ; ... but that would require a suitable target buffer! | |
| rep movsb ; -X- now for CGA EGA VGA MCGA | |
| NEXTOFFSCODE db 01h,0d6h ; ADD SI,DX/ADD DI,DX | |
| ; CODE_ XOR_AX nextxor,<dw ?> ; for interlace modes? | |
| OPCODE_XOR_AX | |
| nextxor dw ? | |
| ; end_ ; of outer countloop_ | |
| dec bx | |
| jnz @@spritewloop | |
| BLITCODE db 90h ; for the label ;-) | |
| call restore3ce ; CALL or nop-ish MOV SI | |
| ret ; TASM inserts the right POP here! | |
| copysprite endp | |
| assume ds:@TSRdata | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Transform the cursor mask row to screen | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: DX = screenmask[row] (which pixels will combine with screen color) | |
| ; BX = cursormask[row] (which pixels will be white/inverted, rather than black/transparent) | |
| ; SI = [spritewidth] | |
| ; CL (sprite shift when mode 13h) | |
| ; CH (sprite shift when non 13h modes) (??) | |
| ; ES:DI (video memory pointer) | |
| ; Out: none | |
| ; Use: bitmapshift (1 if mode 13h MCGA) | |
| ; Modf: AX, CX, DX, BX, SI, DI | |
| ; Call: none | |
| ; | |
| makerow proc | |
| assume es:nothing | |
| cmp [bitmapshift],1 ; =1 for 13h mode | |
| ; if_ eq | |
| jnz @@mrnz | |
| ;----- | |
| ; countloop_ ,si ; loop over x pixels | |
| @@pixloop: | |
| shl bx,cl ; if MSB=0 | |
| ; sbb al,al ; ...then AL=0 | |
| db 1ah, 0c0h ; JWASM and TASM use opposite encoding | |
| and al,0Fh ; ...else AL=0Fh (WHITE color) | |
| shl dx,cl | |
| ; if_ carry ; if most sign bit nonzero | |
| jnc @@mrnc | |
| xor al,es:[di] | |
| ; end_ | |
| @@mrnc: | |
| stosb | |
| mov cl,1 | |
| ; end_ countloop | |
| dec si | |
| jnz @@pixloop | |
| ret | |
| ; end_ if | |
| @@mrnz: | |
| ;----- display cursor row in modes other than 13h | |
| makerowno13: call backup3ce | |
| mov ax,0FFh | |
| ; loop_ ; shift masks left until ch++ is 0 | |
| @@m13zloop: | |
| add dx,dx | |
| adc al,al | |
| inc dx ; al:dh:dl shifted screenmask | |
| add bx,bx | |
| adc ah,ah ; ah:bh:bl shifted cursormask | |
| inc ch | |
| ; until_ zero | |
| jnz @@m13zloop | |
| ; xchg dh,bl ; al:bl:dl - ah:bh:dh | |
| xchg bl,dh ; JWASM and TASM use opposite encoding | |
| ; countloop_ ,si | |
| @@m13loop: | |
| push dx | |
| ; *** push bx ; must be omitted, but why? | |
| mov dx,es | |
| cmp dh,0A0h | |
| ; if_ ne ; if not planar mode 0Dh-12h | |
| jz @@m13z | |
| and al,es:[di] | |
| xor al,ah | |
| stosb | |
| ; else_ | |
| jmp short @@m13nz | |
| @@m13z: | |
| xchg cx,ax ; OPTIMIZE: instead MOV CX,AX | |
| if 1 ; OLD BUT WORKING | |
| ; out_ 3CEh,5,0 ; set write mode 0: "color: reg2 mask: reg8" | |
| mov dx,3ceh | |
| mov ax,5 | |
| out dx,ax | |
| ; out_ ,3,8h ; data ANDed with latched data | |
| mov ax,803h | |
| out dx,ax | |
| xchg es:[di],cl | |
| ; out_ ,3,18h ; data XORed with latched data | |
| mov ax,1803h | |
| out dx,ax | |
| xchg es:[di],ch | |
| else ; NEW BUT NO TRANSPARENCY | |
| mov dx,3ceh ; graphics controller | |
| mov ax,word ptr SEQ5[1] ; mode reg, ax=nn05 | |
| and ah,0f4h ; zap mode bits | |
| or ah,2 ; set write mode 2: "color: ram, mask: reg8" | |
| out dx,ax | |
| mov dx,3ceh ; graphics controller | |
| mov ax, 803h ; 8 pan 0, mode AND (TODO: preserve pan) | |
| out dx,ax ; set operation | |
| mov al,8 ; mask reg | |
| mov ah,cl ; AND mask | |
| out dx,ax ; set mask | |
| mov byte ptr es:[di],12 ; color | |
| mov ax,1803h ; 18 pan 0, mode XOR (TODO: preserve pan) | |
| out dx,ax ; set operation | |
| mov al,8 | |
| mov ah,ch ; XOR mask | |
| out dx,ax ; set mask | |
| mov byte ptr es:[di],15 ; color | |
| endif | |
| inc di | |
| ; end_ | |
| @@m13nz: | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| pop bx ; why was this push dx - pop bx? | |
| ; *** pop dx ; must be omitted, but why? | |
| ; end_ countloop | |
| dec si | |
| jnz @@m13loop | |
| restore3ce:: push dx | |
| push ax | |
| mov dx,3ceh ; graphics controller | |
| SEQ3 db 0b8h,3,0 ; mov ax,0003 | |
| out dx,ax | |
| SEQ4 db 0b8h,4,0 ; mov ax,0004 | |
| out dx,ax | |
| SEQ5 db 0b8h,5,0 ; mov ax,0005 | |
| out dx,ax | |
| SEQ8 db 0b8h,8,0 ; mov ax,0008 | |
| out dx,ax | |
| pop ax | |
| pop dx | |
| ret | |
| ;----- backup 4 EGA+ graphics controller registers, can only read VGA, not from EGA | |
| backup3ce:: push dx | |
| push ax | |
| mov dx,3ceh ; graphics controller | |
| mov al,3 ; operator / pan, pan is 3 LSB | |
| out dx,al | |
| inc dx | |
| in al,dx | |
| mov cs:SEQ3[2],al | |
| dec dx | |
| mov al,4 ; plane: 2 LSM, only for read | |
| out dx,al | |
| inc dx | |
| in al,dx | |
| mov cs:SEQ4[2],al | |
| dec dx | |
| mov al,5 ; mode: read, write, memmode/depth | |
| out dx,al | |
| inc dx | |
| in al,dx | |
| mov cs:SEQ5[2],al | |
| dec dx | |
| mov al,8 ; bit mask (...) | |
| out dx,al | |
| inc dx | |
| in al,dx | |
| mov cs:SEQ8[2],al | |
| pop ax | |
| pop dx | |
| ret | |
| makerow endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Return graphic mode video memory offset to line start | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: DX (Y coordinate in pixels) | |
| ; Out: DI (video memory offset) | |
| ; SI (offset to next row) | |
| ; Use: videoseg, scanline | |
| ; Modf: AX, DX, ES | |
| ; Call: @getoffsret | |
| ; Info: 4/5 (320x200x4) byte offset = (y/2)*80 + (y%2)*2000h + (x*2)/8 | |
| ; 6 (640x200x2) byte offset = (y/2)*80 + (y%2)*2000h + x/8 | |
| ; 0Dh (320x200x16) byte offset = y*40 + x/8, bit offset = 7 - (x % 8) | |
| ; 0Eh (640x200x16) byte offset = y*80 + x/8, bit offset = 7 - (x % 8) | |
| ; 0Fh (640x350x4) byte offset = y*80 + x/8, bit offset = 7 - (x % 8) | |
| ; 10h (640x350x16) byte offset = y*80 + x/8, bit offset = 7 - (x % 8) | |
| ; 11h (640x480x2) byte offset = y*80 + x/8, bit offset = 7 - (x % 8) | |
| ; 12h (640x480x16) byte offset = y*80 + x/8, bit offset = 7 - (x % 8) | |
| ; 13h (320x200x256) byte offset = y*320 + x | |
| ; HGC (720x348x2) byte offset = (y%4)*2000h + (y/4)*90 + x/8 | |
| ; bit offset = 7 - (x % 8) | |
| ; | |
| getgroffset proc | |
| xor di,di | |
| mov ax,[scanline] | |
| MOVSEG es,di,,BIOS | |
| mov si,ax ; [nextrow] | |
| cmp byte ptr videoseg[1],0A0h | |
| je @getoffsret ; jump if not videomode 4-6 | |
| mov si,2000h | |
| sar dx,1 ; DX=Y/2 | |
| jnc @getoffsret | |
| mov di,si ; DI=(Y%2)*2000h | |
| mov si,-(2000h-80) | |
| j @getoffsret | |
| getgroffset endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Return text mode video memory offset | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: AX/BX (cursor position X/Y) | |
| ; Out: DI (video memory offset=row*[0:44Ah]*2+column*2) | |
| ; Use: 0:44Ah, 0:44Eh, bitmapshift | |
| ; Modf: AX, DX, BX, ES | |
| ; Call: getpageoffset | |
| ; | |
| gettxtoffset proc | |
| MOVSEG es,0,dx,BIOS | |
| xchg di,ax ; OPTIMIZE: instead MOV DI,AX | |
| mov al,[bitmapshift] | |
| dec ax ; OPTIMIZE: AX instead AL | |
| xchg cx,ax | |
| sar di,cl ; DI=column*2 | |
| xchg cx,ax ; OPTIMIZE: instead MOV CX,AX | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| sar ax,2 ; AX=row*2=Y/4 | |
| mov dx,[VIDEO_width] ; screen width | |
| @getoffsret:: imul dx ; AX=row*screen width | |
| add ax,[VIDEO_pageoff] ; add video page offset | |
| add di,ax | |
| ret | |
| gettxtoffset endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Check if cursor seen and not in update region | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: AX/BX (cursor position X/Y) | |
| ; SI (cursor height) | |
| ; Out: Carry flag (cursor not seen or in update region) | |
| ; BX (cursor X aligned at byte in video memory) | |
| ; SI (cursor Y+height) | |
| ; Use: scanline, screenheight, upleft, lowright | |
| ; Modf: DX | |
| ; Call: none | |
| ; | |
| checkifseen proc C uses cx | |
| ;----- check if cursor shape seen on the screen | |
| add si,bx | |
| jle @@retunseen ; fail if Y+height<=0 | |
| cmp bx,[screenheight] | |
| jge @@retunseen ; fail if Y>maxY | |
| ; CODE_ MOV_CL bitmapshift,<db ?> ; mode 13h=1, 0Dh=4, other=3 | |
| OPCODE_MOV_CL | |
| bitmapshift db ? | |
| ; CODE_ MOV_DX cursorwidth,<dw ?> ; cursor width in bytes | |
| OPCODE_MOV_DX | |
| cursorwidth dw ? | |
| sar ax,cl | |
| add dx,ax | |
| jle @@retunseen ; fail if X+width<=0 | |
| cmp ax,[scanline] | |
| jge @@retunseen ; fail if X>maxX | |
| ;----- check if cursor shape not intersects with update region | |
| shl ax,cl | |
| cmp bx,[lowright.Y] | |
| jg @@retseen ; ok if Y below | |
| cmp si,[upleft.Y] | |
| jle @@retseen ; ok if Y+height above | |
| cmp ax,[lowright.X] | |
| jg @@retseen ; ok if X from the right | |
| shl dx,cl | |
| cmp dx,[upleft.X] | |
| jle @@retseen ; ok if X+width from the left | |
| @@retunseen: stc | |
| ret | |
| @@retseen: clc | |
| ret | |
| checkifseen endp | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ INT 33 HANDLER SERVICES ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| setupvideo proc | |
| mov si,szClearArea2/2 ; clear area 2 | |
| ; ERRIF (szClearArea2 mod 2 ne 0) "szClearArea2 must be even!" | |
| j @setvideo | |
| setupvideo endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 21 - Software reset | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [AX] = 21h/FFFFh (not installed/installed) | |
| ; [BX] = 2/3/FFFFh (number of buttons) | |
| ; Use: 0:449h, 0:44Ah, 0:463h, 0:484h, 0:487h, 0:488h, 0:4A8h | |
| ; Modf: RedefArea, screenheight, granumask, buffer@, videoseg, cursorwidth, | |
| ; scanline, nextxor, bitmapshift, @registerset, rangemax, ClearArea | |
| ; Call: hidecursor, @savecutpos | |
| ; | |
| softreset_21 proc | |
| mov [_ARG_BX_],3 | |
| buttonscnt equ byte ptr [$-2] ; buttons count (2/3) | |
| mov [_ARG_AX_],0FFFFh | |
| ; restore default area | |
| memcopy szDefArea,ds,@TSRdata,@TSRdata:RedefArea,,,@TSRdata:DefArea | |
| call hidecursor ; restore screen contents | |
| mov si,szClearArea3/2 ; clear area 3 | |
| ; ERRIF (szClearArea3 mod 2 ne 0) "szClearArea3 must be even!" | |
| ;----- setup video regs values for current video mode | |
| @setvideo:: push si | |
| MOVSEG es,ds,,@TSRdata ; push ds pop es, assume... | |
| MOVSEG ds,0,ax,BIOS ; xor ax,ax mov ds,ax | |
| mov ax,[CRTC_base] ; base IO address of CRTC | |
| if USERIL ; -X- | |
| mov videoregs@[0].port@,ax ; 3D4h/3B4h | |
| add ax,6 ; Feature Control register | |
| mov videoregs@[(size RGROUPDEF)*5].port@,ax | |
| else | |
| mov cs:crtc,ax | |
| endif ; -X- USERIL | |
| mov al,[VIDEO_mode] ; current video mode | |
| push ax | |
| ;----- | |
| ; block_ | |
| mov ah,9 | |
| cmp al,11h ; VGA videomodes? | |
| ; breakif_ ae | |
| jae @@blend | |
| cbw ; OPTIMIZE: instead MOV AH,0 | |
| cmp al,0Fh ; 0F-10 videomodes? | |
| ; if_ ae | |
| jb @@blb | |
| ; testflag [VIDEO_control],mask VCTRL_RAM_64K | |
| test [VIDEO_control],60h ; mask VCTRL_RAM_64K | |
| ; value ?nn????? where n+1 = 64kBy blocks of RAM installed | |
| ; breakif_ zero ; break if only 64K of VRAM | |
| jz @@blend | |
| mov ah,2 | |
| ; else_ | |
| jmp short @@blend | |
| @@blb: | |
| cmp al,4 ; not color text modes? | |
| ; andif_ below | |
| jnb @@blend | |
| xchg cx,ax ; OPTIMIZE: instead MOV CX,AX | |
| mov al,[VIDEO_switches] ; get display combination | |
| ; maskflag al,mask VIDSW_feature0+mask VIDSW_display | |
| and al,mask VIDSW_feature0+mask VIDSW_display | |
| cmp al,9 ; EGA+ECD/MDA? | |
| je @@lines350 | |
| cmp al,3 ; MDA/EGA+ECD? | |
| ; if_ eq | |
| jnz @@blnz | |
| @@lines350: mov ch,13h | |
| ; end_ | |
| @@blnz: | |
| xchg ax,cx ; OPTIMIZE: instead MOV AX,CX | |
| ; end_ if | |
| ; end_ block | |
| @@blend: | |
| ;----- | |
| if USERIL ; -X- | |
| lds si,[VIDEO_ptrtable@] ; 40:a8 | |
| assume ds:nothing | |
| lds si,[si].VIDEO_paramtbl@ ; first pointer there... | |
| add ah,al | |
| mov al,(offset VPARAM_SEQC) shl 2 | |
| shr ax,2 | |
| add si,ax ; SI += (AL+AH)*64+5 | |
| mov di,TSRdref:VRegsArea | |
| push di | |
| mov al,3 | |
| stosb ; def_SEQ[0]=3 | |
| memcopy 50 ; copy default registers value | |
| mov al,0 | |
| stosb ; def_ATC[20]=0; VGA only | |
| memcopy 9 ; def_GRC | |
| ;mov ah,0 | |
| stosw ; def_FC=0, def_GPOS1=0 | |
| inc ax ; OPTIMIZE: instead MOV AL,1 | |
| stosb ; def_GPOS2=1 | |
| pop si ; initialize area of defaults | |
| ;mov di,TSRdref:DefVRegsArea | |
| ; ERRIF (DefVRegsArea ne VRegsArea+64) "VRegs area contents corrupted!" | |
| memcopy szVRegsArea,,,,es,@TSRdata ; NOTE: changes es assume! | |
| dec ax ; OPTIMIZE: instead MOV AL,0 | |
| mov cx,8 | |
| mov di,TSRdref:videoregs@[0].rmodify? | |
| ; countloop_ | |
| @@setvloop: | |
| stosb | |
| add di,(size RGROUPDEF)-1 | |
| ; end_ | |
| loop @@setvloop | |
| else ; -X- | |
| ; *** MOVSEG es,ds,,@TSRdata ; -X- push ds pop es, assume... | |
| assume es:nothing ; -X- | |
| MOVSEG ds,cs,,@TSRcode ; -X- push ds pop es, assume... | |
| endif ; -X- USERIL | |
| ;----- set parameters for current video mode | |
| ; mode seg screen cell scan planar VX/ | |
| ; line byte | |
| ; 0 B800h 640x200 16x8 - - - | |
| ; 1 B800h 640x200 16x8 - - - | |
| ; 2 B800h 640x200 8x8 - - - | |
| ; 3 B800h 640x200 8x8 - - - | |
| ; 4 B800h 320x200 2x1 80 no 8 | |
| ; 5 B800h 320x200 2x1 80 no 8 | |
| ; 6 B800h 640x200 1x1 80 no 8 | |
| ; 7 B000h 640x200 8x8 - - - | |
| ; 0Dh A000h 320x200 2x1 40 yes 16 | |
| ; 0Eh A000h 640x200 1x1 80 yes 8 | |
| ; 0Fh A000h 640x350 1x1 80 yes 8 | |
| ; 10h A000h 640x350 1x1 80 yes 8 | |
| ; 11h A000h 640x480 1x1 80 yes 8 | |
| ; 12h A000h 640x480 1x1 80 yes 8 | |
| ; 13h A000h 320x200 2x1 320 no 2 | |
| ; other 0 640x200 1x1 - - - | |
| ; | |
| pop ax ; current video mode | |
| ; mode 0-3 | |
| mov dx,0B8FFh ; B800h: [0-3] | |
| mov cx,0304h ; 16x8: [0-1] | |
| mov di,200 ; x200: [4-6,0Dh-0Eh,13h] | |
| cmp al,2 | |
| ; if_ ae | |
| jb @@stb | |
| dec cx ; 8x8: [2-3,7] | |
| cmp al,4 | |
| ; andif_ ae | |
| jb @@stb | |
| ; mode 7 | |
| cmp al,7 | |
| jne @@checkgraph | |
| mov dh,0B0h ; B000h: [7] | |
| ; end_ | |
| @@stb: | |
| @@settext: mov ch,1 | |
| mov bh,0F8h | |
| shl dl,cl | |
| MOVSEG es,0,ax,BIOS ; xor ax,ax mov es,ax assume | |
| add al,[VIDEO_lastrow] ; screen height-1 | |
| ; if_ nz ; zero on old machines | |
| jz @@stz | |
| inc ax ; OPTIMIZE: AX instead AL | |
| if USE_286 | |
| shl ax,3 | |
| else | |
| mov ah,8 | |
| mul ah | |
| endif | |
| xchg di,ax ; OPTIMIZE: instead MOV DI,AX | |
| ; end_ | |
| @@stz: | |
| mov ax,[VIDEO_width] ; screen width | |
| j @@setcommon | |
| ; mode 4-6 | |
| @@checkgraph: mov ah,0C3h ; RET opcode for [4-6,13h] | |
| ;mov cx,0303h ; sprite: 3 bytes/row | |
| ;mov dx,0B8FFh ; B800h: [4-6]/1x1: [6,0Eh-12h] | |
| ;mov di,200 ; x200: [4-6,0Dh-0Eh,13h] | |
| mov si,2000h xor -(2000h-80) ; [nextxor] for [4-6] | |
| ;MOVSEG es,ds,,@TSRdata | |
| mov bx,TSRdref:spritebuf | |
| cmp al,6 | |
| je @@setgraphics | |
| jb @@set2x1 | |
| ; in modes 0Dh-13h screen contents under cursor sprite will be | |
| ; saved at free space in video memory (A000h segment) | |
| mov dh,0A0h ; A000h: [0Dh-13h] | |
| MOVSEG es,0A000h,bx,nothing | |
| xor si,si ; [nextxor] for [0Dh-13h] | |
| cmp al,13h | |
| ja @@nonstandard | |
| je @@mode13 | |
| ; mode 8-0Dh | |
| cmp al,0Dh | |
| jb @@nonstandard | |
| mov ah,06h ; PUSH ES opcode for [0Dh-12h] | |
| mov bx,3E82h ; 16002: [0Dh-0Eh] | |
| je @@set320 | |
| ; mode 0Eh-12h | |
| cmp al,0Fh | |
| jb @@setgraphics | |
| mov di,350 ; x350: [0Fh-10h] | |
| mov bh,7Eh ; 32386: [0Fh-10h] | |
| cmp al,11h | |
| jb @@setgraphics | |
| mov di,480 ; x480: [11h-12h] | |
| mov bh,9Eh ; 40578: [11h-12h] | |
| j @@setgraphics | |
| ; mode 13h | |
| @@mode13: ;mov bl,0 | |
| mov bh,0FAh ; =320*200 | |
| mov cx,1000h ; sprite: 16 bytes/row | |
| @@set320: inc cx ; OPTIMIZE: instead INC CL | |
| @@set2x1: dec dx ; OPTIMIZE: instead MOV DL,-2 | |
| @@setgraphics: nop ; -X- | |
| saveFAR [buffer@],es,bx | |
| mov [nextxor],si | |
| mov byte ptr [@registerset],ah | |
| j @@setgcommon | |
| @@nonstandard: ;mov cl,3 | |
| ;mov dl,0FFh | |
| ;mov di,200 | |
| ;;+++++ for text modes: dh := 0B8h, j @@settext | |
| mov dh,0 ; no video segment | |
| @@setgcommon: mov ax,640 ; virtual screen width | |
| mov bh,0FFh ; Y granularity | |
| shr ax,cl | |
| @@setcommon: mov [screenheight],di | |
| mov [scanline],ax ; screen line width in bytes | |
| mov [bitmapshift],cl ; log2(screen/memory ratio) | |
| ; (mode 13h=1, 0-1/0Dh=4, other=3) | |
| mov byte ptr [cursorwidth],ch ; cursor width in bytes | |
| mov byte ptr [granumask.X],dl | |
| mov byte ptr [granumask.Y],bh | |
| mov byte ptr videoseg[1],dh | |
| shl ax,cl | |
| pop si | |
| ;----- set ranges and center cursor (AX=screenwidth, DI=screenheight) | |
| mov cx,ax | |
| dec ax | |
| mov [rangemax.X],ax ; set right X range | |
| shr cx,1 ; X middle | |
| mov dx,di | |
| dec di | |
| mov [rangemax.Y],di ; set lower Y range | |
| shr dx,1 ; Y middle | |
| ;----- set cursor position (CX=X, DX=Y, SI=area size to clear) | |
| @setpos:: nop ;cli ; -X- | |
| MOVSEG es,ds,,@TSRdata | |
| mov di,TSRdref:ClearArea | |
| ; xchg cx,si | |
| xchg si,cx ; JWASM and TASM use opposite encoding | |
| xor ax,ax | |
| rep stosw | |
| xchg ax,dx ; OPTIMIZE: instead MOV AX,DX | |
| ; MOVREG_ bx,<offset Y> | |
| mov bx,offset POINT.Y | |
| call @savecutpos | |
| xchg ax,si ; OPTIMIZE: instead MOV AX,SI | |
| ; MOVREG_ bl,<offset X> ; OPTIMIZE: BL instead BX | |
| mov bl,offset POINT.X | |
| jmp @savecutpos | |
| softreset_21 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 1F - Disable mouse driver and unhook int 10 and IRQ | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [AX] = 1Fh/FFFFh (success/unsuccess) | |
| ; [ES:BX] (old int33 handler) | |
| ; Use: oldint33, oldint10 | |
| ; Modf: AX, CX, DX, BX, DS, ES, disabled?, nocursorcnt | |
| ; Call: INT 21/35, INT 21/25, disablePS2/disableUART, hidecursor | |
| ; -X- TODO: call int 15/C201 (reset resolution and rate, disable) | |
| ; -X- TODO: check if enabledriver_20 still works after int 15/C201 | |
| ; | |
| disabledrv_1F proc | |
| les ax,[oldint33] | |
| assume es:nothing | |
| mov [_ARG_ES_],es | |
| mov [_ARG_BX_],ax | |
| ; this can be patched from disablePS2 to disableUART: | |
| call_ disableproc,disablePS2 ; can change ES! | |
| mov al,[disabled?] | |
| test al,al | |
| ; if_ zero ; if driver not disabled | |
| jnz @@ddrvnz | |
| mov [buttstatus],al | |
| inc ax ; OPTIMIZE: instead MOV AL,1 | |
| mov [nocursorcnt],al ; normalize hide counter | |
| call hidecursor ; restore screen contents | |
| ;----- check if INT 33 or INT 10 were intercepted | |
| ; (i.e. handlers segment not equal to CS) | |
| mov cx,cs | |
| DOSGetIntr 33h | |
| mov dx,es | |
| cmp dx,cx | |
| jne althandler_18 | |
| ; DOSGetIntr 10h | |
| ; mov ah,35h | |
| mov al,10h | |
| int 21h | |
| movsub ax,es,cx | |
| jne althandler_18 | |
| inc ax ; OPTIMIZE: instead MOV AL,1 | |
| mov [disabled?],al | |
| lds dx,[oldint10] | |
| assume ds:nothing | |
| DOSSetIntr 10h ; restore old INT 10 handler | |
| ; end_ if | |
| @@ddrvnz: | |
| ret | |
| disabledrv_1F endp | |
| assume ds:@TSRdata | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 18 - Set alternate User Interrupt Routine | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (call mask) | |
| ; ES:DX (FAR routine) | |
| ; Out: [AX] = 18h/FFFFh (success/unsuccess) | |
| ; | |
| althandler_18 proc | |
| assume es:nothing | |
| mov [_ARG_AX_],0FFFFh | |
| ret | |
| althandler_18 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 19 - Get alternate User Interrupt Routine | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (call mask) | |
| ; Out: [CX] (0=not found) | |
| ; [BX:DX] (FAR routine) | |
| ; | |
| althandler_19 proc | |
| mov [_ARG_CX_],0 | |
| ret | |
| althandler_19 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 00 - Reset driver and read status | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [AX] = 0/FFFFh (not installed/installed) | |
| ; [BX] = 2/3/FFFFh (number of buttons) | |
| ; Use: none | |
| ; Modf: none | |
| ; Call: softreset_21, enabledriver_20 | |
| ; | |
| resetdriver_00 proc | |
| call softreset_21 | |
| ;j enabledriver_20 | |
| resetdriver_00 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 20 - Enable mouse driver and hook int 10 and IRQ | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [AX] = 20h/FFFFh (success/unsuccess) | |
| ; Use: none | |
| ; Modf: AX, CX, DX, BX, ES, disabled?, oldint10 | |
| ; Call: INT 21/35, INT 21/25, setupvideo, enablePS2/enableUART | |
| ; | |
| enabledriver_20 proc | |
| xor cx,cx | |
| xchg cl,[disabled?] | |
| ; if_ ncxz | |
| jcxz @@edcxz | |
| ;----- set new INT 10 handler | |
| DOSGetIntr 10h | |
| saveFAR [oldint10],es,bx | |
| ;mov al,10h | |
| push ds ; -X- | |
| push cs ; -X- | |
| pop ds ; -X- | |
| ; DOSSetIntr ,,,@TSRcode:int10handler | |
| mov dx,@TSRcode:int10handler | |
| mov ah,25h | |
| int 21h | |
| pop ds ; -X- | |
| ; end_ | |
| @@edcxz: | |
| ;----- | |
| call setupvideo | |
| ; this can be patched from enablePS2 to enableUART: | |
| jmp_ enableproc,enablePS2 ; can change ES! | |
| enabledriver_20 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 03 - Get cursor position, buttons status and wheel counter | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [BL] (buttons status) | |
| ; [BH] (wheel movement counter) | |
| ; [CX] (X - column) | |
| ; [DX] (Y - row) | |
| ; Use: buttstatus, granpos | |
| ; Modf: AX, CX, DX, wheel.counter | |
| ; Call: @retBCDX | |
| ; | |
| status_03 proc | |
| xor ax,ax | |
| xchg ax,[wheel.counter] | |
| mov ah,al | |
| mov al,[buttstatus] | |
| mov cx,[granpos.X] | |
| mov dx,[granpos.Y] | |
| j @retBCDX | |
| status_03 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 05 - Get button press data | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: BX (button number; -1 for wheel) | |
| ; Out: [AL] (buttons status) | |
| ; [AH] (wheel movement counter) | |
| ; [BX] (press times or wheel counter, if BX was -1) | |
| ; [CX] (last press X) | |
| ; [DX] (last press Y) | |
| ; Use: none | |
| ; Modf: CX, buttpress, wheel | |
| ; Call: @retbuttstat | |
| ; | |
| pressdata_05 proc | |
| mov cx,TSRdref:buttpress-(size BUTTLASTSTATE) | |
| j @retbuttstat | |
| pressdata_05 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 06 - Get button release data | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: BX (button number; -1 for wheel) | |
| ; Out: [AL] (buttons status) | |
| ; [AH] (wheel movement counter) | |
| ; [BX] (release times or wheel counter, if BX was -1) | |
| ; [CX] (last release X) | |
| ; [DX] (last release Y) | |
| ; Use: buttstatus | |
| ; Modf: AX, CX, DX, BX, SI, buttrelease, wheel | |
| ; Call: none | |
| ; | |
| releasedata_06 proc | |
| mov cx,TSRdref:buttrelease-(size BUTTLASTSTATE) | |
| @retbuttstat:: mov ah,byte ptr [wheel.counter] | |
| mov al,[buttstatus] | |
| mov [_ARG_AX_],ax | |
| xor ax,ax | |
| inc bx | |
| mov si,TSRdref:wheel | |
| jz @@retlastpos ; jump if BX was -1 | |
| mov si,cx | |
| xor cx,cx | |
| xor dx,dx | |
| cmp bx,2+1 | |
| ; if_ be | |
| ja @@rlpa | |
| ; ERRIF (6 ne size BUTTLASTSTATE) "BUTTLASTSTATE structure size changed!" | |
| add bx,bx | |
| add si,bx ; SI+BX=buttrelease | |
| add bx,bx ; +button*size BUTTLASTSTATE | |
| @@retlastpos: xchg [si + bx + offset BUTTLASTSTATE.counter],ax | |
| mov cx,[si+bx + offset BUTTLASTSTATE.lastcol] | |
| mov dx,[si+bx + offset BUTTLASTSTATE.lastrow] | |
| ; end_ if | |
| @@rlpa: | |
| @retBCDX:: mov [_ARG_DX_],dx | |
| @retBCX:: mov [_ARG_CX_],cx | |
| @retBX:: mov [_ARG_BX_],ax | |
| ret | |
| releasedata_06 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 0B - Get motion counters | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [CX] (number of mickeys mouse moved | |
| ; [DX] horizontally/vertically since last call) | |
| ; Use: none | |
| ; Modf: mickeys | |
| ; Call: @retBCDX | |
| ; | |
| mickeys_0B proc | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| xor cx,cx | |
| xor dx,dx | |
| xchg [mickeys.X],cx | |
| xchg [mickeys.Y],dx | |
| j @retBCDX | |
| mickeys_0B endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 11 - Check wheel support and get capabilities flags | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [AX] = 574Dh ('WM') | |
| ; [CX] (capabilities flag, bits 1..15 reserved) | |
| ; [BX] (capabilities flag, all bits reserved) | |
| ; Use: none | |
| ; Modf: AX | |
| ; Call: @retBCX | |
| ; | |
| wheelAPI_11 proc | |
| mov [_ARG_AX_],574Dh | |
| ; CODE_ MOV_CX wheelflags,<db 0,0> | |
| OPCODE_MOV_CX | |
| wheelflags db 0,0 | |
| xor ax,ax | |
| j @retBCX | |
| wheelAPI_11 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 15 - Get driver storage requirements | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [BX] (buffer size) | |
| ; Use: szSaveArea | |
| ; Modf: AX | |
| ; Call: @retBX | |
| ; | |
| storagereq_15 proc | |
| mov ax,szSaveArea | |
| j @retBX | |
| storagereq_15 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 1B - Get mouse sensitivity | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [BX] (horizontal sensitivity, 1..100) | |
| ; [CX] (vertical sensitivity, 1..100) | |
| ; [DX] (speed threshold in mickeys/second) | |
| ; Use: sensval, /doublespeed/ | |
| ; Modf: AX, CX, DX | |
| ; Call: @retBCDX | |
| ; | |
| sensitivity_1B proc | |
| mov ax,[sensval.X] | |
| mov cx,[sensval.Y] | |
| inc ax | |
| inc cx | |
| xor dx,dx | |
| ;;* mov dx,[doublespeed] | |
| j @retBCDX | |
| sensitivity_1B endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 1E - Get display page | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: [BX] (display page number) | |
| ; Use: 0:462h | |
| ; Modf: AX, DS | |
| ; Call: @retBX | |
| ; | |
| videopage_1E proc | |
| MOVSEG ds,0,ax,BIOS | |
| mov al,[VIDEO_pageno] | |
| j @retBX | |
| videopage_1E endp | |
| assume ds:@TSRdata | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 01 - Show mouse cursor | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX, lowright.Y | |
| ; Call: cursorstatus | |
| ; | |
| showcursor_01 proc | |
| neg ax ; AL=AH=-1 | |
| mov byte ptr lowright.Y[1],al ; place update region | |
| j cursorstatus ; outside seen screen area | |
| showcursor_01 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 02 - Hide mouse cursor | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX | |
| ; Call: cursorstatus | |
| ; | |
| hidecursor_02 proc | |
| dec ax ; AL=1,AH=0 | |
| ;j cursorstatus | |
| hidecursor_02 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Hint: request to cursor redraw (instead refresh) is useful in cases when | |
| ; interrupt handlers try to hide, then show cursor while cursor | |
| ; drawing is in progress | |
| ; | |
| cursorstatus proc | |
| add al,[nocursorcnt] | |
| sub ah,al ; exit if "already enabled" | |
| jz @showret ; or "counter overflow" | |
| mov [nocursorcnt],al | |
| inc ah ; jump if cursor changed | |
| jz redrawcursor ; between enabled/disabled | |
| ret | |
| cursorstatus endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 07 - Set horizontal cursor range | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (min X) | |
| ; DX (max X) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: BX | |
| ; Call: @setnewrange | |
| ; | |
| hrange_07 proc | |
| ; MOVREG_ bx,<offset X> | |
| xor bx,bx ; MOVREG optimizes mov bx,offset POINT.X ... | |
| j @setnewrange | |
| hrange_07 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 08 - Set vertical cursor range | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (min Y) | |
| ; DX (max Y) | |
| ; Out: none | |
| ; Use: pos | |
| ; Modf: CX, DX, BX, rangemin, rangemax | |
| ; Call: setpos_04 | |
| ; | |
| vrange_08 proc | |
| ; MOVREG_ bx,<offset Y> | |
| mov bx,offset POINT.Y | |
| if FOOLPROOF | |
| @setnewrange:: xchg ax,cx ; OPTIMIZE: instead MOV AX,CX | |
| cmp ax,dx | |
| ; if_ ge | |
| jl @@snrl | |
| xchg ax,dx | |
| ; end_ | |
| @@snrl: | |
| mov word ptr rangemin[bx],ax | |
| else | |
| @setnewrange:: mov word ptr rangemin[bx],cx | |
| endif | |
| mov word ptr rangemax[bx],dx | |
| mov cx,[pos.X] | |
| mov dx,[pos.Y] | |
| ;j setpos_04 | |
| vrange_08 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 04 - Position mouse cursor | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (X - column) | |
| ; DX (Y - row) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: SI | |
| ; Call: @setpos, refreshcursor | |
| ; | |
| setpos_04 proc | |
| mov si,szClearArea1/2 ; clear area 1 | |
| ; ERRIF (szClearArea1 mod 2 ne 0) "szClearArea1 must be even!" | |
| call @setpos | |
| ;j refreshcursor | |
| setpos_04 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| refreshcursor proc | |
| sub [videolock],1 | |
| jc @showret ; was 0: drawing in progress | |
| js @@refreshdone ; was -1: queue already used | |
| sti | |
| ; loop_ | |
| @@rcloop: | |
| call drawcursor | |
| @@refreshdone: inc [videolock] ; drawing stopped | |
| ; until_ nz ; loop until queue empty | |
| jz @@rcloop | |
| cli | |
| @showret:: ret | |
| refreshcursor endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 09 - Define graphics cursor | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: BX (hot spot X) | |
| ; CX (hot spot Y) | |
| ; ES:DX (pointer to bitmaps) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX, CX, BX, SI, DI, ES, hotspot, screenmask, cursormask | |
| ; Call: @showret, redrawcursor | |
| ; | |
| graphcursor_09 proc | |
| assume es:nothing | |
| ;----- compare user shape with internal area | |
| mov si,TSRdref:hotspot | |
| lodsw | |
| cmp ax,bx | |
| ; if_ eq | |
| jnz @@gc9nz | |
| lodsw | |
| xor ax,cx | |
| ; andif_ eq | |
| jnz @@gc9nz | |
| mov di,dx | |
| ;mov ah,0 | |
| mov al,16+16 | |
| xchg ax,cx | |
| repe cmpsw | |
| je @showret ; exit if cursor not changed | |
| xchg cx,ax ; OPTIMIZE: instead MOV CX,AX | |
| ; end_ | |
| @@gc9nz: | |
| ;----- copy user shape to internal area | |
| push ds | |
| push ds | |
| push es | |
| pop ds | |
| pop es | |
| mov di,TSRdref:hotspot | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| stosw | |
| xchg ax,cx ; OPTIMIZE: instead MOV AX,CX | |
| stosw | |
| ; memcopy 2*(16+16),,,,,,dx | |
| mov si,dx | |
| mov cx, 16+16 | |
| rep movsw | |
| pop ds | |
| ;j redrawcursor | |
| graphcursor_09 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| redrawcursor proc | |
| hidecursor:: mov [newcursor],1 ; force cursor redraw | |
| j refreshcursor | |
| redrawcursor endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 0A - Define text cursor | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: BX (0 - SW, else HW text cursor) | |
| ; CX (screen mask/start scanline) | |
| ; DX (cursor mask/end scanline) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX, CX, BX, cursortype, startscan, endscan | |
| ; Call: INT 10/01, @showret, redrawcursor | |
| ; | |
| textcursor_0A proc | |
| ; xchg cx,bx | |
| xchg bx,cx ; TASM and JWASM use opposite encodings | |
| ; if_ ncxz ; if hardware cursor | |
| jcxz @@tcacxz | |
| mov ch,bl | |
| mov cl,dl | |
| mov ah,1 | |
| int 10h ; set cursor shape & size | |
| mov cl,1 | |
| ; end_ | |
| @@tcacxz: | |
| cmp cl,[cursortype] | |
| ; if_ eq | |
| jnz @@tcanz | |
| cmp bx,[startscan] | |
| ; andif_ eq | |
| jnz @@tcanz | |
| cmp dx,[endscan] | |
| je @showret ; exit if cursor not changed | |
| ; end_ | |
| @@tcanz: | |
| ;----- | |
| mov [cursortype],cl | |
| mov [startscan],bx | |
| mov [endscan],dx | |
| j redrawcursor | |
| textcursor_0A endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 10 - Define screen region for updating | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX, DX (X/Y of upper left corner) | |
| ; SI, DI (X/Y of lower right corner) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX, CX, DX, DI, upleft, lowright | |
| ; Call: redrawcursor | |
| ; | |
| updateregion_10 proc | |
| mov ax,[_ARG_SI_] | |
| if FOOLPROOF | |
| cmp cx,ax | |
| ; if_ ge | |
| jl @@ur10l | |
| xchg cx,ax | |
| ; end_ | |
| @@ur10l: | |
| mov [upleft.X],cx | |
| mov [lowright.X],ax | |
| xchg ax,di ; OPTIMIZE: instead MOV AX,DI | |
| cmp dx,ax | |
| ; if_ ge | |
| jl @@ur10l2 | |
| xchg dx,ax | |
| ; end_ | |
| @@ur10l2: | |
| mov [upleft.Y],dx | |
| mov [lowright.Y],ax | |
| else | |
| mov [upleft.X],cx | |
| mov [upleft.Y],dx | |
| mov [lowright.X],ax | |
| mov [lowright.Y],di | |
| endif | |
| j redrawcursor | |
| updateregion_10 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 16 - Save driver state | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: BX (buffer size) | |
| ; ES:DX (buffer) | |
| ; Out: none | |
| ; Use: SaveArea | |
| ; Modf: CX, SI, DI | |
| ; Call: none | |
| ; | |
| savestate_16 proc | |
| assume es:nothing | |
| if FOOLPROOF | |
| ;;- cmp bx,szSaveArea ;!!! TurboPascal IDE | |
| ;;- jb @stateret ; workaround: garbage in BX | |
| endif | |
| ; memcopy szSaveArea,,,dx,,,@TSRdata:SaveArea | |
| mov di,dx | |
| mov si,@TSRdata:SaveArea | |
| mov cx,szSaveArea/2 ; happens to be even | |
| rep movsw | |
| @stateret: ret | |
| savestate_16 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 17 - Restore driver state | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: BX (buffer size) | |
| ; ES:DX (saved state buffer) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: SI, DI, DS, ES, SaveArea | |
| ; Call: @stateret, redrawcursor | |
| ; | |
| restorestate_17 proc | |
| assume es:nothing | |
| if FOOLPROOF | |
| ;;- cmp bx,szSaveArea ;!!! TurboPascal IDE | |
| ;;- jb @stateret ; workaround: garbage in BX | |
| endif | |
| ;----- do nothing if SaveArea is not changed | |
| ;;* mov si,TSRdref:SaveArea | |
| ;;* mov di,dx | |
| ;;* mov cx,szSaveArea/2 | |
| ;;*ERRIF (szSaveArea mod 2 ne 0) "szSaveArea must be even!" | |
| ;;* repe cmpsw | |
| ;;* je @stateret | |
| ;----- change SaveArea | |
| push es | |
| push dx | |
| MOVSEG es,ds,,@TSRdata | |
| pop si | |
| pop ds | |
| assume ds:nothing | |
| memcopy szSaveArea,,,@TSRdata:SaveArea | |
| MOVSEG ds,es,,@TSRdata | |
| j redrawcursor | |
| restorestate_17 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 0D - Light pen emulation ON | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: none | |
| ; Call: lightpenoff_0E | |
| ; | |
| ;;*lightpenon_0D proc | |
| ;;* mov al,0 | |
| ;;* ;j lightpenoff_0E | |
| ;;*lightpenon_0D endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 0E - Light pen emulation OFF | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: nolightpen? | |
| ; Call: none | |
| ; | |
| ;;*lightpenoff_0E proc | |
| ;;* mov [nolightpen?],al ; OPTIMIZE: AL instead nonzero | |
| ;;* ret | |
| ;;*lightpenoff_0E endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 14 - Exchange User Interrupt Routines | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (new call mask) | |
| ; ES:DX (new FAR routine) | |
| ; Out: [CX] (old call mask) | |
| ; [ES:DX] (old FAR routine) | |
| ; Use: callmask, UIR@ | |
| ; Modf: AX | |
| ; Call: UIR_0C | |
| ; | |
| exchangeUIR_14 proc | |
| assume es:nothing | |
| ;mov ah,0 | |
| mov al,[callmask] | |
| mov [_ARG_CX_],ax | |
| mov ax,word ptr UIR@[0] | |
| mov [_ARG_DX_],ax | |
| mov ax,word ptr UIR@[2] | |
| mov [_ARG_ES_],ax | |
| ;j UIR_0C | |
| exchangeUIR_14 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 0C - Define User Interrupt Routine | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (call mask) | |
| ; ES:DX (FAR routine) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: UIR@, callmask | |
| ; Call: none | |
| ; | |
| UIR_0C proc | |
| assume es:nothing | |
| saveFAR [UIR@],es,dx | |
| mov [callmask],cl | |
| ret | |
| UIR_0C endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 0F - Set mickeys/pixels ratios | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: CX (number of mickeys per 8 pix | |
| ; DX horizontally/vertically) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: mickey8 | |
| ; Call: none | |
| ; | |
| sensitivity_0F proc | |
| if FOOLPROOF | |
| test dx,dx | |
| ; if_ nz ; ignore wrong ratio | |
| jz @@sensfp | |
| ; andif_ ncxz ; ignore wrong ratio | |
| jcxz @@sensfp | |
| endif | |
| mov [mickey8.X],cx | |
| mov [mickey8.Y],dx | |
| if FOOLPROOF | |
| ; end_ | |
| @@sensfp: | |
| endif | |
| ret | |
| sensitivity_0F endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 1A - Set mouse sensitivity | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: BX (horizontal sensitivity, 1..100) | |
| ; CX (vertical sensitivity, 1..100) | |
| ; DX (speed threshold in mickeys/second, ignored) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AX, CX, BX | |
| ; Call: senscalc | |
| ; | |
| sensitivity_1A proc | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| ; MOVREG_ bx,<offset X> | |
| xor bx,bx ; MOVREG optimizes mov bx,offset POINT.X | |
| call senscalc | |
| xchg ax,cx ; OPTIMIZE: instead MOV AX,CX | |
| ; MOVREG_ bl,<offset Y> ; OPTIMIZE: BL instead BX | |
| mov bl,offset POINT.Y | |
| ;j senscalc | |
| sensitivity_1A endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: AX (001A value) | |
| ; BX (offset X/offset Y) | |
| ; Out: none | |
| ; Modf: AX, DX, DI, sensval, senscoeff | |
| ; Call: none | |
| ; Hint: sensval=AX-1, senscoeff=[(sensval^2/3600+1/3)*256] | |
| ; | |
| senscalc proc | |
| dec ax | |
| ; cmp ax,100 ; ignore original values | |
| db 3dh, 100, 0 ; "cmp ax, word 100" | |
| ; JWASM encodes this in the "byte 100" syntax, same size | |
| ; if_ below ; outside [1..100] | |
| jnc @@scnc | |
| mov word ptr sensval[bx],ax | |
| mul ax ; DX:AX=V^2 (0<=X^2<10000) | |
| add ax,3600/3 | |
| ;adc dx,0 ; DX:AX=V^2+1200 | |
| ;mov dh,0 | |
| ;xchg dh,dl | |
| ; xchg dl,al | |
| xchg al,dl ; JWASM and TASM use opposite encoding | |
| ; xchg dl,ah ; DX:AX=(V^2+1200)*256 | |
| xchg ah,dl ; JWASM and TASM use opposite encoding | |
| mov di,3600 | |
| div di ; AX=(V^2+1200)*256/3600 | |
| mov word ptr senscoeff[bx],ax | |
| ; end_ | |
| @@scnc: | |
| ret | |
| senscalc endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 13 - Define double-speed threshold | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: DX (speed threshold in mickeys/second) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: /DX/, /doublespeed/ | |
| ; Call: none | |
| ; | |
| doublespeed_13 proc | |
| ;;* test dx,dx | |
| ;;* if_ zero | |
| ;;* mov dl,64 | |
| ;;* end_ | |
| ;;* mov [doublespeed],dx | |
| ;ret | |
| doublespeed_13 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 0D 0E 11 12 18 19 1C 1D - Null function for not implemented calls | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| nullfunc proc | |
| ret | |
| nullfunc endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; INT 33 handler | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| even | |
| handler33table dw TSRcref:resetdriver_00 | |
| dw TSRcref:showcursor_01 | |
| dw TSRcref:hidecursor_02 | |
| dw TSRcref:status_03 | |
| dw TSRcref:setpos_04 | |
| dw TSRcref:pressdata_05 | |
| dw TSRcref:releasedata_06 | |
| dw TSRcref:hrange_07 | |
| dw TSRcref:vrange_08 | |
| dw TSRcref:graphcursor_09 | |
| dw TSRcref:textcursor_0A | |
| dw TSRcref:mickeys_0B | |
| dw TSRcref:UIR_0C | |
| dw TSRcref:nullfunc ;lightpenon_0D | |
| dw TSRcref:nullfunc ;lightpenoff_0E | |
| dw TSRcref:sensitivity_0F | |
| dw TSRcref:updateregion_10 | |
| dw TSRcref:wheelAPI_11 | |
| dw TSRcref:nullfunc ;12 - large graphics cursor | |
| dw TSRcref:doublespeed_13 | |
| dw TSRcref:exchangeUIR_14 | |
| dw TSRcref:storagereq_15 | |
| dw TSRcref:savestate_16 | |
| dw TSRcref:restorestate_17 | |
| dw TSRcref:althandler_18 | |
| dw TSRcref:althandler_19 | |
| dw TSRcref:sensitivity_1A | |
| dw TSRcref:sensitivity_1B | |
| dw TSRcref:nullfunc ;1C - InPort mouse only | |
| dw TSRcref:nullfunc ;1D - define display page # | |
| dw TSRcref:videopage_1E | |
| dw TSRcref:disabledrv_1F | |
| dw TSRcref:enabledriver_20 | |
| dw TSRcref:softreset_21 | |
| handler33 proc | |
| assume ds:nothing,es:nothing | |
| cld | |
| test ah,ah | |
| ; if_ zero | |
| jnz @@h33nz | |
| push ds | |
| MOVSEG ds,cs,,@TSRdata | |
| cmp al,21h | |
| ja language_23 | |
| push es | |
| PUSHALL | |
| mov si,ax ;!!! AX must be unchanged | |
| mov bp,sp | |
| add si,si | |
| call handler33table[si] ; call by calculated offset | |
| rethandler:: POPALL | |
| pop es | |
| pop ds | |
| ; end_ | |
| @@h33nz: | |
| iret | |
| assume ds:@TSRdata | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 23 - Get language for messages | |
| ; Out: [BX] (language code: 0 - English) | |
| ; | |
| language_23: cmp al,23h | |
| je @iretBX0 | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 24 - Get software version, mouse type and IRQ | |
| ; Out: [AX] = 24h/FFFFh (installed/error) | |
| ; [BX] (version) | |
| ; [CL] (IRQ #/0=PS/2) | |
| ; [CH] = 1=bus/2=serial/3=InPort/4=PS2/5=HP (mouse type) | |
| ; Use: driverversion | |
| ; | |
| version_24: cmp al,24h | |
| ; if_ eq | |
| jnz @@v24nz | |
| mov bx,driverversion | |
| ; CODE_ MOV_CX mouseinfo,<db ?,4> | |
| OPCODE_MOV_CX | |
| mouseinfo db ?,4 | |
| ; end_ | |
| @@v24nz: | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 26 - Get maximum virtual screen coordinates | |
| ; Out: [BX] (mouse disabled flag) | |
| ; [CX] (max virtual screen X) | |
| ; [DX] (max virtual screen Y) | |
| ; Use: bitmapshift | |
| ; | |
| maxscreen_26: cmp al,26h | |
| ; if_ eq | |
| jnz @@m26nz | |
| mov cl,[bitmapshift] | |
| ; CODE_ MOV_BX scanline,<dw ?> | |
| OPCODE_MOV_BX | |
| scanline dw ? | |
| ; CODE_ MOV_DX screenheight,<dw ?> | |
| OPCODE_MOV_DX | |
| screenheight dw ? | |
| shl bx,cl | |
| dec dx | |
| mov cx,bx | |
| dec cx | |
| ; CODE_ MOV_BX disabled?,<db 1,0> ; 1=driver disabled | |
| OPCODE_MOV_BX | |
| disabled? db 1,0 | |
| ; end_ | |
| @@m26nz: | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 27 - Get screen/cursor masks and mickey counters | |
| ; Out: [AX] (screen mask/start scanline) | |
| ; [BX] (cursor mask/end scanline) | |
| ; [CX] (number of mickeys mouse moved | |
| ; [DX] horizontally/vertically since last call) | |
| ; Use: startscan, endscan | |
| ; Modf: mickeys | |
| ; | |
| cursor_27: cmp al,27h | |
| ; if_ eq | |
| jnz @@c27nz | |
| mov ax,[startscan] | |
| mov bx,[endscan] | |
| xor cx,cx | |
| xor dx,dx | |
| xchg cx,[mickeys.X] | |
| xchg dx,[mickeys.Y] | |
| pop ds | |
| iret | |
| ; end_ | |
| @@c27nz: | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 31 - Get current virtual cursor coordinates | |
| ; Out: [AX] (min virtual cursor X) | |
| ; [BX] (min virtual cursor Y) | |
| ; [CX] (max virtual cursor X) | |
| ; [DX] (max virtual cursor Y) | |
| ; Use: rangemin, rangemax | |
| ; | |
| cursrange_31: cmp al,31h | |
| ; if_ eq | |
| jnz @@c31nz | |
| mov ax,[rangemin.X] | |
| mov bx,[rangemin.Y] | |
| lds cx,[rangemax] | |
| mov dx,ds | |
| pop ds | |
| iret | |
| ; end_ | |
| @@c31nz: | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 32 - Get supported advanced functions flag | |
| ; Out: [AX] (bits 15-0=function 25h-34h supported) | |
| ; [CX] = 0 | |
| ; [DX] = 0 | |
| ; [BX] = 0 | |
| ; | |
| active_32: cmp al,32h | |
| ; if_ eq | |
| jnz @@a32nz | |
| if USE28 | |
| mov ax,0111010000001100b ; active: 26 27 28 2A 31 32 | |
| else | |
| mov ax,0110010000001100b ; active: 26 27 2A 31 32 | |
| endif | |
| xor cx,cx | |
| xor dx,dx | |
| @iretBX0: xor bx,bx | |
| pop ds | |
| iret | |
| ; end_ | |
| @@a32nz: | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 4D - Get pointer to copyright string | |
| ; Out: [ES:DI] (copyright string) | |
| ; Use: IDstring | |
| ; | |
| copyright_4D: cmp al,4Dh | |
| ; if_ eq | |
| jnz @@c4dnz | |
| MOVSEG es,cs,,@TSRcode | |
| mov di,TSRcref:IDstring | |
| ; end_ | |
| @@c4dnz: | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 6D - Get pointer to version | |
| ; Out: [ES:DI] (version string) | |
| ; Use: msversion | |
| ; | |
| version_6D: cmp al,6Dh | |
| ; if_ eq | |
| jnz @@v6dnz | |
| MOVSEG es,cs,,@TSRcode | |
| mov di,TSRcref:msversion | |
| ; end_ | |
| @@v6dnz: | |
| if USE28 | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 28 - Set video mode | |
| ; In: CX (video mode) | |
| ; DX (font size, ignored) | |
| ; Out: [CX] (=0 if successful) | |
| ; Modf: none | |
| ; Call: none | |
| ; | |
| setvidmode_28: cmp al,28h | |
| ; if_ eq | |
| jnz @@v28nz | |
| push ax bx bp ;!!! some BIOSes trash BP | |
| test ch,ch ; VESA mode >= 100h | |
| ; if_ zero | |
| jnz @@v28nz2 | |
| mov ax,cx | |
| ;mov ah,0 | |
| int 10h ; set the video mode in AL | |
| mov ah,0Fh | |
| int 10h ; get current video mode | |
| cmp al,cl ; CL=requested video mode | |
| je @@setmoderet0 ; return if successful | |
| ; end_ | |
| @@v28nz2: | |
| mov bx,cx | |
| mov ax,4F02h | |
| int 10h ; set VESA video mode in BX | |
| cmp ax,004Fh ; CX=requested video mode | |
| jne @@setmoderet | |
| @@setmoderet0: xor cx,cx ; CX=0 if successful | |
| @@setmoderet: pop bp bx ax ; CX=requested mode or 0 | |
| ; end_ | |
| @@v28nz: | |
| endif | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; 2A - Get cursor hot spot | |
| ; Out: [AX] (cursor visibility counter) | |
| ; [BX] (hot spot X) | |
| ; [CX] (hot spot Y) | |
| ; [DX] = 1=bus/2=serial/3=InPort/4=PS2/5=HP (mouse type) | |
| ; Use: nocursorcnt, hotspot | |
| ; | |
| hotspot_2A: cmp al,2Ah | |
| ; if_ eq | |
| jnz @@h2anz | |
| ;mov ah,0 | |
| mov al,[nocursorcnt] | |
| lds bx,[hotspot] | |
| mov cx,ds | |
| ; CODE_ MOV_DX mouseinfo1,<db 4,0> | |
| OPCODE_MOV_DX | |
| mouseinfo1 db 4,0 | |
| ; end_ | |
| @@h2anz: | |
| pop ds | |
| iret | |
| handler33 endp | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ END OF INT 33 SERVICES ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| RILversion label byte | |
| msversion db driverversion / 100h,driverversion mod 100h | |
| IDstring db 'CuteMouse ',CTMVER,0 | |
| szIDstring = $ - IDstring | |
| TSRend label byte | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ INITIALIZATION PART DATA ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| .const | |
| ; messages segment virtual ; place at the end of current bsegment | |
| include ctmouse.msg | |
| ; messages ends | |
| S_mousetype dw dataref:S_atPS2 | |
| dw dataref:S_inMSYS | |
| dw dataref:S_inLT | |
| dw dataref:S_inMS | |
| .data | |
| options dw 0 | |
| OPT_PS2 equ 1b | |
| OPT_serial equ 10b | |
| OPT_COMforced equ 100b | |
| OPT_PS2after equ 1000b | |
| OPT_3button equ 10000b | |
| OPT_MSYS equ 100000b | |
| OPT_lefthand equ 1000000b | |
| OPT_noUMB equ 10000000b | |
| OPT_newTSR equ 100000000b | |
| OPT_Wheel equ 1000000000b | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ REAL START ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| .code | |
| say macro stroff ; :vararg | |
| ; MOVOFF_ di,<stroff> | |
| mov di,offset stroff | |
| call sayASCIIZ | |
| endm | |
| real_start: cld | |
| DOSGetIntr 33h | |
| saveFAR [oldint33],es,bx ; save old INT 33h handler | |
| ;----- parse command line and find mouse | |
| say @data:Copyright ; 'Cute Mouse Driver' | |
| mov si,offset PSP:cmdline_len | |
| lodsb | |
| cbw ; OPTIMIZE: instead MOV AH,0 | |
| mov bx,ax | |
| mov [si+bx],ah ; OPTIMIZE: AH instead 0 | |
| call commandline ; examine command line | |
| mov al,1Fh ; disable old driver | |
| call mousedrv | |
| ;----- | |
| mov ax,[options] | |
| ; testflag ax,OPT_PS2+OPT_serial | |
| test al, OPT_PS2+OPT_serial ; value is 3, TASM optimizes | |
| ; if_ zero ; if no /S and /P then | |
| jnz @@sonz | |
| ; setflag ax,OPT_PS2+OPT_serial ; both PS2 and serial assumed | |
| or al, OPT_PS2+OPT_serial ; value is 3, TASM optimizes | |
| ; end_ | |
| @@sonz: | |
| ;--- | |
| ; testflag ax,OPT_PS2after | |
| test al, OPT_PS2after ; 8, TASM optimizes this | |
| ; if_ nz | |
| jz @@paz | |
| call searchCOM ; call if /V | |
| jnc @@serialfound | |
| ; end_ | |
| @@paz: | |
| ;--- | |
| ; testflag ax,OPT_PS2+OPT_PS2after | |
| test al, OPT_PS2+OPT_PS2after ; 9, TASM optimizes this | |
| ; if_ nz | |
| jz @@p2z | |
| push ax | |
| call checkPS2 ; call if /V or PS2 | |
| pop ax | |
| ; andif_ nc | |
| jc @@p2z | |
| mov mouseinfo[0],bh | |
| j @@mousefound | |
| ; end_ | |
| @@p2z: | |
| ;--- | |
| ; testflag ax,OPT_PS2after | |
| test al, OPT_PS2after ; 8, TASM optimizes this | |
| ; if_ zero | |
| jnz @@panz | |
| ; testflag ax,OPT_serial+OPT_MSYS ; 2008: better than +nomsys? | |
| test al, OPT_serial+OPT_MSYS ; 22h, TASM optimizes this | |
| ; andif_ nz | |
| jz @@panz | |
| call searchCOM ; call if no /V and serial | |
| jnc @@serialfound | |
| ; end_ | |
| @@panz: | |
| mov di,dataref:E_notfound ; 'Error: device not found' | |
| jmp EXITENABLE | |
| ;----- | |
| @@serialfound: ;push ax ; preserve OPT_newTSR value | |
| mov al,2 | |
| mov mouseinfo[1],al | |
| mov [mouseinfo1],al | |
| ;pop ax | |
| @@mousefound: mov [mousetype],bl | |
| ;----- check if CuteMouse driver already installed | |
| ; testflag ax,OPT_newTSR | |
| test ah, OPT_newTSR shr 8 ; ax,100h, TASM optimizes | |
| jnz @@newTSR | |
| call getCuteMouse | |
| mov di,dataref:S_reset ; 'Resident part reset to' | |
| mov cx,4C02h ; terminate, al=return code | |
| ; if_ ne | |
| jz @@mfz | |
| ;----- allocate UMB memory, if possible, and set INT 33 handler | |
| @@newTSR: mov bx,(TSRend-TSRstart+15)/16 | |
| push bx | |
| call prepareTSR ; new memory segment in ES | |
| memcopy <size oldint33>,es,,@TSRdata:oldint33,ds,,@TSRdata:oldint33 | |
| push ds | |
| MOVSEG ds,es,,@TSRcode | |
| mov [disabled?],1 ; copied back in setupdriver | |
| DOSSetIntr 33h,,,@TSRcode:handler33 | |
| POPSEG ds,@data | |
| pop ax | |
| mov di,dataref:S_installed ; 'Installed at' | |
| mov cl,0 ; errorlevel | |
| ; end_ if | |
| @@mfz: | |
| ;----- | |
| push ax ; size of TSR for INT 21/31 | |
| ; say di | |
| call sayASCIIZ | |
| mov al,[mousetype] | |
| mov bx,dataref:S_CRLF | |
| add al,al | |
| ; if_ carry ; if wheel (=8xh) | |
| jnc @@mfnc | |
| mov bx,dataref:S_wheel | |
| ; end_ | |
| @@mfnc: | |
| cbw ; OPTIMIZE: instead MOV AH,0 | |
| cmp al,1 shl 1 | |
| xchg si,ax ; OPTIMIZE: instead MOV SI,AX | |
| ; if_ ae ; if not PS/2 mode (=0) | |
| jb @@mfb | |
| ; if_ eq ; if Mouse Systems (=1) | |
| jnz @@mfnz | |
| inc cx ; OPTIMIZE: CX instead CL | |
| ; end_ | |
| @@mfnz: | |
| say @data:S_atCOM | |
| ; end_ | |
| @@mfb: | |
| push cx ; exit function and errorlevel | |
| say S_mousetype[si] | |
| ; say bx | |
| mov di,bx | |
| call sayASCIIZ | |
| call setupdriver | |
| ;----- close all handles (20 pieces) to prevent decreasing system | |
| ; pool of handles if INT 21/31 used | |
| mov bx,19 | |
| ; loop_ | |
| @@mfns: | |
| ; DOSCloseFile | |
| mov ah,3eh | |
| int 21h | |
| dec bx | |
| ; until_ sign | |
| jns @@mfns | |
| ;----- | |
| pop ax ; AH=31h (TSR) or 4Ch (EXIT) | |
| pop dx | |
| int 21h | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Setup resident driver code and parameters | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| setupdriver proc | |
| ;----- detect VGA card (VGA ATC have one more register) | |
| mov ax,1A00h | |
| int 10h ; get display type in BX | |
| cmp al,1Ah | |
| ; if USERIL ; -X- | |
| ; if_ eq | |
| jnz @@sdnz | |
| xchg ax,bx ; OPTIMIZE: instead MOV AL,BL | |
| sub al,7 | |
| cmp al,8-7 | |
| ; andif_ be ; if monochrome or color VGA | |
| ja @@sdnz | |
| if USERIL | |
| inc videoregs@[(size RGROUPDEF)*3].regscnt | |
| endif | |
| ; end_ | |
| @@sdnz: | |
| ; else | |
| if 1 ; -X- | |
| ; *** SAY error if AL not 1ah: need VGA as we have no RIL *** | |
| jz @havevga | |
| say E_needvga | |
| @havevga: | |
| endif ; -X- | |
| ; endif ; -X- USERIL | |
| ;----- setup left hand mode handling | |
| ; CODE_ MOV_CX mousetype,<db ?,0> ; 0=PS/2,1=MSys,2=LT,3=MS, | |
| OPCODE_MOV_CX | |
| mousetype db ?,0 | |
| ; 80h=PS/2+wheel,83h=MS+wheel | |
| test cl,7Fh | |
| mov al,00000000b ; =0 | |
| ; if_ nz ; if not PS/2 mode (=x0h) | |
| jz @@mtz | |
| mov al,00000011b ; =3 | |
| ; end_ | |
| @@mtz: | |
| ; testflag [options],OPT_lefthand | |
| test byte ptr [options], OPT_lefthand ; 40h, TASM optimizes | |
| ; if_ nz | |
| jz @@mtz2 | |
| xor al,00000011b ; =3 | |
| ; end_ | |
| @@mtz2: | |
| mov [swapmask],al | |
| ;----- setup buttons count, mask and wheel flags | |
| mov al,3 | |
| ; testflag [options],OPT_3button | |
| test byte ptr [options], OPT_3button ; 10h, TASM optimizes | |
| ; if_ zero | |
| jnz @@mtnz | |
| jcxz @@setbuttons ; jump if PS/2 mode (=0) | |
| cmp cl,al ; OPTIMIZE: AL instead 3 | |
| ; andif_ eq ; if MS mode (=3) | |
| jnz @@mtnz | |
| @@setbuttons: mov [buttonsmask],al ; OPTIMIZE: AL instead 0011b | |
| dec ax | |
| mov [buttonscnt],al ; OPTIMIZE: AL instead 2 | |
| ; end_ | |
| @@mtnz: | |
| cmp cl,80h ; if some wheel protocol | |
| ; if_ ae | |
| jb @@mtb | |
| inc wheelflags[0] ; report "wheel present" | |
| mov [wheelmask],00001111b ; =0Fh | |
| ; end_ | |
| @@mtb: | |
| ;----- setup mouse handlers code | |
| ; block_ | |
| test cl,7Fh | |
| ; breakif_ zero ; break if PS/2 mode (=x0h) | |
| jz @@mtblock | |
| ; -X- fixcode IRQproc,0B0h,%OCW2<OCW2_EOI> ; MOV AL,OCW2<OCW2_EOI> | |
| fixnear enableproc,enableUART | |
| fixnear disableproc,disableUART | |
| dec cx | |
| ; breakif_ zero ; break if Mouse Systems mode (=1) | |
| jz @@mtblock | |
| fixnear mouseproc,MSLTproc | |
| dec cx | |
| ; breakif_ zero ; break if Logitech mode (=2) | |
| jz @@mtblock | |
| fixcode MSLTCODE3,,2 | |
| loop @@setother ; break if wheel mode (=83h) | |
| cmp al,2 ; OPTIMIZE: AL instead [buttonscnt] | |
| ; if_ ne ; if not MS2 | |
| jz @@mtbz | |
| fixcode MSLTCODE2,075h ; JNZ | |
| ; end_ | |
| @@mtbz: | |
| mov al,0C3h ; RET | |
| fixcode MSLTCODE1,al | |
| fixcode MSLTCODE3,al | |
| ; end_ block | |
| @@mtblock: | |
| ;----- setup, if required, other parameters | |
| @@setother: push es | |
| push ds | |
| push es | |
| push ds | |
| pop es | |
| pop ds ; get back [oldint10]... | |
| memcopy <size oldint10>,es,,@TSRdata:oldint10,ds,,@TSRdata:oldint10 | |
| mov al,[disabled?] | |
| pop ds | |
| mov [disabled?],al ; ...and [disabled?] | |
| DOSGetIntr [IRQintnum] ; -X- can be 0, none | |
| mov ax,es | |
| pop es | |
| mov di,TSRdref:oldIRQaddr | |
| xchg ax,bx | |
| stosw ; save old IRQ handler | |
| xchg ax,bx ; OPTIMIZE: instead MOV AX,BX | |
| stosw | |
| ;----- copy TSR image (even if ES=DS - this is admissible) | |
| memcopy ((TSRend-TSRdata+1)/2)*2,es,,@TSRdata:TSRdata,ds,,@TSRdata:TSRdata | |
| ;----- call INT 33/0000 (Reset driver) | |
| pop ax | |
| pushf ;!!! Logitech MouseWare | |
| push cs | |
| push ax ; Windows driver workaround | |
| mov ax,TSRcref:handler33 | |
| push es | |
| push ax | |
| xor ax,ax ; reset driver | |
| nop ; -X- | |
| retf ; jump to relocated INT33 | |
| setupdriver endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Check given or all COM-ports for mouse connection | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| searchCOM proc | |
| ;mov [LCRset],LCR<0,,LCR_noparity,0,2> | |
| mov di,coderef:detectmouse | |
| call COMloop | |
| jnc @searchret | |
| ; testflag [options],OPT_MSYS | |
| test byte ptr [options], OPT_MSYS ; 20h, TASM optimizes | |
| stc | |
| jz @searchret | |
| ; mov [LCRset],LCR<0,,LCR_noparity,0,3> | |
| mov [LCRset],3 | |
| mov bl,1 ; =Mouse Systems mode | |
| mov di,coderef:checkUART | |
| ;j COMloop | |
| searchCOM endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| COMloop proc | |
| push ax | |
| xor ax,ax ; scan only current COM port | |
| ; testflag [options],OPT_COMforced | |
| test byte ptr [options], OPT_COMforced ; 4, TASM optimizes | |
| jnz @@checkCOM | |
| mov ah,3 ; scan all COM ports | |
| ; loop_ | |
| @@ccns: | |
| inc ax ; OPTIMIZE: AX instead AL | |
| push ax | |
| call setCOMport | |
| pop ax | |
| @@checkCOM: push ax | |
| mov si,[IO_address] | |
| call di | |
| pop ax | |
| jnc @@searchbreak | |
| dec ah | |
| ; until_ sign | |
| jns @@ccns | |
| ;stc ; preserved from prev call | |
| @@searchbreak: pop ax | |
| @searchret:: ret | |
| COMloop endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Check if UART available | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: SI = [IO_address] | |
| ; Out: Carry flag (no UART detected) | |
| ; Use: none | |
| ; Modf: AX, DX | |
| ; Call: none | |
| ; | |
| checkUART proc | |
| test si,si | |
| jz @@noUART ; no UART if base=0 | |
| ;----- check UART registers for reserved bits | |
| movidx dx,MCR_index,si ; {3FCh} MCR (modem ctrl reg) | |
| in ax,dx ; {3FDh} LSR (line status reg) | |
| ; testflag al,mask MCR_reserved+mask MCR_AFE | |
| test al, mask MCR_reserved+mask MCR_AFE | |
| jnz @@noUART | |
| movidx dx,LSR_index,si,MCR_index | |
| in al,dx ; {3FDh} LSR (line status reg) | |
| inc ax | |
| jz @@noUART ; no UART if AX was 0FFFFh | |
| ;----- check LCR function | |
| cli | |
| movidx dx,LCR_index,si,LSR_index ; "dec dx dec dx" | |
| in al,dx ; {3FBh} LCR (line ctrl reg) | |
| push ax | |
| ; out_ dx,%LCR<1,0,-1,-1,3> ; {3FBh} LCR: DLAB on, 8S2 | |
| ; mov al,%LCR<1,0,-1,-1,3> | |
| mov al,10111111b | |
| out dx,al | |
| inb ah,dx | |
| ; out_ dx,%LCR<0,0,0,0,2> ; {3FBh} LCR: DLAB off, 7N1 | |
| ; mov al,%LCR<0,0,0,0,2> | |
| mov al,00000010b | |
| out dx,al | |
| in al,dx | |
| sti | |
| ; sub ax,(LCR<1,0,-1,-1,3> shl 8)+LCR<0,0,0,0,2> | |
| sub ax, (10111111b shl 8) + 00000010b | |
| ; if_ zero ; zero if LCR conforms | |
| jnz @@lcrnz | |
| ;----- check IER for reserved bits | |
| movidx dx,IER_index,si,LCR_index | |
| in al,dx ; {3F9h} IER (int enable reg) | |
| movidx dx,LCR_index,si,IER_index | |
| ;mov ah,0 | |
| and al,mask IER_reserved ; reserved bits should be clear | |
| ; end_ if | |
| @@lcrnz: | |
| neg ax ; nonzero makes carry flag | |
| pop ax | |
| out dx,al ; {3FBh} LCR: restore contents | |
| ret | |
| @@noUART: stc | |
| ret | |
| checkUART endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Detect mouse type if present | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: SI = [IO_address] | |
| ; Out: Carry flag (no UART or mouse found) | |
| ; BX (mouse type: 2=Logitech,3=MS,83h=MS+wheel) | |
| ; Use: 0:46Ch, LCRset | |
| ; Modf: AX, CX, DX, ES | |
| ; Call: checkUART | |
| ; | |
| detectmouse proc | |
| call checkUART | |
| jnc @@detmokay | |
| jmp @@detmret | |
| @@detmokay: | |
| ;----- save current LCR/MCR | |
| movidx dx,LCR_index,si ; {3FBh} LCR (line ctrl reg) | |
| in ax,dx ; {3FCh} MCR (modem ctrl reg) | |
| push ax ; keep old LCR and MCR values | |
| ;----- reset UART: drop RTS line, interrupts and disable FIFO | |
| ;movidx dx,LCR_index,si ; {3FBh} LCR: DLAB off | |
| ; out_ dx,%LCR<>,%MCR<> ; {3FCh} MCR: DTR/RTS/OUT2 off | |
| ; mov al,0 ; %LCR<> | |
| ; mov ah,0 ; %MCR<> | |
| xor ax,ax ; the out_ macro optimizes this | |
| out dx,ax | |
| movidx dx,IER_index,si,LCR_index | |
| ;mov ax,(FCR<> shl 8)+IER<> ; {3F9h} IER: interrupts off | |
| out dx,ax ; {3FAh} FCR: disable FIFO | |
| ;----- set communication parameters and flush receive buffer | |
| movidx dx,LCR_index,si,IER_index | |
| ; out_ dx,%LCR{LCR_DLAB=1} ; {3FBh} LCR: DLAB on | |
| ; mov al,%LCR{LCR_DLAB=1} | |
| mov al,80h | |
| out dx,al | |
| ; xchg dx,si | |
| xchg si,dx ; TASM and JWASM use opposite encodings | |
| ;mov ah,0 ; 1200 baud rate | |
| ; out_ dx,96,ah ; {3F8h},{3F9h} divisor latch | |
| mov al,96 | |
| out dx,ax | |
| ; xchg dx,si | |
| xchg si,dx ; TASM and JWASM use opposite encodings | |
| ; out_ dx,[LCRset] ; {3FBh} LCR: DLAB off, 7/8N1 | |
| mov al,[LCRset] | |
| out dx,al | |
| movidx dx,RBR_index,si,LCR_index | |
| in al,dx ; {3F8h} flush receive buffer | |
| ;----- wait current+next timer tick and then raise RTS line | |
| MOVSEG es,0,ax,BIOS | |
| ; loop_ | |
| @@tmrnz: | |
| mov ah,byte ptr [BIOS_timer] | |
| ; loop_ | |
| @@tmrz: | |
| cmp ah,byte ptr [BIOS_timer] | |
| ; until_ ne ; loop until next timer tick | |
| jz @@tmrz | |
| xor al,1 | |
| ; until_ zero ; loop until end of 2nd tick | |
| jnz @@tmrnz | |
| movidx dx,MCR_index,si,RBR_index | |
| ; out_ dx,%MCR<,,,0,,1,1> ; {3FCh} MCR: DTR/RTS on, OUT2 off | |
| ; mov al,%MCR<,,,0,,1,1> | |
| mov al,00000011b | |
| out dx,al | |
| ;----- detect if Microsoft or Logitech mouse present | |
| mov bx,0103h ; bl=mouse type, bh=no `M' | |
| ; countloop_ 4,cl ; scan 4 first bytes | |
| mov cl,4 | |
| @@clloop: | |
| ; countloop_ 2+1,ch ; length of silence in ticks | |
| mov ch,2+1 | |
| @@chloop: | |
| ; (include rest of curr tick) | |
| mov ah,byte ptr [BIOS_timer] | |
| ; loop_ | |
| @@zloop: | |
| movidx dx,LSR_index,si | |
| in al,dx ; {3FDh} LSR (line status reg) | |
| ; testflag al,mask LSR_RBF | |
| test al, mask LSR_RBF | |
| jnz @@parse ; jump if data ready | |
| cmp ah,byte ptr [BIOS_timer] | |
| ; until_ ne ; loop until next timer tick | |
| jz @@zloop | |
| ; end_ countloop ; loop until end of 2nd tick | |
| dec ch | |
| jnz @@chloop | |
| ; break_ ; break if no more data | |
| jmp short @@clloopend | |
| @@parse: movidx dx,RBR_index,si | |
| in al,dx ; {3F8h} receive byte | |
| cmp al,'('-20h | |
| ; breakif_ eq ; break if PnP data starts | |
| jz @@clloopend | |
| cmp al,'M' ; PnP: microsoft? | |
| ; if_ eq | |
| jnz @@prsnz | |
| mov bh,0 ; MS compatible mouse found... | |
| ; end_ | |
| @@prsnz: | |
| cmp al,'Z' ; PnP: wheel? | |
| ; if_ eq | |
| jnz @@prsnz2 | |
| ; * Only for PS2, wheel detection is a risk, so never disable COM wheel check | |
| ; * testflag [options],OPT_Wheel | |
| ; * if_ nz | |
| mov bl,83h ; ...MS mouse+wheel found | |
| ; * end_ ; else leave bx = 103 (from above) = MS without wheel | |
| ; end_ | |
| @@prsnz2: | |
| cmp al,'3' ; PnP: logitech? | |
| ; if_ eq | |
| jnz @@prsnz3 | |
| mov bl,2 ; ...Logitech mouse found | |
| ; end_ | |
| @@prsnz3: | |
| ; end_ countloop | |
| dec cl | |
| jnz @@clloop | |
| @@clloopend: | |
| movidx dx,LCR_index,si | |
| pop ax ; {3FBh} LCR: restore contents | |
| out dx,ax ; {3FCh} MCR: restore contents | |
| shr bh,1 ; 1 makes carry flag | |
| @@detmret: ret | |
| detectmouse endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Check for PS/2 | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: Carry flag (no PS/2 device found) | |
| ; BL (mouse type: 0=PS/2) | |
| ; BH (interrupt #/0=PS/2) | |
| ; Use: none | |
| ; Modf: AX, CX, BX | |
| ; -X- did the old version change ES? | |
| ; Call: INT 11, INT 15/C2xx, setRate | |
| ; -X- replaced outKBD, flushKBD by int 15/C2xx calls (KoKo/Eric) | |
| ; After reset with C201: "disabled, 100 Hz, 4 c/mm, 1:1", protocol unchanged | |
| ; | |
| checkPS2 proc | |
| jmp short @@ps2foo | |
| @@noPS2y: jmp @@noPS2 ; no supported type | |
| @@ps2foo: | |
| int 11h ; get equipment list | |
| ; testflag al,mask HW_PS2 | |
| test al, mask HW_PS2 | |
| jz @@noPS2y ; jump if PS/2 not indicated | |
| mov bh,3 ; standard 3 byte packets | |
| PS2serv 0C205h,@@noPS2y ; initialize mouse, bh=datasize | |
| mov bh,3 ; resolution: 2^bh counts/mm | |
| PS2serv 0C203h,@@noPS2x ; set mouse resolution bh | |
| PS2serv 0C204h,@@PS2valid1 ; get type (KoKo) | |
| ; Dell Inspirion 1501 touchpad fails w/ i/o error on c204 | |
| ; but works as a 2 button non-PnP mouse with ctmouse 1.9 | |
| @@isPS2pnp: cmp bh,0FFh ; KoKo: ? | |
| jz @@PS2valid1 | |
| cmp bh,0AAh ; Dosemu | |
| jz @@PS2valid1 | |
| cmp bh,0 ; KoKo: plain | |
| jz @@PS2valid1 | |
| cmp bh,3 ; KoKo: wheel | |
| jz @@PS2valid1 | |
| cmp bh,4 ; KoKo: plain? wheel? | |
| jz @@PS2valid1 | |
| @@noPS2x: jmp @@noPS2 ; no supported type | |
| @@dummyPS2: retf ; no-op callback handler | |
| @@PS2valid1: push cs | |
| pop es | |
| mov bx,coderef:@@dummyPS2 | |
| PS2serv 0C207h,@@noPS2x ; can we set a handler? | |
| MOVSEG es,0,bx,nothing | |
| PS2serv 0C207h ; clear mouse handler (ES:BX=0) | |
| ; testflag [options],OPT_Wheel ; dare to try PS2 wheel? | |
| test byte ptr [options+1], OPT_Wheel shr 8 ; TASM optimizes | |
| ; if_ nz | |
| jz @@ps2wz | |
| ;----- select IntelliMouse Z wheel + 3 button mode, via magic rate handshake | |
| mov ah,200 | |
| call setRate | |
| jc @@noPS2z | |
| mov ah,100 | |
| call setRate | |
| jc @@noPS2z | |
| mov ah,80 | |
| call setRate ; 200->100->80 rate does this | |
| jc @@noPS2z | |
| ; end_ | |
| @@ps2wz: | |
| ;----- check if successful | |
| if 0 | |
| mov dx,0D464h ; enable mouse functions | |
| call outKBD | |
| mov dx,0F260h ; get ID | |
| call flushKBD ; returns ah | |
| else | |
| PS2serv 0C204h,@@PS2nonPnP ; get type (KoKo) | |
| mov ah,bh | |
| endif | |
| cmp ah,0FFh ; ? | |
| jz @@PS2valid2 | |
| cmp ah,0AAh ; Dosemu | |
| jz @@PS2valid2 | |
| cmp ah,0 ; plain | |
| jz @@PS2valid2 | |
| cmp ah,3 ; wheel | |
| jz @@PS2valid2 | |
| cmp ah,4 ; plain? wheel? | |
| jz @@PS2valid2 | |
| jmp @@noPS2 ; no supported type | |
| @@noPS2z: jmp @@noPS2 | |
| @@PS2nonPnP: ; see note about Dell Inspiron 1501 above | |
| mov ah,0 ; assume plain | |
| @@PS2valid2: | |
| xor bx,bx ; =PS/2 mouse found | |
| cmp ah,3 ; ID=3 -> 3 button+wheel mode | |
| ; if_ eq | |
| jnz @@ps2w2 | |
| ; testflag [options],OPT_Wheel | |
| test byte ptr [options+1], OPT_Wheel shr 8 ; TASM optimizes | |
| ; if_ nz ; patch a jump short from to PS2PLAIN into to PS2WHEEL: | |
| jz @@ps2w2 | |
| ; mov PS2WHEELCODE[1], PS2WHEEL - PS2WHEELCODE - 2 | |
| ; ... push bx | |
| ; ... mov bx,offset PS2WHEELCODE + 2 ; enable wheel | |
| ; ... mov word ptr cs:[bx], -1 ; make test return NZ | |
| ; ... pop bx | |
| mov byte ptr [PS2WHEELCODE+1],PS2WHEEL-PS2WHEELCODE-2 | |
| mov bl,80h ; =PS/2+wheel mouse | |
| push ax | |
| push bx | |
| mov bh,4 ; packet size in bytes | |
| PS2serv 0C205h,@@noPS2w ; -X- KoKo: 4 byte protocol | |
| mov ah,200 ; -X- KoKo: repeat magic... | |
| call setRate | |
| jc @@noPS2w | |
| mov ah,100 | |
| call setRate | |
| jc @@noPS2w | |
| mov ah,80 | |
| call setRate | |
| jc @@noPS2w | |
| pop bx | |
| pop ax | |
| ; end_ | |
| ; end_ | |
| @@ps2w2: | |
| ;----- | |
| ; -X- mov byte ptr [IRQintnum],68h+12 | |
| ; no handler yet, enabledriver_20 does int 15/C207, 15/C200 | |
| clc | |
| ret | |
| @@noPS2w: pop bx | |
| pop ax | |
| @@noPS2: stc | |
| ret | |
| checkPS2 endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Set mouse sampling rate to AH samples per second | |
| ; -X- old version changed DX and (!) ES | |
| setRate proc | |
| if 0 | |
| push ax | |
| mov dx,0D464h ; enable mouse functions | |
| call outKBD | |
| mov dx,0F360h ; set rate... | |
| call flushKBD ; should be 0FAh (ACK) or 0FEh (resend) | |
| mov dx,0D464h ; enable mouse functions | |
| call outKBD | |
| pop dx | |
| mov dl,60h ; ...value | |
| ;j flushKBD ; should be 0FAh (ACK) or 0FEh (resend) | |
| else | |
| push ax | |
| mov al,6 | |
| cmp ah,200 | |
| jz @@RATEFOUND | |
| dec ax ; OPTIMIZE: instead of AL | |
| cmp ah,100 | |
| jz @@RATEFOUND | |
| dec ax ; OPTIMIZE: instead of AL | |
| cmp ah,80 | |
| jz @@RATEFOUND | |
| dec ax ; OPTIMIZE: instead of AL | |
| cmp ah,60 | |
| jz @@RATEFOUND | |
| dec ax ; OPTIMIZE: instead of AL | |
| cmp ah,40 | |
| jz @@RATEFOUND | |
| dec ax ; OPTIMIZE: instead of AL | |
| cmp ah,20 | |
| jz @@RATEFOUND | |
| dec ax ; OPTIMIZE: instead of AL | |
| cmp ah,10 | |
| jz @@RATEFOUND | |
| ; else: invalid rate selected, using 10 Hz :-p | |
| @@RATEFOUND: push bx | |
| mov bh,al ; the rate | |
| PS2serv 0C202h,@@RATEERR ; set rate | |
| clc | |
| pop bx | |
| pop ax | |
| ret | |
| @@RATEERR: stc | |
| pop bx | |
| pop ax | |
| ret | |
| endif | |
| SetRate endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: DL (port) | |
| ; DH (value) | |
| ; Out: AH | |
| ; Use: 0:46Ch | |
| ; Modf: AL, DX, ES | |
| ; Call: outKBD | |
| ; | |
| if 0 | |
| flushKBD proc | |
| call outKBD | |
| mov ah,0 | |
| @@inKBDstart: MOVSEG es,0,dx,BIOS | |
| loop_ | |
| mov dl,byte ptr [BIOS_timer] | |
| loop_ | |
| in al,64h ; keyboard status register | |
| test al,00000001b ; =1 | |
| if_ nz ; if read buffer full | |
| inb ah,60h | |
| j @@inKBDstart ; wait next byte | |
| end_ | |
| cmp dl,byte ptr [BIOS_timer] | |
| until_ ne ; loop until next timer tick | |
| xor dh,1 | |
| until_ zero ; loop until end of 2nd tick | |
| clc | |
| ret | |
| flushKBD endp | |
| endif | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Send command to auxiliary device | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: DL (port) | |
| ; DH (value) | |
| ; Out: none | |
| ; Use: 0:46Ch | |
| ; Modf: AL, DH, ES | |
| ; Call: none | |
| ; | |
| if 0 | |
| outKBD proc | |
| push dx | |
| MOVSEG es,0,dx,BIOS | |
| loop_ | |
| mov dl,byte ptr [BIOS_timer] | |
| loop_ | |
| in al,64h ; keyboard status register | |
| test al,00000010b ; =2 ; check if we can send data | |
| jz @@outKBD ; jump if write buffer empty | |
| cmp dl,byte ptr [BIOS_timer] | |
| until_ ne ; loop until next timer tick | |
| xor dh,1 | |
| until_ zero ; loop until end of 2nd tick | |
| @@outKBD: pop dx | |
| mov al,dh | |
| mov dh,0 | |
| out dx,al | |
| ret | |
| outKBD endp | |
| endif | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Set COM port | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: AL (COM port, 1-4) | |
| ; Out: none | |
| ; Use: 0:400h | |
| ; Modf: AL, CL, ES, com_port, IO_address, S_atIO | |
| ; Call: setIRQ | |
| ; | |
| setCOMport proc | |
| push ax | |
| push di | |
| add al,'0' | |
| mov [com_port],al | |
| cbw ; OPTIMIZE: instead MOV AH,0 | |
| xchg di,ax ; OPTIMIZE: instead MOV DI,AX | |
| MOVSEG es,0,ax,BIOS | |
| add di,di | |
| mov ax,COM_base[di-'1'-'1'] | |
| mov [IO_address],ax | |
| mov di,dataref:S_atIO ; string for 4 digits | |
| MOVSEG es,ds,,@data | |
| _word_hex | |
| pop di | |
| pop ax | |
| and al,1 ; 1=COM1/3, 0=COM2/4 | |
| add al,3 ; IRQ4 for COM1/3 | |
| ;j setIRQ ; IRQ3 for COM2/4 | |
| setCOMport endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Set IRQ number | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: AL (IRQ#, 1-7) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AL, CL, IRQno, mouseinfo, IRQintnum, PIC1state, notPIC1state | |
| ; Call: none | |
| ; | |
| setIRQ proc | |
| add al,'0' | |
| mov [IRQno],al | |
| sub al,'0' | |
| mov mouseinfo[0],al | |
| mov cl,al | |
| add al,8 ; INT=IRQ+8 | |
| mov [IRQintnum],al | |
| mov al,1 | |
| shl al,cl ; convert IRQ into bit mask | |
| mov [PIC1state],al ; PIC interrupt disabler | |
| not al | |
| mov [notPIC1state],al ; PIC interrupt enabler | |
| ret | |
| setIRQ endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Check if CuteMouse driver is installed | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: none | |
| ; Out: Zero flag (ZF=1 if installed) | |
| ; ES (driver segment) | |
| ; Use: IDstring | |
| ; Modf: AX, CX, SI, DI | |
| ; Call: mousedrv | |
| ; | |
| getCuteMouse proc | |
| xor di,di | |
| mov al,4Dh ; get copyright string | |
| call mousedrv | |
| mov si,TSRcref:IDstring | |
| cmp di,si | |
| ; if_ eq | |
| jnz @@gcmnz | |
| mov cx,szIDstring | |
| repe cmpsb | |
| ; end_ | |
| @@gcmnz: | |
| ret | |
| getCuteMouse endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Call mouse driver if present | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| ; | |
| ; In: AL (function) | |
| ; Out: results of INT 33h, if driver installed | |
| ; Use: oldint33 | |
| ; Modf: AH | |
| ; Call: INT 33 | |
| ; | |
| mousedrv proc | |
| mov cx,word ptr oldint33[2] | |
| ; if_ ncxz | |
| jcxz @@mdcxz | |
| mov ah,0 | |
| pushf ;!!! Logitech MouseWare | |
| call [oldint33] ; Windows driver workaround | |
| ; end_ | |
| @@mdcxz: | |
| ret | |
| mousedrv endp | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ COMMAND LINE PARSING ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Parse Serial option | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| _serialopt proc | |
| mov bx,(4 shl 8)+1 | |
| call parsedigit | |
| ; if_ nc ; '/Sc' -> set COM port | |
| jc @@soc | |
| ; setflag [options],OPT_COMforced | |
| or byte ptr [options], OPT_COMforced ; TASM optimizes | |
| call setCOMport | |
| ;mov bl,1 | |
| mov bh,7 | |
| call parsedigit | |
| jnc setIRQ ; '/Sci' -> set IRQ line | |
| ; end_ | |
| @@soc: | |
| ret | |
| _serialopt endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Parse Resolution option | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| _resolution proc | |
| ;mov ah,0 | |
| mov bx,(9 shl 8)+0 | |
| call parsedigit ; first argument | |
| ; if_ nc | |
| jc @@resc | |
| mov ah,al | |
| ;mov bx,(9 shl 8)+0 | |
| call parsedigit ; second argument | |
| jnc @@setres ; jump if digit present | |
| ; end_ | |
| @@resc: | |
| mov al,ah ; replicate missing argument | |
| @@setres: add ax,0101h | |
| push ax ; AL=RY+1, AH=RX+1 | |
| mov al,10 | |
| mul ah ; AX=10*(RX+1) | |
| mov bx,offset POINT.X+(DefArea-SaveArea) | |
| call senscalc | |
| pop ax | |
| mov ah,10 | |
| mul ah ; AX=10*(RY+1) | |
| mov bx,offset POINT.Y+(DefArea-SaveArea) | |
| jmp senscalc | |
| _resolution endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: DS:SI (string pointer) | |
| ; BL (low bound) | |
| ; BH (upper bound) | |
| ; Out: DS:SI (pointer after digit) | |
| ; Carry flag (no digit) | |
| ; AL (digit if no carry) | |
| ; Use: none | |
| ; Modf: CX | |
| ; Call: BADOPTION | |
| ; | |
| parsedigit proc | |
| lodsb | |
| ;_ch2digit | |
| sub al,'0' | |
| cmp al,bh | |
| ; if_ be | |
| ja @@pda | |
| cmp al,bl | |
| jae @ret ; JAE mean CF=0 | |
| ; end_ | |
| @@pda: | |
| cmp al,10 | |
| mov cx,dataref:E_argument ; 'Error: Invalid argument' | |
| jb BADOPTION ; error if decimal digit | |
| dec si | |
| stc | |
| @ret:: ret | |
| parsedigit endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Check if mouse services already present | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| _checkdriver proc | |
| mov cx,word ptr oldint33[2] | |
| jcxz @ret | |
| ;mov ah,0 | |
| mov al,21h ; OPTIMIZE: AL instead AX | |
| int 33h | |
| inc ax | |
| jnz @ret | |
| mov di,dataref:E_mousepresent ; 'Mouse service already...' | |
| j EXITMSG | |
| _checkdriver endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| .const | |
| cmOPTION struc ; OPTION is a reserved word in some MASM / TASM | |
| optchar db ? | |
| optmask dw 0 | |
| optproc@ dw ? | |
| cmOPTION ends | |
| OPTABLE cmOPTION <'P',OPT_PS2, @ret> | |
| cmOPTION <'O',OPT_Wheel, @ret> | |
| cmOPTION <'S',OPT_serial, _serialopt> | |
| cmOPTION <'V',OPT_PS2after, @ret> | |
| cmOPTION <'3' and not 20h,OPT_3button, @ret> | |
| cmOPTION <'R',, _resolution> | |
| cmOPTION <'L',OPT_lefthand, @ret> | |
| cmOPTION <'B',, _checkdriver> | |
| cmOPTION <'N',OPT_newTSR, @ret> | |
| cmOPTION <'W',OPT_noUMB, @ret> | |
| cmOPTION <'U',, unloadTSR> | |
| cmOPTION <'?' and not 20h,, EXITMSG> | |
| ; ignore the old "disable mouse systems" option | |
| ; default is now to disable old mouse systems, as | |
| ; those can be confused with empty serial ports. | |
| cmOPTION <'Y',, @ret> | |
| ; new option to "enable mouse systems"... | |
| cmOPTION <'M',OPT_MSYS, @ret> | |
| OPTABLEend label byte | |
| .code | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: DS:SI (null terminated command line) | |
| ; | |
| commandline proc | |
| ; loop_ | |
| @@clloop: | |
| lodsb | |
| test al,al | |
| jz @ret ; exit if end of command line | |
| cmp al,' ' | |
| ; until_ above ; skips spaces and controls | |
| jbe @@clloop | |
| cmp al,'/' ; option character? | |
| ; if_ eq | |
| jnz @@clnz | |
| lodsb | |
| and al,not 20h ; uppercase | |
| mov di,dataref:Syntax ; 'Options:' | |
| mov bx,dataref:OPTABLE | |
| ; loop_ | |
| @@cloloop: | |
| cmp al,[bx + offset cmOPTION.optchar] | |
| ; if_ eq | |
| jnz @@clonz | |
| mov ax,[bx + offset cmOPTION.optmask] | |
| or [options],ax | |
| call [bx + offset cmOPTION.optproc@] | |
| j commandline | |
| ; end_ | |
| @@clonz: | |
| add bx,size cmOPTION | |
| cmp bx,dataref:OPTABLEend | |
| ; until_ ae | |
| jb @@cloloop | |
| ; end_ if | |
| @@clnz: | |
| mov cx,dataref:E_option ; 'Error: Invalid option' | |
| BADOPTION:: say @data:E_error ; 'Error: Invalid ' | |
| ; say cx ; 'option'/'argument' | |
| mov di,cx | |
| call sayASCIIZ | |
| mov di,dataref:E_help ; 'Enter /? on command line' | |
| EXITMSG:: mov bl,[di] | |
| inc di | |
| ; say di | |
| call sayASCIIZ | |
| say @data:S_CRLF | |
| xchg ax,bx ; OPTIMIZE: instead MOV AL,BL | |
| .exit ; terminate, al=return code | |
| commandline endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: DS:DI (null terminated string) | |
| ; Out: none | |
| ; Use: none | |
| ; Modf: AH, DL, DI | |
| ; Call: none | |
| ; | |
| sayASCIIZ_ proc | |
| ; loop_ | |
| @@sazloop: | |
| mov ah,2 | |
| int 21h ; write character in DL to stdout | |
| inc di | |
| sayASCIIZ:: mov dl,[di] | |
| test dl,dl | |
| ; until_ zero | |
| jnz @@sazloop | |
| ret | |
| sayASCIIZ_ endp | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ TSR MANAGEMENT ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Unload driver and quit | |
| ;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ | |
| unloadTSR proc | |
| call getCuteMouse ; check if CTMOUSE installed | |
| mov di,dataref:E_nocute ; 'CuteMouse driver is not installed!' | |
| jne EXITMSG | |
| push es | |
| mov al,1Fh ; disable CuteMouse driver | |
| call mousedrv | |
| mov cx,es | |
| pop es | |
| cmp al,1Fh | |
| mov di,dataref:E_notunload ; 'Driver unload failed...' | |
| ; if_ eq | |
| jnz @@unlnz | |
| saveFAR [oldint33],cx,bx | |
| push ds | |
| ; DOSSetIntr 33h,cx,,bx ; restore old int33 handler | |
| mov dx,bx | |
| mov ax,2533h | |
| mov ds,cx | |
| int 21h | |
| pop ds | |
| call FreeMem | |
| mov di,dataref:S_unloaded ; 'Driver successfully unloaded...' | |
| ; end_ | |
| @@unlnz: | |
| EXITENABLE:: mov al,20h ; enable old/current driver | |
| call mousedrv | |
| j EXITMSG | |
| unloadTSR endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Prepare memory for TSR | |
| ; | |
| ; In: BX (TSR size) | |
| ; DS (PSP segment) | |
| ; Out: ES (memory segment to be TSR) | |
| ; CH (exit code for INT 21) | |
| ; Use: PSP:2Ch, MCB:8 | |
| ; Modf: AX, CL, DX, SI, DI | |
| ; Call: INT 21/49, AllocUMB | |
| ; | |
| prepareTSR proc | |
| assume ds:PSP | |
| mov cx,[env_seg] | |
| ; if_ ncxz ; suggested by Matthias Paul | |
| jcxz @@prepcxz | |
| DOSFreeMem cx ; release environment block | |
| ; end_ | |
| @@prepcxz: | |
| assume ds:@data | |
| call AllocUMB | |
| mov ax,ds | |
| mov ch,31h ; TSR exit, al=return code | |
| cmp dx,ax | |
| ; if_ ne ; if TSR not "in place" | |
| jz @@prepz | |
| push ds | |
| dec ax ; current MCB | |
| dec dx ; target MCB... | |
| ; ...copy process name | |
| memcopy 8,dx,MCB,MCB:ownername,ax,MCB,MCB:ownername | |
| POPSEG ds,@data | |
| inc dx | |
| mov [MCB:ownerID],dx ; ...set owner to itself | |
| mov ch,4Ch ; terminate, al=return code | |
| ; end_ if | |
| @@prepz: | |
| mov es,dx | |
| ; mov es:[PSP:DOS_exit],cx ; memory shouldn't be | |
| ; interpreted as PSP | |
| ; (CX != 20CDh) | |
| mov es:[0],cx ; JWASM complains about es:PSP:... | |
| ret | |
| prepareTSR endp | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ MEMORY HANDLING ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Get XMS handler address | |
| ; | |
| ; In: none | |
| ; Out: Carry flag (set if no XMS support) | |
| ; Use: none | |
| ; Modf: AX, CX, BX, XMSentry | |
| ; Call: INT 2F/4300, INT 2F/4310 | |
| ; | |
| if 0 | |
| getXMSaddr proc C uses es | |
| DOSGetIntr 2Fh ; suggested by Matthias Paul | |
| mov cx,es | |
| stc | |
| ; if_ ncxz ; if INT 2F initialized | |
| jcxz @@gxacxz | |
| mov ax,4300h | |
| int 2Fh ; XMS: installation check | |
| cmp al,80h | |
| stc | |
| ; andif_ eq ; if XMS service present | |
| jnz @@gxacxz | |
| mov ax,4310h ; XMS: Get Driver Address | |
| int 2Fh | |
| saveFAR [XMSentry],es,bx | |
| clc | |
| ; end_ | |
| @@gxacxz: | |
| ret | |
| getXMSaddr endp | |
| endif | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Save allocation strategy | |
| ; | |
| ; In: none | |
| ; Out: Carry flag (no UMB link supported) | |
| ; Use: none | |
| ; Modf: AX, SaveMemStrat, SaveUMBLink | |
| ; Call: INT 21/5800, INT 21/5802 | |
| ; | |
| SaveStrategy proc | |
| DOSGetAlloc ; get DOS alloc strategy | |
| mov [SaveMemStrat],ax | |
| DOSGetUMBlink ; get UMB link state | |
| mov [SaveUMBLink],al | |
| ret | |
| SaveStrategy endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Restore allocation strategy | |
| ; | |
| ; In: none | |
| ; Out: none | |
| ; Use: SaveMemStrat, SaveUMBLink | |
| ; Modf: AX, BX | |
| ; Call: INT 21/5801, INT 21/5803 | |
| ; | |
| RestoreStrategy proc | |
| ; CODE_ MOV_BX SaveMemStrat,<dw ?> | |
| OPCODE_MOV_BX | |
| SaveMemStrat dw ? | |
| DOSSetAlloc ; set DOS alloc strategy | |
| ; CODE_ MOV_BX SaveUMBLink,<db ?,0> | |
| OPCODE_MOV_BX | |
| SaveUMBLink db ?,0 | |
| DOSSetUMBlink ; set UMB link state | |
| ret | |
| RestoreStrategy endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; Allocate high memory | |
| ; | |
| ; In: BX (required memory size in para) | |
| ; DS (current memory segment) | |
| ; Out: DX (seg of new memory or DS) | |
| ; -X- Use: XMSentry | |
| ; Modf: AX, ES | |
| ; Call: INT 21/48, INT 21/49, INT 21/58, | |
| ; SaveStrategy, RestoreStrategy, getXMSaddr | |
| ; | |
| AllocUMB proc | |
| push bx | |
| ; testflag [options],OPT_noUMB | |
| test byte ptr [options], OPT_noUMB ; 80h, TASM optimizes | |
| jnz @@allocasis ; jump if UMB prohibited | |
| mov ax,ds | |
| cmp ah,0A0h | |
| jae @@allocasis ; jump if already loaded hi | |
| ;----- check if UMB is a DOS type | |
| call SaveStrategy | |
| DOSSetUMBlink UMB_LINK ; add UMB to MCB chain | |
| mov bl,HI_BESTFIT ; OPTIMIZE: BL instead BX | |
| DOSSetAlloc ; try best strategy to | |
| ; allocate DOS UMBs | |
| ; if_ carry | |
| jnc @@nhilo | |
| mov bl,HILOW_BESTFIT ; OPTIMIZE: BL instead BX | |
| DOSSetAlloc ; try a worse one then | |
| ; end_ | |
| @@nhilo: | |
| pop bx | |
| push bx | |
| DOSAlloc ; allocate UMB (size in BX) | |
| pushf | |
| xchg dx,ax ; OPTIMIZE: instead MOV DX,AX | |
| call RestoreStrategy ; restore allocation strategy | |
| popf | |
| ; if_ nc | |
| jc @@allc | |
| cmp dh,0A0h ; exit if allocated mem is | |
| jae @@allocret ; is above 640k (segment | |
| DOSFreeMem dx ; 0A000h) else free it | |
| ; end_ | |
| @@allc: | |
| if 0 | |
| ;----- try a XMS manager to allocate UMB | |
| call getXMSaddr | |
| ; if_ nc | |
| jc @@xmsc | |
| pop dx | |
| push dx | |
| mov ah,10h ; XMS: Request UMB (size=DX) | |
| call [XMSentry] ; ...AX=1 -> BX=seg, DX=size | |
| dec ax | |
| ; andif_ zero | |
| jnz @@xmsc | |
| pop ax | |
| push ax | |
| cmp bx,ax | |
| mov dx,bx | |
| jae @@allocret | |
| mov ah,11h ; XMS: Release UMB (seg=DX) | |
| call [XMSentry] | |
| ; end_ | |
| @@xmsc: | |
| endif | |
| ;----- use current memory segment | |
| @@allocasis: mov dx,ds | |
| @@allocret: pop bx | |
| ret | |
| AllocUMB endp | |
| ;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß | |
| ; In: ES (segment to free) | |
| ; Out: none | |
| ; Use: XMSentry | |
| ; Modf: AH, DX | |
| ; Call: INT 21/49, getXMSaddr | |
| ; | |
| FreeMem proc | |
| assume es:nothing | |
| if 0 | |
| call getXMSaddr | |
| ; if_ nc | |
| jc @@fmc | |
| mov dx,es | |
| mov ah,11h ; XMS: Release UMB | |
| call_far XMSentry | |
| ; end_ | |
| @@fmc: | |
| endif | |
| DOSFreeMem ; free allocated memory | |
| ret | |
| FreeMem endp | |
| ;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ | |
| end start |