From 141b7db85d90a3f200e6a67f6ead3839184bdc3e Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Thu, 25 Jun 2015 09:10:52 -0700 Subject: [PATCH] More VGA tests --- tests/pc/vga/L25-1.ASM | 230 +++++++++++++++++++++++++++++++++++++++++ tests/pc/vga/L25-2.ASM | 81 +++++++++++++++ tests/pc/vga/L25-3.ASM | 108 +++++++++++++++++++ tests/pc/vga/L25-4.ASM | 108 +++++++++++++++++++ tests/pc/vga/README.md | 9 +- 5 files changed, 534 insertions(+), 2 deletions(-) create mode 100644 tests/pc/vga/L25-1.ASM create mode 100644 tests/pc/vga/L25-2.ASM create mode 100644 tests/pc/vga/L25-3.ASM create mode 100644 tests/pc/vga/L25-4.ASM diff --git a/tests/pc/vga/L25-1.ASM b/tests/pc/vga/L25-1.ASM new file mode 100644 index 000000000..18f99d2ae --- /dev/null +++ b/tests/pc/vga/L25-1.ASM @@ -0,0 +1,230 @@ +; Program to illustrate operation of data rotate and bit mask +; features of Graphics Controller. Draws 8x8 character at +; specified location, using VGA's 8x8 ROM font. Designed +; for use with modes 0Dh, 0Eh, 0Fh, 10h, and 12h. +; By Michael Abrash. +; +stack segment para stack ‘STACK' + db 512 dup(?) +stack ends +; +VGA_VIDEO_SEGMENT equ 0a000h ;VGA display memory segment +SCREEN_WIDTH_IN_BYTES equ 044ah ;offset of BIOS variable +FONT_CHARACTER_SIZE equ 8 ;# bytes in each font char +; +; VGA register equates. +; +GC_INDEX equ 3ceh ;GC index register +GC_ROTATE equ 3 ;GC data rotate/logical function + ; register index +GC_BIT_MASK equ 8 ;GC bit mask register index +; +dseg segment para common ‘DATA' +TEST_TEXT_ROW equ 69 ;row to display test text at +TEST_TEXT_COL equ 17 ;column to display test text at +TEST_TEXT_WIDTH equ 8 ;width of a character in pixels + +TestString label byte + db ‘Hello, world!',0 ;test string to print. +FontPointer dd ? ;font offset +dseg ends +; +; Macro to set indexed register INDEX of GC chip to SETTING. +; +SETGC macro INDEX, SETTING + mov dx,GC_INDEX + mov ax,(SETTING SHL 8) OR INDEX + out dx,ax + endm +; +cseg segment para public ‘CODE' + assume cs:cseg, ds:dseg +start proc near + mov ax,dseg + mov ds,ax +; +; Select 640x480 graphics mode. +; + mov ax,012h + int 10h +; +; Set driver to use the 8x8 font. +; + mov ah,11h ;VGA BIOS character generator function, + mov al,30h ; return info subfunction + mov bh,3;get 8x8 font pointer + int 10h + call SelectFont +; +; Print the test string. +; + mov si,offset TestString + mov bx,TEST_TEXT_ROW + mov cx,TEST_TEXT_COL +StringOutLoop: + lodsb + and al,al + jz StringOutDone + call DrawChar + add cx,TEST_TEXT_WIDTH + jmp StringOutLoop +StringOutDone: +; +; Reset the data rotate and bit mask registers. +; + SETGC GC_ROTATE, 0 + SETGC GC_BIT_MASK, 0ffh +; +; Wait for a keystroke. +; + mov ah,1 + int 21h +; +; Return to text mode. +; + mov ax,03h + int 10h +; +; Exit to DOS. +; + mov ah,4ch + int 21h +Start endp +; +; Subroutine to draw a text character in a linear graphics mode +; (0Dh, 0Eh, 0Fh, 010h, 012h). +; Font used should be pointed to by FontPointer. +; +; Input: +; AL = character to draw +; BX = row to draw text character at +; CX = column to draw text character at +; +; Forces ALU function to "move". +; +DrawChar proc near + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds +; +; Set DS:SI to point to font and ES to point to display memory. +; + lds si,[FontPointer] ;point to font + mov dx,VGA_VIDEO_SEGMENT + mov es,dx ;point to display memory +; +; Calculate screen address of byte character starts in. +; + push ds ;point to BIOS data segment + sub dx,dx + mov ds,dx + xchg ax,bx + mov di,ds:[SCREEN_WIDTH_IN_BYTES] ;retrieve BIOS + ; screen width + pop ds + mul di ;calculate offset of start of row + push di ;set aside screen width + mov di,cx ;set aside the column + and cl,0111b ;keep only the column in-byte address + shr di,1 + shr di,1 + shr di,1 ;divide column by 8 to make a byte address + add di,ax ;and point to byte +; +; Calculate font address of character. +; + sub bh,bh + shl bx,1 ;assumes 8 bytes per character; use + shl bx,1 ; a multiply otherwise + shl bx,1 ;offset in font of character + add si,bx ;offset in font segment of character +; +; Set up the GC rotation. +; + mov dx,GC_INDEX + mov al,GC_ROTATE + mov ah,cl + out dx,ax +; +; Set up BH as bit mask for left half, +; BL as rotation for right half. +; + mov bx,0ffffh + shr bh,cl + neg cl + add cl,8 + shl bl,cl +; +; Draw the character, left half first, then right half in the +; succeeding byte, using the data rotation to position the character +; across the byte boundary and then using the bit mask to get the +; proper portion of the character into each byte. +; Does not check for case where character is byte-aligned and +; no rotation and only one write is required. +; + mov bp,FONT_CHARACTER_SIZE + mov dx,GC_INDEX + pop cx ;get back screen width + dec cx + dec cx ; -2 because do two bytes for each char +CharacterLoop: +; +; Set the bit mask for the left half of the character. +; + mov al,GC_BIT_MASK + mov ah,bh + out dx,ax +; +; Get the next character byte & write it to display memory. +; (Left half of character.) +; + mov al,[si] ;get character byte + mov ah,es:[di] ;load latches + stosb ;write character byte +; +; Set the bit mask for the right half of the character. +; + mov al,GC_BIT_MASK + mov ah,bl + out dx,ax +; +; Get the character byte again & write it to display memory. +; (Right half of character.) +; + lodsb ;get character byte + mov ah,es:[di] ;load latches + stosb ;write character byte +; +; Point to next line of character in display memory. +; + add di,cx +; + dec bp + jnz CharacterLoop +; + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + ret +DrawChar endp +; +; Set the pointer to the font to draw from to ES:BP. +; +SelectFont proc near + mov word ptr [FontPointer],bp ;save pointer + mov word ptr [FontPointer+2],es + ret +SelectFont endp +; +cseg ends + end start diff --git a/tests/pc/vga/L25-2.ASM b/tests/pc/vga/L25-2.ASM new file mode 100644 index 000000000..9710be530 --- /dev/null +++ b/tests/pc/vga/L25-2.ASM @@ -0,0 +1,81 @@ +; Program to illustrate operation of Map Mask register when drawing +; to memory that already contains data. +; By Michael Abrash. +; +stack segment para stack ‘STACK' + db 512 dup(?) +stack ends +; +EGA_VIDEO_SEGMENT equ 0a000h ;EGA display memory segment +; +; EGA register equates. +; +SC_INDEX equ 3c4h ;SC index register +SC_MAP_MASK equ 2 ;SC map mask register +; +; Macro to set indexed register INDEX of SC chip to SETTING. +; +SETSC macro INDEX, SETTING + mov dx,SC_INDEX + mov al,INDEX + out dx,al + inc dx + mov al,SETTING + out dx,al + dec dx + endm +; +cseg segment para public ‘CODE#146; + assume cs:cseg +start proc near +; +; Select 640x480 graphics mode. +; + mov ax,012h + int 10h +; + mov ax,EGA_VIDEO_SEGMENT + mov es,ax ;point to video memory +; +; Draw 24 10-scan-line high horizontal bars in green, 10 scan lines apart. +; + SETSC SC_MAP_MASK,02h ;map mask setting enables only + ; plane 1, the green plane + sub di,di ;start at beginning of video memory + mov al,0ffh + mov bp,24 ;# bars to draw +HorzBarLoop: + mov cx,80*10 ;# bytes per horizontal bar + rep stosb ;draw bar + add di,80*10 ;point to start of next bar + dec bp + jnz HorzBarLoop +; +; Fill screen with blue, using Map Mask register to enable writes +; to blue plane only. +; + SETSC SC_MAP_MASK,01h ;map mask setting enables only + ; plane 0, the blue plane + sub di,di + mov cx,80*480 ;# bytes per screen + mov al,0ffh + rep stosb ;perform fill (affects only + ; plane 0, the blue plane) +; +; Wait for a keystroke. +; + mov ah,1 + int 21h +; +; Restore text mode. +; + mov ax,03h + int 10h +; +; Exit to DOS. +; + mov ah,4ch + int 21h +start endp +cseg ends + end start diff --git a/tests/pc/vga/L25-3.ASM b/tests/pc/vga/L25-3.ASM new file mode 100644 index 000000000..5dbfaf112 --- /dev/null +++ b/tests/pc/vga/L25-3.ASM @@ -0,0 +1,108 @@ +; Program to illustrate operation of set/reset circuitry to force +; setting of memory that already contains data. +; By Michael Abrash. +; +stack segment para stack ‘STACK#146; + db 512 dup(?) +stack ends +; +EGA_VIDEO_SEGMENT equ 0a000h ;EGA display memory segment +; +; EGA register equates. +; +SC_INDEX equ 3c4h ;SC index register +SC_MAP_MASK equ 2 ;SC map mask register +GC_INDEX equ 3ceh ;GC index register +GC_SET_RESET equ 0 ;GC set/reset register +GC_ENABLE_SET_RESET equ 1 ;GC enable set/reset register +; +; Macro to set indexed register INDEX of SC chip to SETTING. +; +SETSC macro INDEX, SETTING + mov dx,SC_INDEX + mov al,INDEX + out dx,al + inc dx + mov al,SETTING + out dx,al + dec dx + endm +; +; Macro to set indexed register INDEX of GC chip to SETTING. +; +SETGC macro INDEX, SETTING + mov dx,GC_INDEX + mov al,INDEX + out dx,al + inc dx + mov al,SETTING + out dx,al + dec dx + endm +; +cseg segment para public ‘CODE#146; + assume cs:cseg +start proc near +; +; Select 640x480 graphics mode. +; + mov ax,012h + int 10h +; + mov ax,EGA_VIDEO_SEGMENT + mov es,ax ;point to video memory +; +; Draw 24 10-scan-line high horizontal bars in green, 10 scan lines apart. +; + SETSC SC_MAP_MASK,02h ;map mask setting enables only + ; plane 1, the green plane + sub di,di ;start at beginning of video memory + mov al,0ffh + mov bp,24 ;# bars to draw +HorzBarLoop: + mov cx,80*10 ;# bytes per horizontal bar + rep stosb ;draw bar + add di,80*10 ;point to start of next bar + dec bp + jnz HorzBarLoop +; +; Fill screen with blue, using set/reset to force plane 0 to 1#146;s and all +; other plane to 0#146;s. +; + SETSC SC_MAP_MASK,0fh ;must set map mask to enable all + ; planes, so set/reset values can + ; be written to memory + SETGC GC_ENABLE_SET_RESET,0fh ;CPU data to all planes will be + ; replaced by set/reset value + SETGC GC_SET_RESET,01h ;set/reset value is 0ffh for plane 0 + ; (the blue plane) and 0 for other + ; planes + sub di,di + mov cx,80*480 ;# bytes per screen + mov al,0ffh ;since set/reset is enabled for all + ; planes, the CPU data is ignored- + ; only the act of writing is + ; important + rep stosb ;perform fill (affects all planes) +; +; Turn off set/reset. +; + SETGC GC_ENABLE_SET_RESET,0 +; +; Wait for a keystroke. +; + mov ah,1 + int 21h +; +; Restore text mode. +; + mov ax,03h + int 10h +; +; Exit to DOS. +; + mov ah,4ch + int 21h +start endp +cseg ends + end start diff --git a/tests/pc/vga/L25-4.ASM b/tests/pc/vga/L25-4.ASM new file mode 100644 index 000000000..ffda0fa72 --- /dev/null +++ b/tests/pc/vga/L25-4.ASM @@ -0,0 +1,108 @@ +; Program to illustrate operation of set/reset circuitry in conjunction +; with CPU data to modify setting of memory that already contains data. +; By Michael Abrash. +; +stack segment para stack ‘STACK#146; + db 512 dup(?) +stack ends +; +EGA_VIDEO_SEGMENT equ 0a000h ;EGA display memory segment +; +; EGA register equates. +; +SC_INDEX equ 3c4h ;SC index register +SC_MAP_MASK equ 2 ;SC map mask register +GC_INDEX equ 3ceh ;GC index register +GC_SET_RESET equ 0 ;GC set/reset register +GC_ENABLE_SET_RESET equ 1 ;GC enable set/reset register +; +; Macro to set indexed register INDEX of SC chip to SETTING. +; +SETSC macro INDEX, SETTING + mov dx,SC_INDEX + mov al,INDEX + out dx,al + inc dx + mov al,SETTING + out dx,al + dec dx + endm +; +; Macro to set indexed register INDEX of GC chip to SETTING. +; +SETGC macro INDEX, SETTING + mov dx,GC_INDEX + mov al,INDEX + out dx,al + inc dx + mov al,SETTING + out dx,al + dec dx + endm +; +cseg segment para public ‘CODE#146; + assume cs:cseg +start proc near +; +; Select 640x350 graphics mode. +; + mov ax,010h + int 10h +; + mov ax,EGA_VIDEO_SEGMENT + mov es,ax ;point to video memory +; +; Draw 18 10-scan-line high horizontal bars in green, 10 scan lines apart. +; + SETSC SC_MAP_MASK,02h;map mask setting enables only +; plane 1, the green plane + sub di,di;start at beginning of video memory + mov al,0ffh + mov bp,18;# bars to draw +HorzBarLoop: + mov cx,80*10;# bytes per horizontal bar + rep stosb;draw bar + add di,80*10;point to start of next bar + dec bp + jnz HorzBarLoop +; +; Fill screen with alternating bars of red and brown, using CPU data +; to set plane 1 and set/reset to set planes 0, 2 & 3. +; + SETSC SC_MAP_MASK,0fh ;must set map mask to enable all + ; planes, so set/reset values can + ; be written to planes 0, 2 & 3 + ; and CPU data can be written to + ; plane 1 (the green plane) + SETGC GC_ENABLE_SET_RESET,0dh ;CPU data to planes 0, 2 & 3 will be + ; replaced by set/reset value + SETGC GC_SET_RESET,04h ;set/reset value is 0ffh for plane 2 + ; (the red plane) and 0 for other + ; planes + sub di,di + mov cx,80*350/2 ;# words per screen + mov ax,07e0h ;CPU data controls only plane 1; + ; set/reset controls other planes + rep stosw ;perform fill (affects all planes) +; +; Turn off set/reset. +; + SETGC GC_ENABLE_SET_RESET,0 +; +; Wait for a keystroke. +; + mov ah,1 + int 21h +; +; Restore text mode. +; + mov ax,03h + int 10h +; +; Exit to DOS. +; + mov ah,4ch + int 21h +start endp +cseg ends + end start diff --git a/tests/pc/vga/README.md b/tests/pc/vga/README.md index 1093d0fc1..e6dc90d03 100644 --- a/tests/pc/vga/README.md +++ b/tests/pc/vga/README.md @@ -26,9 +26,14 @@ Development of PCjs VGA support has just begun (June 2015), so don't expect *any List of VGA Samples from [Michael Abrash's Graphics Programming Black Book](https://github.com/jeffpar/abrash-black-book): * [Chapter 23](https://github.com/jeffpar/abrash-black-book/blob/master/src/chapter-23.md) - * [L23-1.ASM](L23-1.ASM) + * [L23-1.ASM: Animates four balls bouncing around a playfield by using page flipping and panning](L23-1.ASM) * [Chapter 24](https://github.com/jeffpar/abrash-black-book/blob/master/src/chapter-24.md) - * [L24-1.ASM](L24-1.ASM) + * [L24-1.ASM: Illustrates operation of ALUs and latches of the VGA's Graphics Controller](L24-1.ASM) + * [Chapter 25](https://github.com/jeffpar/abrash-black-book/blob/master/src/chapter-25.md) + * [L25-1.ASM: Illustrates operation of data rotate and bit mask features of Graphics Controller](L25-1.ASM) + * [L25-2.ASM: Illustrates operation of Map Mask register when drawing to memory that already contains data](L25-2.ASM) + * [L25-3.ASM: Illustrates operation of set/reset circuitry to force setting of memory that already contains data](L25-3.ASM) + * [L25-4.ASM: Illustrates operation of set/reset circuitry in conjunction with CPU data](L25-4.ASM) ---