Metropoli BBS
VIEWER: modex.asm MODE: TEXT (ASCII)
; Tweaked VGA (modeX)
.data
modex_size dd 0  ;size of each plane (physical size in RAM)
modex_plane_wr db 1   ;current plane #  (if the plane # is altered in an
                      ; IRQ handler it must be returned to this plane #
                      ; before exiting IRQ handler)
modex_plane_rd db 1   ;current plane #  (if the plane # is altered in an
                      ; IRQ handler it must be returned to this plane #
                      ; before exiting IRQ handler)
mx_mode db 0   ;last successful modex_getmode()

vga_ADDR_HIGH     equ    0ch     ;Index of Start Address High reg in CRTC
vga_ADDR_LOW      equ    0dh     ;                       Low
vga_CRTC_OFFSET   equ    13h     ; CRTC offset register index
vga_MAP_MASK      equ    02h     ;index in SC of Map Mask register
vga_READ_MAP      equ    04h     ;index in GC of the Read Map register
vga_AC_INDEX        equ  03c0h   ;Attribute controller index register
vga_MISC_OUTPUT     equ  03c2h   ;Miscellaneous Output register
vga_SC_INDEX        equ  03c4h   ;Sequence Controller Index
vga_GC_INDEX        equ  03ceh   ;Graphics controller Index
vga_CRTC_INDEX      equ  03d4h   ;CRT Controller Index
vga_DAC_READ_INDEX  equ  03c7h   ; write color #
vga_DAC_WRITE_INDEX equ  03c8h   ; write color #
vga_DAC_DATA        equ  03c9h   ; write/read color #s (RGB)
vga_INPUT_STATUS_0  equ  03dah  ;Input status 0 register
vga_PEL_PANNING     equ    13h   ; Pel panning register index in AC

.data
;data for modes
vga_X320Y200 label  word
  db      0e3h    ; dot clock
  db      02      ; Number of CRTC Registers to update
  dw      00014h  ; turn off dword mode
  dw      0e317h  ; turn on byte mode
  dw      320     ; width
  dw      200     ; height

vga_X320Y240 label  word
  db      0e3h    ; dot clock
  db      10      ; Number of CRTC Registers to update
  dw      00d06h  ; vertical total
  dw      03e07h  ; overflow (bit 8 of vertical counts)
  dw      04109h  ; cell height (2 to double-scan)
  dw      0ea10h  ; v sync start
  dw      0ac11h  ; v sync end and protect cr0-cr7
  dw      0df12h  ; vertical displayed
  dw      00014h  ; turn off dword mode
  dw      0e715h  ; v blank start
  dw      00616h  ; v blank end
  dw      0e317h  ; turn on byte mode
  dw      320     ; width
  dw      240     ; height

vga_X360Y200 label  word
  db      0e7h    ; dot clock
  db      08      ; Number of CRTC Registers to update
  dw      06b00h  ; horz total
  dw      05901h  ; horz displayed
  dw      05a02h  ; start horz blanking
  dw      08e03h  ; end horz blanking
  dw      05e04h  ; start h sync
  dw      08a05h  ; end h sync
  dw      00014h  ; turn off dword mode
  dw      0e317h  ; turn on byte mode
  dw      360     ; width
  dw      200     ; height

vga_X360Y240  label word
  db      0e7h    ; dot clock
  db      17      ; Number of CRTC Registers to update
  dw  06b00h  ; horz total
  dw  05901h  ; horz displayed
  dw  05a02h  ; start horz blanking
  dw  08e03h  ; end horz blanking
  dw  05e04h  ; start h sync
  dw  08a05h  ; end h sync
  dw  00d06h  ; vertical total
  dw  03e07h  ; overflow (bit 8 of vertical counts)
  dw  04109h  ; cell height (2 to double-scan)
  dw  0ea10h  ; v sync start
  dw  0ac11h  ; v sync end and protect cr0-cr7
  dw  0df12h  ; vertical displayed
  dw  02d13h  ; offset;
  dw  00014h  ; turn off dword mode
  dw  0e715h  ; v blank start
  dw  00616h  ; v blank end
  dw  0e317h  ; turn on byte mode
  dw  360
  dw  240

vga_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  564

vga_X320Y400 label  word
  db  0e3h    ; dot clock
  db  03      ; Number of CRTC Registers to update
  dw  04009h  ; cell height
  dw  00014h  ; turn off dword mode
  dw  0e317h  ; turn on byte mode
  dw  320     ; width
  dw  400     ; height

vga_X320Y480 label  word
  db  0e3h    ; dotclock
  db  10      ; Number of CRTC Registers to update
  dw  00d06h  ; vertical total
  dw  03e07h  ; overflow (bit 8 of vertical counts)
  dw  04009h  ; cell height (2 to double-scan)
  dw  0ea10h  ; v sync start
  dw  0ac11h  ; v sync end and protect cr0-cr7
  dw  0df12h  ; vertical displayed
  dw  00014h  ; turn off dword mode
  dw  0e715h  ; v blank start
  dw  00616h  ; v blank end
  dw  0e317h  ; turn on byte mode
  dw  320     ; width
  dw  480     ; height

vga_X360Y400 label  word
  db      0e7h    ; dot clock
  db      09      ; Number of CRTC Registers to update
  dw      06b00h  ; horz total
  dw      05901h  ; horz displayed
  dw      05a02h  ; start horz blanking
  dw      08e03h  ; end horz blanking
  dw      05e04h  ; start h sync
  dw      08a05h  ; end h sync
  dw      04009h  ; cell height
  dw      00014h  ; turn off dword mode
  dw      0e317h  ; turn on byte mode
  dw      360     ; width
  dw      400     ; height

vga_X360Y480  label word
  db  0e7h
  db  17
  dw  06b00h  ; horz total
  dw  05901h  ; horz displayed
  dw  05a02h  ; start horz blanking
  dw  08e03h  ; end horz blanking
  dw  05e04h  ; start h sync
  dw  08a05h  ; end h sync
  dw  00d06h  ; vertical total
  dw  03e07h  ; overflow
  dw  04009h  ; cell height
  dw  0ea10h  ; v sync start
  dw  0ac11h  ; v sync end and protect cr0-cr7
  dw  0df12h  ; vertical displayed
  dw  02d13h  ; offset
  dw  00014h  ; turn off dword mode
  dw  0e715h  ; v blank start
  dw  00616h  ; v blank end
  dw  0e317h  ; turn on byte mode
  dw  360
  dw  480

vga_X360Y360  label word
  db  0e7h
  db  15
  dw  06b00h  ; horz total
  dw  05901h  ; horz displayed
  dw  05a02h  ; start horz blanking
  dw  08e03h  ; end horz blanking
  dw  05e04h  ; start h sync
  dw  08a05h  ; end h sync
  dw  04009h  ; cell height
  dw  08810h  ; v sync start
  dw  08511h  ; v sync end and protect cr0-cr7
  dw  06712h  ; vertical displayed
  dw  02d13h  ; offset
  dw  00014h  ; turn off dword mode
  dw  06d15h  ; v blank start
  dw  0ba16h  ; v blank end
  dw  0e317h  ; turn on byte mode
  dw  360
  dw  360

vga_X376Y308 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  00f07h  ; overflow
  dw  04009h  ;
  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  308

vga_X376Y564 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  06009h  ;
  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  564

vga_LAST_X_MODE  equ  11
vga_ModeTable label byte  ; Mode X tweak table   # pages
  dd      offset vga_X320Y200 ;mode # 0              4
  dd      offset vga_X320Y240 ;mode # 1              3
  dd      offset vga_X360Y200 ;mode # 2              2
  dd      offset vga_X360Y240 ;mode # 3              3
  dd      offset vga_X376Y282 ;mode # 4              2
  dd      offset vga_X320Y400 ;mode # 5              2
  dd      offset vga_X320Y480 ;mode # 6              1
  dd      offset vga_X360Y400 ;mode # 7              1
  dd      offset vga_X360Y480 ;mode # 8              1
  dd      offset vga_X360Y360 ;mode # 9              2  cool!
  dd      offset vga_X376Y308 ;mode # 10             2
  dd      offset vga_X376Y564 ;mode # 11             1
  dd 0  ;end of list

.code
modex_getmode proc private,x:word,y:word
  ;does NOT preserve regs
  mov esi,offset vga_ModeTable
  mov cl,0  ;Mode #
  mov bx,x
  mov dx,y
  mov getmode_bpsl,bx
  xor eax,eax
top:
  cmp [esi],dptr 0
  jz bad                   
  mov edi,[esi]            ; FIX : v2.06 Beta #2
  inc edi                  ;This whole x/y checker has been fixed
  mov al,[edi]             ;it twas not even closely working after these
  inc edi                  ;grafix libs have been modified greatly in v2.02
  shl al,1                 
  add edi,eax              
  cmp bx,[edi]
  jnz nomatch
  cmp dx,[edi+2]
  jnz nomatch
  mov mx_mode,cl
  xor eax,eax
  ret
nomatch:
  inc cl
  add esi,4
  jmp top
bad:
  mov eax,ERROR
  ret
modex_getmode endp

modex_setmode proc private
  cmp mx_mode,vga_LAST_X_MODE
  jbe @f
  mov eax,ERROR
  ret
@@:
  mov ax,13h              ; let the BIOS set standard 256-color
  int 10h                 ;  mode (320x200 linear)

  mov dx,vga_SC_INDEX
  mov ax,0604h
  out dx,ax                 ; enable chain4 mode (now non-linear)
  mov ax,0100h
  out dx,ax             ; synchronous reset while setting Misc
                        ;  Output for safety, even though clock
                        ;  unchanged

  movzx ecx,mx_mode
  mov ebx,offset vga_ModeTable
  shl ecx,2
  add ebx,ecx
  mov esi,[ebx]
  lodsb

  mov dx,vga_MISC_OUTPUT
  out dx,al               ; select the dot clock and Horiz

  mov dx,vga_SC_INDEX
  mov ax,0300h
  out dx,ax      ; undo reset (restart sequencer)
  
  mov dx,vga_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
  xor cx,cx
  lodsb
  mov cl,al

@@:
  lodsw               ; get the next CRT Index/Data pair
  out dx,ax           ; set the next CRT Index/Data pair
  loop @b
  
  mov dx,vga_SC_INDEX
  mov ax,0f02h
  out dx,ax             ; enable writes to all four planes
  
  ;set logical width to physical width
  mov dx,vga_CRTC_INDEX
  mov al,vga_CRTC_OFFSET
  out dx,al
  inc dx
  lodsw
  xor ebx,ebx
  mov bx,ax
  shr ax,3
  out dx,al  ;sets width (320,360, etc.)
  
;calculate modex_size for coping RAM to VRAM
  shr bx,2
  lodsw
  mov wptr[_v_y],ax
  xor dx,dx
  mul bx
  movzx eax,ax
  mov modex_size,eax  ;size of each plane

  xor ax,ax
  mov ecx,8000h
  mov edi,0a0000h
  rep stosw

  xor eax,eax
  ret   ;all done!
modex_setmode endp

modex_offset proc,off:word
  mov ax,off
  mov bh,al
  mov ch,ah
  mov bl,vga_ADDR_LOW
  mov cl,vga_ADDR_HIGH
  
  mov  dx,vga_INPUT_STATUS_0    ;Wait for trailing edge of Vsync pulse

@@:
  in al,dx
  test al,01h
  jnz @b
  mov dx,vga_CRTC_INDEX
  mov ax,bx
  out dx,ax    ;start address low
  mov ax,cx
  out dx,ax    ;start address high
; Now wait for vertical sync, so the other page will be invisible when
; we start drawing to it.
  call g_waitvsync
  ret
modex_offset endp


[ RETURN TO DIRECTORY ]