;//******************************************************************************************* ; ; MHG ; ; Assembler for screen mode and sound blaster ; ; (C) 1990 MHG ; ; ModeX SetMode Written by Themie Gouthas, ; ; ;*******************************************************************************************/ GAP = 1 ;;64 .386 AC_INDEX equ 03c0h ;Attribute controller index register MISC_OUTPUT equ 03c2h ;Miscellaneous Output register SC_INDEX equ 03c4h ;Sequence Controller Index GC_INDEX equ 03ceh ; Graphics controller Index CRTC_INDEX equ 03d4h ;CRT Controller Index DAC_READ_INDEX equ 03c7h ; DAC_WRITE_INDEX equ 03c8h ; DAC_DATA equ 03c9h ; INPUT_STATUS_0 equ 03dah ;Input status 0 register SCREEN_SEG equ 0a000h ;segment of display memory in mode X MAP_MASK equ 02h ;index in SC of Map Mask register READ_MAP equ 04h ;index in GC of the Read Map register BIT_MASK equ 08h ;index in GC of Bit Mask register OVERFLOW equ 07h ; CRTC overflow register index MAX_SCAN_LINE equ 09h ; CRTC maximum scan line register index ADDR_HIGH equ 0ch ;Index of Start Address High reg in CRTC ADDR_LOW equ 0dh ; Low CRTC_OFFSET equ 13h ; CRTC offset register index UNDERLINE equ 14h ; CRTC underline location register index MODE_CONTROL equ 17h ; CRTC mode control register index LINE_COMPARE equ 18h ; CRTC line compare reg. index (bits 0-7 of ; split screen scan line AC_MODE_CONTROL equ 10h ; Index of Mode COntrol register in AC PEL_PANNING equ 13h ; Pel panning register index in AC PATTERN_BUFFER equ 0fffch ;offset in screen memory of pattern buffer TRUE equ 1 FALSE equ 0 OK equ 0 ERROR equ 1 _DATA SEGMENT BYTE PUBLIC USE32 'DATA' crttab dw 00d06h dw 03e07h dw 04109h dw 0ea10h dw 0ac11h dw 0df12h dw 00014h dw 0e715h dw 00616h dw 0e317h ;;//screenstart dd 0,06000h screenstart dd 0,08000h segptr dd 0 screen_no dw 0 XREZ = 320 YREZ = 240 X376Y282 label word db 0e7h db 18 dw 06e00h ; horz total dw 05d01h ; horz displayed dw 05e02h ; start horz blanking dw 09103h ; end horz blanking dw 06204h ; start h sync dw 08f05h ; end h sync dw 06206h ; vertical total dw 0f007h ; overflow dw 06109h ; cell height dw 0310fh ; dw 03710h ; v sync start dw 08911h ; v sync end and protect cr0-cr7 dw 03312h ; vertical displayed dw 02f13h ; offset dw 00014h ; turn off dword mode dw 03c15h ; v blank start dw 05c16h ; v blank end dw 0e317h ; turn on byte mode dw 376 dw 282 _DATA ENDS DGROUP GROUP _DATA pageinw macro a mov ah,a mov dx,03c4h mov al,2 out dx,ax endm bitmask macro a mov ah,a mov dx,03ceh mov al,8 out dx,al endm _TEXT SEGMENT BYTE PUBLIC USE32 'CODE' ASSUME cs:_TEXT,ds:_DATA public SetModeX_ public SwapModeX_ public CursorOff_ CursorOff_: pushad mov cx,0 mov bx,24+2 mov dl,cl mov dh,bl mov bl,0 mov ah,2h int 010h popad ret ;----------------------------------------------------------------------- ; Mode X graphics mode set with a virtual screen ; logical screen width. ; C near-callable as: ; ; int x_set_mode(unsigned int mode,unsigned int WidthInPixels); ; ; returns the actual width of the allocated virtual screen in pixels ; if a valid mode was selected otherwise returns -1 ; ; Saves virtual screen pixel width in _ScrnLogicalPixelWidth. ; Saves virtual screen byte width in _ScrnLogicalByteWidth. ; Physical screen dimensions are set in _ScrnPhysicalPixelWidth, ; _ScrnPhysicalByteWidth and _ScrnPhysicalHeight ; ; ; Modes: 0 = 320 x 200 (256 color) NOTE: Some of these modes require ; 1 = 320 x 240 (256 color) vertical size adjustment. ; 2 = 360 x 200 (256 color) ; 3 = 360 x 240 (256 color) ; 4 = 320 x 400 (256 color) ; 5 = 320 x 480 (256 color) ; 6 = 360 x 200 (256 color) ; 7 = 360 x 480 (256 color) ; 8 = 360 x 360 (256 color) ; 9 = 376 x 308 (256 color) ; 10 = 376 x 564 (256 color) ; ; Written by Themie Gouthas, ; parts adapted from M. Abrash code. ;------------------------------------------------------------------------ SetModeX_: pushad cld ;; call clear_vram mov ax,13h ; let the BIOS set standard 256-color int 10h ; mode (320x200 linear) mov dx,SC_INDEX mov ax,0604h out dx,ax ; disable chain4 mode mov ax,0100h out dx,ax ; synchronous reset while setting Misc ; Output for safety, even though clock ; unchanged lea esi,X376Y282 lodsb or al,al jz @@DontSetDot mov dx,MISC_OUTPUT out dx,al ; select the dot clock and Horiz ; scanning rate @@DontSetDot: mov dx,SC_INDEX mov ax,0300h out dx,ax ; undo reset (restart sequencer) mov dx,CRTC_INDEX ; reprogram the CRT Controller mov al,11h ; VSync End reg contains register write out dx,al ; protect bit inc dx ; CRT Controller Data register in al,dx ; get current VSync End register setting and al,07fh ; remove write protect on various out dx,al ; CRTC registers dec dx ; CRT Controller Index cld xor cx,cx lodsb mov cl,al @@SetCRTParmsLoop: lodsw ; get the next CRT Index/Data pair out dx,ax ; set the next CRT Index/Data pair loop @@SetCRTParmsLoop mov dx,SC_INDEX mov ax,0f02h out dx,ax ; enable writes to all four planes mov edi,0a0000h mov eax,0 mov ecx,65536 ; # of words in display memory rep stosb ; clear all of display memory popad ret SetModeX2_: pushad mov ax,013h int 010h bitmask 0ffh pageinw 01111b ;write to all planes push edi push ecx mov edi,0a0000h mov al,[edi] ;do a read/write to set bitmask mov [edi],al mov ecx,010000h ;clear 64k mov eax,0 rep stosb pop ecx pop edi mov dx,03c4h mov al,4 out dx,al inc dx in al,dx and al, not 08h or al,4 out dx,al mov dx,03ceh mov al,5 out dx,al inc dx in al,dx and al,not 010h out dx,al dec dx mov al,6 out dx,al in al,dx and al,not 02h out dx,al mov dx,03d4h mov al,014h out dx,al inc dx in al,dx and al,not 040h out dx,al dec dx mov al,017h out dx,al inc dx in al,dx or al,040h out dx,al mov dx,03d4h mov al,011h out dx,al inc dx in al,dx and al,07fh out dx,al dec dx mov ecx,10 lea esi,crttab @@loop33: lodsw out dx,ax loop @@loop33 ;reprog popad ret ; ; ; eax = address of 320*256 screen ; // expects a dummy 320*256 linear ; ; 378*256 SwapModeX_: push ebp mov ebp,esp pushad ;; mov eax,-4h[ebp] mov segptr,eax mov ebp,256 movzx ebx,screen_no xor ebx,1 mov screen_no,bx if 1 pageinw 1 mov esi,0 call syncplane pageinw 2 mov esi,1 call syncplane pageinw 4 mov esi,2 call syncplane pageinw 8 mov esi,3 call syncplane endif mov eax,screenstart[ebx*4] mov cx,ax mov dx,03d4h mov al,0ch mov ah,ch out dx,ax ;swap loop56r: mov dx,03dah ;make sure v trace is not occuring in al,dx test al,1000b jnz loop56r ; ; start address is loaded at the start of v trace ; so dont draw on the screen until v trace occurs ; loop44r: mov dx,03dah in al,dx ;wait for vertical retrace to occur test al,1000b jz loop44r popad pop ebp ret ; ; 376 = 94 * 4 = 47 *8 ; syncplane: mov edi,0a0000h movzx ecx,screen_no add edi,screenstart[ecx*4] add edi,7+13*94 add esi,segptr mov edx,ebp @@lp12: mov ecx,320 ;;320 shr ecx,4 ;/16 @@loop: mov al,[esi+8] ;pixel 4 mov ah,[esi+12] ;pixel 3 rol eax,16 mov al,[esi+0] ;pixel 2 mov ah,[esi+4] ;pixel 1 mov [edi],eax add edi,4 add esi,16 loop @@loop add edi,14 dec edx jne @@lp12 ret mov eax,0aaaaaaaah mov edx,ebp cmp edx,256 je @@okok @@lpp: mov ecx,320 shr ecx,4 ;/16 @@lpp2: mov [edi],eax add edi,4 loop @@lpp2 add edi,14 inc edx cmp edx,256 jb @@lpp @@okok: ret syncplane2: mov edi,0a0000h movzx ecx,screen_no add edi,screenstart[ecx*4] add esi,segptr mov ecx,XREZ imul ecx,YREZ shr ecx,4 ;/16 @@loop111: mov al,[esi+8] ;pixel 4 mov ah,[esi+12] ;pixel 3 rol eax,16 mov al,[esi+0] ;pixel 2 mov ah,[esi+4] ;pixel 1 mov [edi],eax add edi,4 add esi,16 loop @@loop111 ret _TEXT ENDS ;-------------------------------------------------------------------------------------------------------------------; ; ; ; ; ; 2 Jan 97 MHG message ; ; ; ; ; ;-------------------------------------------------------------------------------------------------------------------; DMA_CMD_REG = 008h DMA_MASK_REG = 00Ah DMA_MODE_REG = 00Bh DMA_FLIP_FLOP = 00Ch DMA_DISABLE = 00Dh DMA_MASK_CLR = 00Eh DMA_MEM_START = 2 DMA_PAGE_SELECT = 083h DMA_COUNT = 3 .386 inportb macro PORT mov dx,PORT in al,dx endm xinportb macro PORT mov dx,bp add dx,PORT in al,dx endm outportb macro PORT,VAL mov al,VAL mov dx,PORT out dx,al jmp $+2 jmp $+2 endm dspwrite macro VAL local @@lp @@lp: jmp $+2 mov dx,022Ch in al,dx test al,080h jnz @@lp mov al,VAL out dx,al endm xdspwrite macro VAL local @@lp @@lp: jmp $+2 mov dx,bp add dx,0Ch in al,dx test al,080h jnz @@lp mov al,VAL out dx,al endm ;/******************************************************************************************* ; ; ; SB Real Mode Interrupt routine ; ; 260 dac flip flop ; 261 page index ; 262;263 buffer offset (tail) ; 264;265 buffer offset (head) ; 266,267 SB address ; 268 Counter ; ;*******************************************************************************************/ TAIL_L = 264 TAIL_H = 265 HEAD_L = 262 HEAD_H = 263 _TEXT16 SEGMENT BYTE PUBLIC USE16 'CODE' ASSUME cs:_TEXT16 PUBLIC rm_sb_ rm_sb_: push ds push es push ax push bx push cx push dx push bp push si push di cli ;stop any interrupts cld mov ax,0 mov es,ax mov si,034h*4 mov ax,es:[si] mov bx,es:[si+2] rept 12 sal ax,1 rcl bx,1 endm mov es,bx rol ax,4 mov si,ax ;;//get address inc byte ptr es:[268+si] ;;counter mov bp,es:[si+266]; xinportb 00Eh ;clear sb dsp mov al,020h out 020h,al ;int control port mov bx,es:[HEAD_L+si] mov ax,es:[TAIL_L+si] sub ax,bx ;tail >head cmp ax,256 jl @@not_ready_yet ; ; move new memory into dma buffer ; push si push es mov al,es:[si+261] ;DMA 64K page index mov ah,0 sal ax,12 mov es,ax ;es now points to dma buffer add ax,01000h ;64K onwards mov ds,ax mov si,0 mov ch,GAP ;copy from storage buffer into play buffer mov cl,0 @@lp22: mov al,es:[bx] mov ds:[si],al inc si inc bx loop @@lp22 pop es pop si @@cco: mov es:[HEAD_L+si],bx @@miss: xdspwrite 014h ;;Start dma again xdspwrite 0ffh ;;DMA 256 bytes to the sound blaster !! xdspwrite GAP-1 pop di pop si pop bp pop dx pop cx pop bx pop ax pop es pop ds iret @@not_ready_yet: mov byte ptr es:[268+si],1 mov bx,es:[HEAD_L+si] ;get pointer to 64K sample buffer sub bx,es:[TAIL_L+si] ;subtract neg bx jz @@nogood mov dx,bx sal dx,8 mov di,0 mov bx,es:[HEAD_L+si] ;get pointer to 64K sample buffer push si push es mov al,es:[si+261] ;DMA 64K page index mov ah,0 sal ax,12 mov es,ax ;es now points to dma buffer add ax,01000h ;64K onwards mov ds,ax mov si,0 mov ch,GAP ;copy from storage buffer into play buffer mov cl,0 @@lp212: mov al,es:[bx] ;source buffer mov ds:[si],al add di,dx adc bx,0 inc si loop @@lp212 pop es pop si mov es:[HEAD_L+si],bx @@nogood: xdspwrite 014h ;;Start dma again xdspwrite 255 ;;DMA 256 bytes to the sound blaster !! xdspwrite 0 pop di pop si pop bp pop dx pop cx pop bx pop ax pop es pop ds iret _TEXT16 ENDS END