; MS-DOS textmode screenshot utility for the default 80x25 text mode
; Requires 80186+ (because of pusha/popa instructions)
; Compiling: nasm -fbin scrshot.asm -o scrshot.com
;
; Usage: run SCRSHOT.COM and press F10 to screenshot your screen
; The result is written in a file called 'SCRSHOT.TXT'

	bits 16
	org 100h
	push cs
	pop ds
	
	; get old interrupt handler
	mov ax, 3509h
	int 21h
	mov word [old_int9_offset], bx
	mov word [old_int9_seg], es

	; set new interrupt handler
	cli
	mov ax, 2509h
	mov dx, screenshot_int
	int 21h
	sti

	; terminate and stay resident
	mov ax, 3100h
	mov dx, 64 ; number of pages to keep
	int 21h

screenshot_int:
	pusha
	push ds
	push es

	in al, 60h
	cmp al, 0C4h ; trigger key - here F10
	je screenshot

	; if it is another key, handle it with the former int. handler

	mov ax, word cs:[old_int9_seg]
	mov bx, word cs:[old_int9_offset]
	pushf
	push cs
	push quit
	push ax
	push bx
	retf ; call the older handler
quit:
	pop es
	pop ds
	popa
	iret

screenshot:
	cli
	in al, 61h
	or al, 80h
	mov dl, al
	out 61h, al ; received
	mov al, dl
	out 61h, al ; original state
	mov al, 20h
	out 20h, al ; end of interrupt

	push cs
	pop ds

	; write screen content to file 'SCRSHOT.TXT'

	mov dx, 0B800h
	mov es, dx

        mov ah, 3Ch
        sub cx, cx
        mov dx, filename
        int 21h
        mov word [file_handler], ax

        sub si, si
	mov cx, 25
read:
	push cx
        mov di, buffer
	mov cx, 80
read_loop:
	mov al, byte es:[si]
	mov byte ds:[di], al
	inc si
	inc si
	inc di
	loop read_loop

	mov ah, 40h
	mov bx, word [file_handler]
	mov cx, 82
	mov dx, buffer
	int 21h
	jc quit ; if there is an error

	pop cx
	loop read

	mov ah, 3Eh
	mov bx, word [file_handler]
	int 21h
	jc quit

	sti
	jmp quit

;; data
file_handler:
	dw 0
filename:
	db "SCRSHOT.TXT", 0
buffer:
	times 80 db ' '
	db 0Dh, 0Ah
old_int9_offset:
	dw 0
old_int9_seg:
	dw 0
