schmitz@uiucdcsb.UUCP (06/08/87)
I'm trying to implement hardware scrolling on a Paradise EGA card. By hardware scrolling I mean that the screen should "scroll" just by changing the Start Address High and Start Adress Low registers of the CRT controller chip. The problem is that don't know how to make the wraparound at the end of the video buffer function properly. When I leave the memory address generator in word mode, after the high bit becomes 1, it apparently starts accessing odd locations in bit plane 0. That's fine except when the processor access the video buffer in odd/even mode it writes the charater byte to an even location in bit plane 0, and the attribute byte to the corresponding location in bit plane 1. There is no way to fill in the odd addresses in bit plane 0. These odd addresses will be accessed by the memory address generator when it is looking for characters to write and the high bit in the memory address register is 1. The result is you get sixteen screenfuls (or so) of text, and then sixteen blank screenfuls until the wraparound. I'm using a 64K buffer because the memory address register is a sixteen bits wide, so you need that big a buffer to get the wraparound. For some perverse reason, I put it at A000. I do have a solution which works by changing to byte mode. But it is horribly inefficent! First you enable bit plane zero and write the ascii code. Then you enable bit plane 1 and write the attribute byte. This must be done for every character written. I would like to find a solution that will keep the processor mapping in odd/even mode so that the character and the attribute byte can be written with a single write. Below is a program that demonstrates the "bytewise" solution. It fills the video buffer with hexadecimal numbers. Each number has a value which is its offset from the start of the video buffer. That way you can always tell where you are in the buffer. When the program is running 'j' and 'k' scroll up and down by lines, and ' ' and '-' scroll up and down by screenfuls. Note that there are 32 screenfuls! I would be most grateful for help with this problem. +=============================================================================+ | Michael Schmitz University of Illinois Dept. of CS (217) 333-6680 | | | | arpa schmitz@b.cs.uiuc.edu | | csnet schmitz@uiuc.csnet | | usenet ihnp4!uiucdcs!schmitz | +=============================================================================+ ;=============================================================================== ; VID.ASM ;=============================================================================== .RADIX 16 INCLUDE vid.mac sseg segment stack db 256 dup(?) sseg ends dseg segment ; the data segment is not used tmp dw ? dseg ends vid_buf segment at 0A000 ; segment extends for 64K bytes vid_buf ends cseg segment assume cs:cseg, ds:dseg,es:vid_buf main proc far push ds sub ax,ax push ax mov ax,vid_buf mov es,ax mov ax,dseg mov ds,ax mov bx,0 G_misc 4 G_mode 0 C_mode 0E3 S_mode 7 ; S_mode 7 means that odd/even writes by the processor is ; disabled. The processor must call S_map to change the default ; write bit plane to 0 or 1. Bytes containing ascii values go ; to bit plane 0, while the corresponding attribute bytes go to ; bit plane 1. There must be a way to have this done ; automatically, without ruining the wraparound. mov cx, 2000 fill: mov al, 40 call pr_bx add bx, 4 mov al,60 call pr_bx add bx,4 loop fill scroll: mov ah, 7 int 21 cmp al, ' ' je scr_up cmp al, '-' je scr_dn cmp al, 'j' je ln_dn cmp al, 'k' je ln_up ; Only possibility left is to exit, after restoring all ; modified EGA registers to their original values. G_misc 0E G_mode 10 C_mode 0A3 C_sa 0, 0 S_mode 03 S_map 2 ret scr_up: add bx,780 jmp ld_ega scr_dn: sub bx,780 jmp ld_ega ln_up: add bx,50 jmp ld_ega ln_dn: sub bx,50 ld_ega: C_sa bl, bh jmp scroll main endp pr_bx proc near ; The value in bx is interpreted as four hexadecimal characters and then ; these characters are written to the regen buffer starting at location ; es:[bx]. Thus each word in the regen buffer gives its offset from the ; beginning of the regen buffer. The attribute byte to use is in al. ; All registers are preserved. push ax push si push cx push dx mov dx, ax mov cx, 0C mov si, 0 n_chr: mov ax, 0F shl ax, cl and ax, bx shr ax, cl cmp al, 9 ja lttr add al, 30 jmp prnt lttr: add al, 37 prnt: mov ah, dl ; The next four lines are the part that really need improvement. ; Only a byte can be written at a time, and in between those two ; writes the bit planes have to be changed. However, when I ; change to odd/even mapping of processor accesses into the ; regen buffer, I can't fix things up to get scrolling to ; wraparound the end of the regen buffer. S_map 0 mov es:[bx + si], al S_map 1 mov es:[bx + si], ah inc si sub cx, 4 cmp cx, 0 jge n_chr pop dx pop cx pop si pop ax ret pr_bx endp cseg ends end main ;=============================================================================== ; VID.MAC ;=============================================================================== C_sa MACRO low, high ;; set the start address high and start address low of the ;; CRTC chip push dx push ax mov dx, 3d4H mov al, 0dH mov ah, &low out dx, ax mov al, 0cH mov ah, &high out dx, ax pop ax pop dx ENDM G_misc MACRO pattern ;; Among other things the graphics miscellanous register controls the ;; chaining of odd maps to even, and the mapping of the regen buffer ;; into processor address space. The default is 0EH. push dx push ax mov ah, &pattern mov al, 06H mov dx, 3ceH out dx, ax pop ax pop dx ENDM G_mode MACRO pattern ;; Again, this has something to do with the chaining of odd maps ;; to even. Bit 4 of this register should be the same as memory ;; mode register bit 3 of the sequencer. The default value is 10H. push dx push ax mov ah, &pattern mov al, 05H mov dx, 3ceH out dx, ax pop ax pop dx ENDM C_mode MACRO pattern ;; This is the mode control register of the CRTC chip. The default ;; value is A3H. push dx push ax mov ah, &pattern mov al, 17H mov dx, 3d4H out dx, ax pop ax pop dx ENDM S_mode MACRO pattern ;; This is the mode control register of the Sequencer chip. The ;; default value is 03H. push dx push ax mov ah, &pattern mov al, 04H mov dx, 3c4H out dx, ax pop ax pop dx ENDM S_map MACRO plane ;; plane is 0 or 1. push dx push ax mov ah, &plane add ah, 1 mov al, 02H mov dx, 3c4H out dx, ax pop ax pop dx ENDM