home *** CD-ROM | disk | FTP | other *** search
- PAGE ,132
- TITLE HPRTSC
- SUBTTL Description
-
- ; Copyright (c) 1987, Background Processes
- ;
- ; Permission is hereby granted to copy, distribute, modify, include,
- ; burn, rape, or pillage this software in accordance with the following
- ; guidelines:
- ;
- ; 1) Distribution of this program is to be free. If a charge is made
- ; for copying, it must be no more than $5 US. Permission for
- ; inclusion into commercial products must be obtained individually.
- ;
- ; 2) Distribution of the program must include this complete source
- ; code, or at least it should be made available. Software
- ; exchange should not only be a way of getting free software,
- ; but should also be a learning experience. The best way to
- ; learn is to be able to read the source code.
- ;
- ; 3) You promise not to laugh at the code (at least not too hard). I'm
- ; a PDP-11 programmer. If that doesn't mean anything to you, ask
- ; a hacker friend about the advantages of orthogonal instruction sets
- ; and REAL general registers.
- ;
- ; 4) If you find (or correct - hint, hint) any bugs in this program, I
- ; would appreciate it if you would let me know. This way I can
- ; learn, too.
- ;
- ; Alan Groupe
- ; Background Processes
- ; PO Box 6347
- ; Nashua, NH 03063-6347
-
- ; This program implements a graphics screen dump from a Hercules
- ; monochrome graphics board. It is similar to the DOS GRAPHICS.COM in
- ; that it takes over the PrtSc interrupt.
-
- ; When HPRTSC is typed at the DOS prompt, it grabs the PrtSc interrupt
- ; vector, and then issues a terminate and stay resident DOS function
- ; call. When the PrtSc key is pressed, this program checks the Hercules
- ; board to determine whether it is in text or graphics mode. If the
- ; board is in text mode, the program simply executes a far jump to the
- ; original PrtSc routine. If the board is in graphics mode, the program
- ; waits for a key to be pressed on the keyboard. If the '1' key is pressed,
- ; the program scans through the first graphics page (B0000 - B7FFF; called
- ; page 0 in the Hercules manual) and formats it for output on the printer.
- ; If the '2' key is pressed, the second graphics page (B8000 - BFFFF) is
- ; printed. If any other key is pressed, you will hear a short beep and HPRTSC
- ; will just return. You can use this to freeze an animated graphics display
- ; to look at it more closely. Just press PrtSc to freeze the screen. To
- ; unfreeze it, just press any key other than '1' or '2'.
- ;
- ; The dot mapping of a Hercules board is a little weird. Each byte in
- ; the graphics memory corresponds to eight dots horizontally, with the
- ; most significant bit of each byte representing the leftmost dot of the
- ; eight. There are 720 dots across on the display, so the first 90 bytes
- ; (B0000 - B005A) make up the first line on the screen (line 1).
- ; However, the next 90 bytes are not line 2, but rather line 5. The next
- ; 90 bytes, line 9. This continues down the screen until line 345
- ; (B1E3C). The remaining 170 bytes (B1E96 - B1FFF) are unused. Then the
- ; 90 byte groups starting at B2000 correspond to lines 2, 6, 10, etc.
- ; Therefore, lines 1-10 have the respective starting addresses B0000,
- ; B2000, B4000, B6000, B005A, B205A, B405A, B605A, B00B4, and B20B4.
- ;
- ; This, of course, is not even close to how an Epson printer maps dots
- ; on the paper. The Epson printer takes an eight bit byte and prints a
- ; column of 8 dots vertically, with the most significant bit at the top.
- ;
- ; Since the Hercules board is organized horizontally and the Epson printer
- ; is organized vertically, this program prints the screen image rotated 90
- ; degrees.
-
- SUBTTL Entry Point
- PAGE +
-
- cseg segment
- assume cs:cseg,ds:cseg
-
- ; This is the initial program entry point. It jumps to 'init' which sets
- ; up the interrupt vector, prints out a message confirming program load,
- ; and does a terminate and stay resident call.
-
- jmp init ; jump around real code to load in memory
- SUBTTL PrtSc Entry Point
- PAGE +
-
- ; This is the entry point when PrtSc is pressed. It is ORG'ed at location
- ; 348 (minus 100h) to allow the previous 348 bytes, including the now
- ; unnecessary PSP to be used as a buffer to hold a full vertical scan of the
- ; screen.
-
- org 348-100h
-
- int5:
- push ax
- push bx
- push dx
-
- ; First we must determine whether the Hercules board is in text mode or
- ; graphics mode. This is done with a program given to me by Hercules Computer
- ; Technology Inc. It isn't real clear to me why this program works the way it
- ; does, but it appears that if you force trip the light pen, it returns the
- ; character location (6845 meaning) just past the end of the screen. This may
- ; have something to do with the fact that there is no light pen receiving a
- ; raster pulse. If this is the case, I have no idea if this still works if you
- ; actually have a light pen connected.
-
- ourstat equ 03bah
- notvsync equ 80h
- lpreset equ 03bbh
- lpset equ 03b9h
- our6845 equ 03b4h
- threshold equ (80*25 + 45*87)/2
-
- mov dx,ourstat
-
- w1: in al,dx ; first, wait for vertical retrace
- test al,notvsync
- jz w1
-
- w2: in al,dx ; then make sure not to test during vertical
- test al,notvsync ; retrace
- jnz w2
-
- xor al,al ; tickle light pen
- mov dx,lpreset
- out dx,al
- mov dx,lpset
- out dx,al
-
- mov al,16 ; get high byte of lp trip offset
- mov dx,our6845
- out dx,al
- inc dx
- in al,dx
- mov bh,al
-
- mov al,17 ; and low byte
- mov dx,our6845
- out dx,al
- inc dx
- in al,dx
-
- mov ah,bh ; return light pen trip address
- cmp ax,threshold
- pop dx ; restore original user registers
- pop bx
- pop ax
- ja gprint ; above threshold, in graphics mode
-
- ; The following two lines are a 'jmp far' instruction to jump to the BIOS
- ; print screen routine if the Hercules board is in text mode. The location
- ; is filled in in the 'init' routine.
-
- tjump: db 0eah ;! JMP FAR 0:0
- dw 0,0
-
- SUBTTL Graphics Entry Point
- PAGE +
-
- ; This is the entry point if the Hercules board is in graphics mode.
-
- gprint:
- push ax ; save all registers
- push bx
- push cx
- push dx
- push si
- push di
- push bp
- push ds
- push es
-
- ; First test location 50:0 to see if print screen is already in progress.
-
- mov ax,50h
- mov ds,ax
- cmp byte ptr ds:0,1 ; prtsc already active?
- mov byte ptr ds:0,1 ; it is now
- mov ax,cs ; retore ds:
- mov ds,ax
- jnz gp1 ; print screen in progress before? no.
- jmp exit ; yes
- gp1:
- xor ax,ax ; set for read char
- int 16h ; read char from keyboard
- mov dx,0b000h ; assume page 1
- cmp al,'1'
- je gp3
- mov dx,0b800h ; page 2
- cmp al,'2'
- je gp3
- ;
- ; neither '1' nor '2', so beep an error and return
- ;
- timer equ 40h
- port_b equ 61h
-
- mov al,10110110b ; sel tim 2,lsb,msb,binary
- out timer+3,al ; write the timer mode reg
- mov ax,533h ; divisor for 1000 hz
- out timer+2,al ; write timer 2 cnt - lsb
- mov al,ah
- out timer+2,al ; write timer 2 cnt - msb
- in al,port_b ; get current setting of port
- mov ah,al ; save that setting
- or al,03 ; turn speaker on
- out port_b,al
- sub cx,cx ; set count to 500 ms
- gp2: loop gp2 ; delay before turning off
- mov al,ah ; recover value of port
- out port_b,al
- jmp done
-
- ;
- ; set up printer for graphics printing
- ;
- gp3: mov ds,dx ; segment address of page requested
- push cs ; es points to work area which is at
- pop es ; beginning of code segment
- xor dx,dx ; printer number is zero (LPT1)
- xor si,si ; horizontal offset (start at left edge)
-
- mov ax,27 ; select 8/72" line feeds (ESC A 8)
- int 17h
- mov ax,'A'
- int 17h
- mov ax,8
- int 17h
- mov ax,27 ; set selection in force (ESC 2)
- int 17h
- mov ax,'2'
- int 17h
-
- ; start running through screen starting with lower left corner, working up
- ; and then to the right
- ;
- ; l1 is loop for each vertical pass. This is also one print line.
-
- l1: mov bx,1e3ch ; bottom-most scan line in first quadrant
- mov cx,87 ; # horizontal lines in a quadrant (348/4)
- xor di,di ; pointer into ES: work area (beginning of code)
-
- l2: mov al,6000h[bx+si] ; get character from quadrant 4 scan line
- stosb ; and store in work area
- cmp al,0 ; if it was other than a zero, store new
- je $+4 ; of di in dx so dx will be length of line to
- mov dx,di ; print (null truncated)
-
- mov al,4000h[bx+si] ; do likewise for third quadrant
- stosb
- cmp al,0
- je $+4
- mov dx,di
-
- mov al,2000h[bx+si] ; and second
- stosb
- cmp al,0
- je $+4
- mov dx,di
-
- mov al,[bx+si] ; and the first quadrant
- stosb
- cmp al,0
- je $+4
- mov dx,di
-
- sub bx,5ah ; up one horizontal scan line (90 bytes)
- loop l2 ; (effectively 4 horizontal scan lines)
-
- cmp dx,0 ; completely blank vertical line?
- je l5 ; don't print, just advance paper
- push dx ; save length of line to print
- xor dx,dx ; for printer zero, again
- mov cx,10 ; count for left margin (ie, 10 spaces)
- l3: mov ax,' ' ; the print them
- int 17h
- loop l3
- mov ax,27 ; then print the graphics line
- int 17h
- mov ax,'L' ; ESC L introduction (double density)
- int 17h
- pop cx ; length of line to print
- shl cx,1 ; *2 since we print double for double density
- mov ax,cx
- xor ah,ah ; get least significant byte
- int 17h ; and send it
- xor ah,ah
- mov al,ch ; then get most significant byte
- int 17h ; and send it
- shr cx,1 ; then shift back down to real count
-
- push si ; save horizontal offset
- xor si,si ; point to save graphics line
- l4: lods byte ptr cs:0 ; get a character to print
- xor ah,ah
- push ax ; BUG: my clone BIOS' int 17 stomps on AL
- int 17h ; and print it
- pop ax ; restore due to my BIOS' bug
- int 17h ; print a second time for increased density
- loop l4 ; till end of line
- pop si ; and restore horizontal offset for next pass
-
- l5: mov ax,0dh ; now do a CRLF
- int 17h
- mov ax,0ah
- int 17h
-
- inc si ; move one space to the right
- cmp si,5ah ; already on right hand edge?
- jae l6 ; yes
- jmp l1 ; no, do another vertical pass
- l6:
-
- mov ax,27 ; set the printer back to 6lpi
- int 17h ; (even if it was at 8lpi)
- mov ax,'2'
- int 17h
- mov ax,12 ; really 12/72 of an inch
- int 17h
-
- done: mov ax,50h
- mov ds,ax
- mov byte ptr ds:0,0 ; prtsc is now over
-
- exit:
- pop es ; restore all registers
- pop ds
- pop bp
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
-
- iret ; and return to what user was doing
- SUBTTL Initial Entry Point (Setup)
- PAGE +
- ; This is the code executed the first time the program is invoked. It first
- ; builds a jump instruction at location 'tjump' that jumps to the BIOS print
- ; screen routine when the Hercules board is in text mode. Then it loads the
- ; print screen vector to point to the entry point and issues a terminate and
- ; stay resident call.
-
- init:
- mov ax,ds:2ch
- mov es,ax ; segment address of environment strings
- mov ah,49h ; deallocate our copy of environment strings
- int 21h
- mov ax,3505h ; get address for normal print screen
- int 21h
- mov ax,es
- mov word ptr tjump+103h,ax ; store segment address in jmp instr.
- mov word ptr tjump+101h,bx ; likewise with offset
-
- mov dx,offset int5+100h
- mov ax,2505h ; grab print screen interrupt vector
- int 21h
-
- mov dx,offset announce+100h
- mov ah,09h ; print announcement
- int 21h
- mov dx,offset init+100h ; lock program in memory
- int 27h
-
- announce:
- db 0dh,0ah,'HPrtSc - Graphics Screen Dump, Version 1.00',0dh,0ah
- db 'Copyright (c) 1987, Background Processes',0dh,0ah,'$'
-
- cseg ends
- end
-