; THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX ; SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO ; END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ; ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS ; IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS ; SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE ; FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE ; CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS ; AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. ; COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. ; $Log: not supported by cvs2svn $ ; Revision 1.2 1994/02/17 15:55:59 john ; Initial version ; ; Revision 1.20 1994/01/18 10:58:55 john ; *** empty log message *** ; ; Revision 1.19 1993/12/22 13:28:40 john ; Added back changes Matt made in r1.14 ; ; Revision 1.18 1993/12/22 13:18:32 john ; *** empty log message *** ; ; Revision 1.17 1993/12/20 16:48:47 john ; Put cli/sti around clear keybuffer in key_close ; ; Revision 1.16 1993/12/20 15:39:13 john ; Tried to neaten handler code... also, moved some cli's and sti's around ; trying to find bug. Made the code call key_get_milliseconds instead ; of timer_get_milliseconds, because we don't want the cli and sti ; stuff in the interrupt handler. ; ; Revision 1.15 1993/12/02 10:54:48 john ; Made the Ctrl,Shift,Alt keys buffer like all the other keys. ; ; Revision 1.14 1993/10/29 11:25:18 matt ; Made key_down_time() not accumulate time if shift,alt,ctrl down ; ; Revision 1.13 1993/10/29 10:47:00 john ; *** empty log message *** ; ; Revision 1.12 1993/10/16 19:24:16 matt ; Added new function key_clear_times() & key_clear_counts() ; ; Revision 1.11 1993/10/15 10:16:49 john ; bunch of stuff, mainly with detecting debugger. ; ; Revision 1.10 1993/10/04 13:25:57 john ; Changed the way extended keys are processed. ; ; Revision 1.9 1993/09/28 11:35:32 john ; added key_peekkey ; ; Revision 1.8 1993/09/23 18:09:23 john ; fixed bug checking for DBG ; ; Revision 1.7 1993/09/23 17:28:01 john ; made debug check look for DBG> instead of CONTROL ; ; Revision 1.6 1993/09/20 17:08:19 john ; Made so that keys pressed in debugger don't get passed through to ; the keyboard handler. I also discovered, but didn't fix a error ; (page fault) caused by jumping back and forth between the debugger ; and the program... ; ; Revision 1.5 1993/09/17 09:58:12 john ; Added checks for already installed, not installed, etc. ; ; Revision 1.4 1993/09/15 17:28:00 john ; Fixed bug in FlushBuffer that used CX before a REP instead of ECX. ; ; Revision 1.3 1993/09/08 14:48:00 john ; made getch() return an int instead of a char that has shift states, etc. ; ; Revision 1.2 1993/07/22 13:12:23 john ; fixed comment ; ,. ; ; Revision 1.1 1993/07/10 13:10:42 matt ; Initial revision ; ; ; ;*************************************************************************** ;*************************************************************************** ;***** ***** ;***** ***** ;***** K E Y . A S M ***** ;***** ***** ;***** Contains routines to get, buffer, and check key presses. ***** ;***** ***** ;***** ***** ;***** PROCEDURES ***** ;***** ***** ;***** key_init() - Activates the keyboard package. ***** ;***** key_close() - Deactivates the keyboard package. ***** ;***** key_check() - Returns 1 if a buffered key is waiting. ***** ;***** key_getch() - Waits for and returns a buffered keypress. ***** ;***** key_flush() - Clears buffers and state array. ***** ;***** key_time() - Index by scan code. Contains the time key has been ***** ;***** held down. NOT DONE YET. ***** ;***** ***** ;***** ***** ;***** VARIABLES ***** ;***** ***** ;***** keyd_buffer_type -Set to 0 and key_getch() always returns 0. ***** ;***** Set to 1 to so that ASCII codes are returned ***** ;***** by key_getch(). Set to 2 and key_getch() returns***** ;***** the buffered keyboard scan codes. ***** ;***** keyd_repeat - Set to 0 to not allow repeated keys in the ***** ;***** keyboard buffer. Set to 1 to allow repeats. ***** ;***** keyd_pressed[] -Index by scan code. Contains 1 if key down else 0***** ;***** ***** ;***** ***** ;***** CONSTANTS ***** ;***** ***** ;***** Setting the DEBUG to 1 at compile time passes SysReq through ***** ;***** to the debugger, and when the debugger is active, it will give ***** ;***** the debugger any keys that are pressed. Note that this only ***** ;***** works with the Watcom VIDEO debugger at this time. Setting ***** ;***** DEBUG to 0 takes out all the debugging stuff. ***** ;***** ***** ;*************************************************************************** ;*************************************************************************** DEBUG EQU 1 .386 ;************************************************************************ ;**************** FLAT MODEL DATA SEGMENT STUFF ************************* ;************************************************************************ _DATA SEGMENT BYTE PUBLIC USE32 'DATA' rcsid db "$Id: oldkey.asm,v 1.1.1.2 2001-01-19 03:33:50 bradleyb Exp $" PUBLIC _keyd_pressed ; Must start with a _ so C can see the variable. _keyd_pressed db 256 dup (?) keybuffer dw 256 dup (?) ; Use 256 so an inc wraps around TimeKeyWentDown dd 256 dup(0) TimeKeyHeldDown dd 256 dup(0) NumDowns dd 256 dup(0) NumUps dd 256 dup(0) MyCodeSegment dw ? PUBLIC _keyd_editor_mode _keyd_editor_mode db 0 PUBLIC _keyd_use_bios _keyd_use_bios db 1 PUBLIC _keyd_last_pressed _keyd_last_pressed db 0 PUBLIC _keyd_last_released _keyd_last_released db 0 PUBLIC _keyd_dump_key_array _keyd_dump_key_array db 0 org_int_sel dw ? org_int_off dd ? interrupted_cs dw ? interrupted_eip dd ? keyhead db ? keytail db ? PUBLIC _keyd_buffer_type PUBLIC _keyd_repeat _keyd_buffer_type db ? ; 0=No buffer, 1=buffer ASCII, 2=buffer scans _keyd_repeat db ? E0Flag db 0 Installed db 0 INCLUDE KEYS.INC _DATA ENDS DGROUP GROUP _DATA ;************************************************************************ ;**************** FLAT MODEL CODE SEGMENT STUFF ************************* ;************************************************************************ _TEXT SEGMENT BYTE PUBLIC USE32 'CODE' ASSUME ds:_DATA ASSUME cs:_TEXT key_get_milliseconds: EXTERNDEF timer_get_stamp64:NEAR push ebx push edx call timer_get_stamp64 ; Timing in milliseconds ; Can be used for up to 1000 hours shld edx, eax, 21 ; Keep 32+11 bits shl eax, 21 mov ebx, 2502279823 ; 2^21*1193180/1000 div ebx pop edx pop ebx ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ T O _ A S C I I _ ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_to_ascii_ key_to_ascii_: ; EAX = scancode push ebx mov bl, ah and bl, 011111110b cmp bl, 0 jne CantDoKey cmp al, 127 jae CantDoKey and ah, 01b ; take away ctrl and alt codes shl al, 1 shr eax, 1 and eax, 0ffh mov al, byte ptr key1[eax] pop ebx ret CantDoKey: pop ebx mov eax, 255 ret public key_clear_times_,key_clear_counts_ ;clear the array of key down times. key_clear_times_: cli push eax push ecx push edi xor eax,eax mov ecx,256 lea edi,TimeKeyHeldDown rep stosd ;clear array pop edi pop ecx pop eax sti ret ;clear the arrays of key down counts key_clear_counts_: cli push eax push ecx push edi xor eax,eax mov ecx,256 lea edi,NumDowns rep stosd ;clear array mov ecx,256 lea edi,NumUps rep stosd ;clear array pop edi pop ecx pop eax sti ret PUBLIC key_down_time_ key_down_time_: cli push edx push ecx push ebx mov ebx, eax xor eax, eax cmp _keyd_pressed[ebx], 0 je NotPressed cmp _keyd_editor_mode, 0 je read_time call get_modifiers ;shift,alt,ctrl? or ah,ah jz read_time xor eax,eax jmp NotPressed read_time: mov ecx, TimeKeyWentDown[ebx*4] call key_get_milliseconds mov TimeKeyWentDown[ebx*4], eax sub eax, ecx ; EAX = time held since last NotPressed: add eax, TimeKeyHeldDown[ebx*4] mov TimeKeyHeldDown[ebx*4], 0 pop ebx pop ecx pop edx sti ret PUBLIC key_down_count_ key_down_count_: cli push ebx mov ebx, eax mov eax, NumDowns[ebx*4] mov NumDowns[ebx*4], 0 pop ebx sti ret PUBLIC key_up_count_ key_up_count_: cli push ebx mov ebx, eax mov eax, NumUps[ebx*4] mov NumUps[ebx*4], 0 pop ebx sti ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ F L U S H ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_flush_ key_flush_: cli push eax push ecx push edi mov keyhead,0 mov keytail,255 mov E0Flag, 0 ; Clear the keyboard array mov edi, offset _keyd_pressed mov ecx, 32 mov eax,0 rep stosd pop edi pop ecx pop eax sti ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ I N I T ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_init_ key_init_: push eax push ebx push ds push es ;************************************************************** ;******************* INITIALIZE key QUEUE ********************** ;************************************************************** mov _keyd_buffer_type,1 mov _keyd_repeat,1 mov E0Flag, 0 ; Clear the keyboard array call key_flush_ cmp Installed, 0 jne AlreadyInstalled ;************************************************************** ;******************* SAVE OLD INT9 HANDLER ******************** ;************************************************************** mov Installed, 1 mov eax, 03509h ; DOS Get Vector 09h int 21h ; Call DOS mov org_int_sel, es ; Save old interrupt selector mov org_int_off, ebx ; Save old interrupt offset ;************************************************************** ;***************** INSTALL NEW INT9 HANDLER ******************* ;************************************************************** mov eax, 02509h ; DOS Set Vector 09h mov edx, offset key_handler ; Point DS:EDX to new handler mov bx, cs mov MyCodeSegment, bx mov ds, bx int 21h AlreadyInstalled: pop es pop ds pop ebx pop eax ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ C L O S E _ ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_close_ key_close_: push eax push ebx push edx push ds cmp Installed, 0 je @f ;************************************************************** ;***************** RESTORE OLD INT9 HANDLER ******************* ;************************************************************** mov Installed, 0 ; Clear the BIOS buffer cli mov ebx, 041ch mov al, byte ptr [ebx] mov ebx, 041ah mov byte ptr [ebx], al sti mov eax, 02509h ; DOS Set Vector 09h mov edx, org_int_off mov ds, org_int_sel int 21h @@: pop ds pop edx pop ebx pop eax ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ C H E C K _ ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_checkch_ ; Must end with a _ so C can see the function. key_checkch_: cli push ebx xor eax, eax cmp Installed, 0 je NoKey mov bl, keytail inc bl cmp bl, keyhead je Nokey mov eax, 1 Nokey: pop ebx sti ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ D E B U G ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_debug_ key_debug_: int 3h ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ G E T C H _ ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_getch_ ; Must end with a _ so C can see the function. key_getch_: push ebx xor eax, eax xor ebx, ebx cmp Installed, 0 jne StillNoKey pop ebx ret StillNoKey: cli ; Critical section mov bl, keytail inc bl cmp bl, keyhead sti je StillNoKey cli ; Critical section xor ebx, ebx mov bl, keyhead mov ax, word ptr keybuffer[ebx*2] inc BYTE PTR keyhead sti pop ebx ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ I N K E Y _ ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_inkey_ ; Must end with a _ so C can see the function. key_inkey_: push ebx xor eax, eax xor ebx, ebx cmp Installed, 0 je NoInkey cli ; Critical section mov bl, keytail inc bl cmp bl, keyhead sti je NoInkey cli ; Critical section mov bl, keyhead mov ax, word ptr keybuffer[ebx*2] inc BYTE PTR keyhead sti NoInkey: pop ebx ret PUBLIC key_peekkey_ ; Must end with a _ so C can see the function. key_peekkey_: push ebx xor eax, eax xor ebx, ebx cli ; Critical section cmp Installed, 0 je NoPeek mov bl, keytail inc bl cmp bl, keyhead je NoPeek mov bl, keyhead mov ax, word ptr keybuffer[ebx*2] NoPeek: sti pop ebx ret ;************************************************************************ ;************************************************************************ ;***** ***** ;***** K E Y _ H A N D L E R ***** ;***** ***** ;************************************************************************ ;************************************************************************ PUBLIC key_handler ; Must end with a _ so C can see the function. key_handler: pushfd ; Save flags in case we have to chain to original push eax push ebx push ecx push edx push ds mov ax, DGROUP ; Point to our data segment, since this is an mov ds, ax ; interrupt and we don't know where we were. mov eax, (0b0000h+76*2) mov byte ptr [eax], '1' IFDEF DEBUG call CheckForDebugger jnc @f mov eax, 0b0000h+78*2 mov byte ptr [eax], 'D' jmp PassToBios ; If debugger is active, then skip buffer @@: mov eax, 0b0000h+78*2 mov byte ptr [eax], 'I' ; Clear the BIOS buffer ;**mov ebx, 041ch ;**mov al, byte ptr [ebx] ;**mov ebx, 041ah ;**mov byte ptr [ebx], al ENDIF xor eax, eax xor ebx, ebx in al, 060h ; Get scan code from keyboard cmp al, 0E0h jne NotE0Code E0Code: mov E0Flag, 010000000b jmp LeaveHandler ; If garbage key, then don't buffer it NotE0Code: mov bl, al ; Put break bit into bl ; 0 = pressed, 1=released and al, 01111111b ; AL = scancode or al, E0Flag ; AL = extended scancode mov E0Flag,0 ; clear E0 flag cmp al, 029h je pause_execution shl bl, 1 ; put upper bit into carry flag jc key_mark_released ; if upper bit of bl was set, then it was a release code ;************************************************************** ;****************** HANDLE A NEWLY PRESSED KEY **************** ;************************************************************** ;Marks the key press in EAX in the scancode array. key_mark_pressed: ;cmp al, 0eh ; backspace ;je pause_execution mov _keyd_last_pressed, al ; Check if the key is repeating or if it just got pressed. cmp byte ptr _keyd_pressed[eax], 1 je AlreadyDown ;------------------------------- Code for a key pressed for the first time ------------------------ mov byte ptr _keyd_pressed[eax], 1 ; Set the time push edx push eax call key_get_milliseconds mov edx, eax pop eax mov TimeKeyWentDown[eax*4], edx pop edx inc NumDowns[eax*4] jmp BufferAX ;------------------------------- Code for a key that is already pressed ------------------------ AlreadyDown: cmp _keyd_repeat, 0 je DoneMarkingPressed BufferAX: cmp _keyd_buffer_type, 0 je SkipBuffer ; Buffer = 0 means don't buffer anything. cmp al, 0AAh ; garbage key je SkipBuffer call get_modifiers ;returns ah xor ebx, ebx mov bl, keytail inc bl inc bl ; If the buffer is full then don't buffer this key cmp bl, keyhead je SkipBuffer dec bl mov word ptr keybuffer[ebx*2], ax mov keytail, bl SkipBuffer: ;---------------------------------- Exit function ----------------------------- DoneMarkingPressed: jmp LeaveHandler ;************************************************************** ;******************* HANDLE A RELEASED KEY ******************** ;************************************************************** ; Unmarks the key press in EAX from the scancode array. key_mark_released: mov _keyd_last_released, al mov byte ptr _keyd_pressed[eax], 0 inc NumUps[eax*4] cmp _keyd_editor_mode, 0 je NotInEditorMode push eax xor ah,ah call get_modifiers or ah,ah ;check modifiers pop eax jnz skip_time NotInEditorMode: push eax call timer_get_stamp64 ; Timing in milliseconds ; Can be used for up to 1000 hours shld edx, eax, 21 ; Keep 32+11 bits shl eax, 21 mov ebx, 2502279823 ; 2^21*1193180/1000 div ebx mov edx, eax pop eax sub edx, TimeKeyWentDown[eax*4] add TimeKeyHeldDown[eax*4], edx skip_time: ;**jmp LeaveHandler ;************************************************************** ;*************** FINISH UP THE KEYBOARD INTERRUPT ************* ;************************************************************** LeaveHandler: mov eax, (0b0000h+76*2) mov byte ptr [eax], '2' ;; cmp _keyd_dump_key_array, 0 ;; je DontPassToBios jmp PassToBios mov ecx, 256 mov ebx, 0 showdown: mov al, _keyd_pressed[ebx] add al, '0' mov [ebx*2+ 0b0000h], al inc ebx loop showdown mov eax, 0b0000h mov byte ptr [ eax+(036h*2+1) ], 070h mov byte ptr [ eax+(02Ah*2+1) ], 070h mov byte ptr [ eax+(038h*2+1) ], 070h mov byte ptr [ eax+(0B8h*2+1) ], 070h mov byte ptr [ eax+(01Dh*2+1) ], 070h mov byte ptr [ eax+(09dh*2+1) ], 070h mov byte ptr [ eax+(0AAh*2+1) ], 07Fh mov byte ptr [ eax+(0E0h*2+1) ], 07Fh jmp DontPassToBios ; If in debugger, pass control to dos interrupt. PassToBios: pop ds ; Nothing left on stack but flags pop edx pop ecx pop ebx pop eax sub esp, 8 ; Save space for IRETD frame push ds ; Save registers we use. push eax mov ax, DGROUP mov ds, ax ; Set DS to our data segment mov eax, org_int_off ; put original handler address mov [esp+8], eax ; in the IRETD frame movzx eax, org_int_sel mov [esp+12], eax pop eax ; Restore registers pop ds iretd ; Chain to previous handler pause_execution: in al, 61h ; Get current port 61h state or al, 10000000b ; Turn on bit 7 to signal clear keybrd out 61h, al ; Send to port and al, 01111111b ; Turn off bit 7 to signal break out 61h, al ; Send to port mov al, 20h ; Reset interrupt controller out 20h, al sti ; Reenable interrupts pop ds pop edx ; Restore all of the saved registers. pop ecx pop ebx pop eax sub esp, 8 ; Save space for IRETD frame push ds ; Save registers we use. push eax mov ax, DGROUP mov ds, ax ; Set DS to our data segment mov eax, org_int_off ; put original handler address mov [esp+8], eax ; in the IRETD frame movzx eax, org_int_sel mov [esp+12], eax pop eax ; Restore registers pop ds iretd ; Interrupt must return with IRETD DontPassToBios: ; Resets the keyboard, PIC, restores stack, returns. in al, 61h ; Get current port 61h state or al, 10000000b ; Turn on bit 7 to signal clear keybrd out 61h, al ; Send to port and al, 01111111b ; Turn off bit 7 to signal break out 61h, al ; Send to port mov al, 20h ; Reset interrupt controller out 20h, al sti ; Reenable interrupts pop ds pop edx ; Restore all of the saved registers. pop ecx pop ebx pop eax popfd iretd ; Interrupt must return with IRETD ;returns ah=bitmask of shift,ctrl,alt keys get_modifiers: push ecx xor ah,ah ; Check the shift keys mov cl, _keyd_pressed[ 036h ] or cl, _keyd_pressed[ 02ah ] or ah, cl ; Check the alt key mov cl, _keyd_pressed[ 038h ] or cl, _keyd_pressed[ 0b8h ] shl cl, 1 or ah, cl ; Check the ctrl key mov cl, _keyd_pressed[ 01dh ] or cl, _keyd_pressed[ 09dh ] shl cl, 2 or ah, cl pop ecx ret IFDEF DEBUG CheckForDebugger: ; Returns CF=0 if debugger isn't active ; CF=1 if debugger is active ;*************************** DEBUG ****************************** ; When we're in the VIDEO debugger, we want to pass control to ; the original interrupt. So, to tell if the debugger is active, ; I check if video page 1 is the active page since that is what ; page the debugger uses, and if that works, I check the top of ; the screen to see if the texxt "Control" is there, which should ; only be there when we're in the debugger. push eax ;mov eax, 0462h ; Address 0462 stores BIOS current page ;cmp BYTE PTR [eax], 1 ;jne NoDebuggerOnColor ;mov eax, 0b8000h+4096 ; 4096 = offset to 2nd video mem page ;cmp BYTE PTR [eax+2],'C' ;jne NoDebuggerOnColor ;cmp BYTE PTR [eax+4],'o' ;jne NoDebuggerOnColor ;cmp BYTE PTR [eax+6],'n' ;jne NoDebuggerOnColor ;cmp BYTE PTR [eax+8],'t' ;jne NoDebuggerOnColor ;cmp BYTE PTR [eax+10],'r' ;jne NoDebuggerOnColor ;cmp BYTE PTR [eax+12],'o' ;jne NoDebuggerOnColor ;cmp BYTE PTR [eax+14],'l' ;jne NoDebuggerOnColor ;jmp ActiveDebugger ;NoDebuggerOnColor: ; First, see if there is a mono debugger... ;mov eax, 0b0000h ; 4096 = offset to mono video mem ;cmp BYTE PTR [eax+2],'C' ;jne NoActiveDebugger ;cmp BYTE PTR [eax+4],'o' ;jne NoActiveDebugger ;cmp BYTE PTR [eax+6],'n' ;jne NoActiveDebugger ;cmp BYTE PTR [eax+8],'t' ;jne NoActiveDebugger ;cmp BYTE PTR [eax+10],'r' ;jne NoActiveDebugger ;cmp BYTE PTR [eax+12],'o' ;jne NoActiveDebugger ;cmp BYTE PTR [eax+14],'l' ;jne NoActiveDebugger mov eax, 0b0000h ; 4096 = offset to mono video mem add eax, 24*80*2 cmp BYTE PTR [eax+0],'D' jne NextTest cmp BYTE PTR [eax+2],'B' jne NextTest cmp BYTE PTR [eax+4],'G' jne NextTest cmp BYTE PTR [eax+6],'>' jne NextTest ;Found DBG>, so consider debugger active: jmp ActiveDebugger NextTest: cmp BYTE PTR [eax+14],'<' jne NextTest1 cmp BYTE PTR [eax+16],'i' jne NextTest1 cmp BYTE PTR [eax+18],'>' jne NextTest1 cmp BYTE PTR [eax+20],' ' jne NextTest1 cmp BYTE PTR [eax+22],'-' jne NextTest1 ; Found - , so consider debugger active: jmp ActiveDebugger NextTest1: cmp BYTE PTR [eax+0], 200 jne NextTest2 cmp BYTE PTR [eax+2], 27 jne NextTest2 cmp BYTE PTR [eax+4], 17 jne NextTest2 ; Found either the help screen or view screen, so consider ; debugger active jmp ActiveDebugger NextTest2: ; Now we see if its active by looking for the "Executing..." ; text on the bottom of the mono screen ;mov eax, 0b0000h ; 4096 = offset to mono video mem ;add eax, 24*80*2 ;cmp BYTE PTR [eax+0],'E' ;je NoActiveDebugger ;cmp BYTE PTR [eax+2],'x' ;je NoActiveDebugger ;cmp BYTE PTR [eax+4],'e' ;je NoActiveDebugger ;cmp BYTE PTR [eax+6],'c' ;je NoActiveDebugger NoActiveDebugger: pop eax clc ret ActiveDebugger: pop eax stc ret ENDIF _TEXT ENDS END