| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748 |
- ;
- ; Command & Conquer Red Alert(tm)
- ; Copyright 2025 Electronic Arts Inc.
- ;
- ; This program is free software: you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, either version 3 of the License, or
- ; (at your option) any later version.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program. If not, see <http://www.gnu.org/licenses/>.
- ;
- ;****************************************************************************
- ;*
- ;* C O N F I D E N T I A L -- W E S T W O O D S T U D I O S
- ;*
- ;*---------------------------------------------------------------------------
- ;*
- ;* FILE
- ;* xmode.asm
- ;*
- ;* DESCRIPTION
- ;* Xmode graphics display routines. (32-Bit protected mode)
- ;*
- ;* PROGRAMMER
- ;* Bill Randolph
- ;* Denzil E. Long, Jr.
- ;*
- ;* DATE
- ;* Febuary 3, 1995
- ;*
- ;*---------------------------------------------------------------------------
- ;*
- ;* PUBLIC
- ;* SetXMode - Set the specified Xmode video mode.
- ;* ClearXMode - Clear the XMode VRAM.
- ;* ShowXPage - Set a specific page for XMode display.
- ;* Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.
- ;* Xmode_Blit - Bit blit a block to the XMode display.
- ;*
- ;****************************************************************************
- IDEAL
- P386
- MODEL USE32 FLAT
- LOCALS ??
- INCLUDE "vga.i"
- INCLUDE "video.i"
- CODESEG
- ;****************************************************************************
- ;*
- ;* NAME
- ;* SetXMode - Set the specified Xmode video mode.
- ;*
- ;* SYNOPSIS
- ;* Error = SetXMode(Mode)
- ;*
- ;* long SetXMode(long);
- ;*
- ;* FUNCTION
- ;* This routines set the current display adapter to the specified Xmode.
- ;* Portions of this routine were take from Dr. Dobb's, written in C, and
- ;* portions were taken from Dominic's 320x200 code.
- ;*
- ;* INPUTS
- ;* Mode - Xmode mode to set display to.
- ;*
- ;* RESULT
- ;* Error - 0 if successful, or -1 if error.
- ;*
- ;****************************************************************************
- GLOBAL C SetXMode:NEAR
- PROC SetXMode C NEAR USES edx
- ARG mode:DWORD
- ??Set320x200:
- cmp [mode],XMODE_320X200 ;320x200?
- jne ??Set320x240
- IF 0
- mov eax,MCGA
- int 10h
- ; Memory Mode:
- ; bit3 (chain) = 0 (planes are accessed via Map Mask)
- ; bit2 (odd/even) = 1 (use sequential addressing mode)
- INPORT R_SEQUENCER,SEQ_MEMORY_MODE
- and al,not 08h ;Turn off chain 4
- or al,04h ;Turn off odd/even
- out dx,al
- INPORT R_GRAPHICS_CONTROLLER,GC_MODE
- and al,not 10h ;Turn off odd/even
- out dx,al
- INPORT R_GRAPHICS_CONTROLLER,GC_MISC
- and al,not 02h ;Turn off chain
- out dx,al
- OUTPORT R_SEQUENCER,SEQ_MAP_MASK,0Fh
- INPORT R_CRT_CONTROLLER, CRT_MAX_SCANLINE
- and al,not 1fh ;Clear low 5 bits
- or al,1 ;Mode = 0 => 400 lines
- out dx,al ;Mode =1 => 200
- INPORT R_CRT_CONTROLLER,CRT_UNDERLINE
- and al,not 40h ;Turn off doubleword
- out dx,al
- INPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL
- or al,40h ;Turn on byte mode bit,
- out dx,al ; so mem scanned linearly
- ENDIF
- ; The following section of code is from Roger Stevens' XMode
- ; example code; it's the same as 320x400, except the value sent
- ; to CRT_MAX_SCANLINE is 41, not 40.
- mov eax,MCGA
- int 10h
- OUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h
- INPORT R_CRT_CONTROLLER,CRT_VERTRET_END
- and al,07Fh
- out dx,al
- OUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,41h
- OUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h
- OUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h
- mov eax,0
- jmp ??Done
- ??Set320x240:
- cmp [mode],XMODE_320X240 ;320x240?
- jne ??Set320x400
- ; Start by setting MCGA to let the BIOS program the registers;
- ; then, reprogram the registers that need it.
- mov eax,MCGA
- int 10h
- ; Memory Mode:
- ; bit3 (chain) = 0 (planes are accessed via Map Mask)
- ; bit2 (odd/even) = 1 (use sequential addressing mode)
- ; bit1 (extended mem) = 1 (>64K video RAM)
- ; bit0 (alpha/graph) = 0 (graphics mode)
- OUTPORT R_SEQUENCER,SEQ_MEMORY_MODE,06h
- ; Issue a Sequencer Reset
- OUTPORT R_SEQUENCER,SEQ_RESET,01h
- ; Misc Output: (set to 1100 0011)
- ; Bit 7: VSync polarity (1=negative)
- ; Bit 6: HSync polarity (1=negative)
- ; Bit 5: page bit for odd/even (0=low 64K)
- ; Bit 4: Video drivers (0=enable)
- ; Bit 3,2: clock select (0=25-MHz clock)
- ; Bit 1: VRAM access (1 = enable CPU to access)
- ; Bit 0: I/O Address (1=color emulation)
- mov edx,R_MISC_OUTPUT
- mov al,0C3h
- out dx,al
- ; Clear Sequencer Reset
- OUTPORT R_SEQUENCER,SEQ_RESET,03h
- ; Read Vertical Retrace End, and with 07f to clear high bit
- ; (clearing bit 7 enables writing to registers 0-7)
- INPORT R_CRT_CONTROLLER,CRT_VERTRET_END
- and al,07Fh
- out dx,al
- ; Program the CRT Controller to display 480 scanlines, but to
- ; double each scanline so only 240 are displayed:
- OUTPORT R_CRT_CONTROLLER,CRT_UNDERLINE,00h
- OUTPORT R_CRT_CONTROLLER,CRT_MODE_CONTROL,0E3h
- OUTPORT R_CRT_CONTROLLER,CRT_VERT_TOTAL,0Dh
- OUTPORT R_CRT_CONTROLLER,CRT_OVERFLOW,03Eh
- OUTPORT R_CRT_CONTROLLER,CRT_VERTRET_START,0EAh
- OUTPORT R_CRT_CONTROLLER,CRT_VERTRET_END,0ACh
- OUTPORT R_CRT_CONTROLLER,CRT_VERTDISP_END,0DFh
- OUTPORT R_CRT_CONTROLLER,CRT_START_VB,0E7h
- OUTPORT R_CRT_CONTROLLER,CRT_END_VB,06h
- OUTPORT R_CRT_CONTROLLER,CRT_MAX_SCANLINE,041h
- xor eax,eax
- jmp ??Done
- ??Set320x400:
- cmp [mode],XMODE_320X400 ;320x400
- jne ??Set320x480
- mov eax,MCGA
- int 10h
- OUTPORT R_SEQUENCER,04h,06h
- INPORT R_CRT_CONTROLLER,011h
- and al,07Fh
- out dx,al
- OUTPORT R_CRT_CONTROLLER,09h,40h
- OUTPORT R_CRT_CONTROLLER,014h,00h
- OUTPORT R_CRT_CONTROLLER,017h,0E3h
- xor eax,eax
- jmp ??Done
- ??Set320x480:
- cmp [mode],XMODE_320X480 ;320x480?
- jne ??Set360x400
- mov eax,MCGA
- int 10h
- mov edx,R_SEQUENCER
- mov eax,0604h
- out dx,ax
- mov eax,0100h
- out dx,ax
- mov edx,R_MISC_OUTPUT
- mov al,0C3h
- out dx,al
- mov edx,R_SEQUENCER
- mov eax,0300h
- out dx,ax
- mov edx,R_CRT_CONTROLLER
- mov al,011h
- out dx,al
- mov edx,03D5h
- in al,dx
- and al,07Fh
- out dx,al
- mov edx,R_CRT_CONTROLLER
- mov eax,04009h
- out dx,ax
- mov eax,00014h
- out dx,ax
- mov eax,0E317h
- out dx,ax
- mov eax,00D06h
- out dx,ax
- mov eax,03E07h
- out dx,ax
- mov eax,0EA10h
- out dx,ax
- mov eax,0AC11h
- out dx,ax
- mov eax,0DF12h
- out dx,ax
- mov eax,0E715h
- out dx,ax
- mov eax,00616h
- out dx,ax
- mov eax,04009h
- out dx,ax
- xor eax,eax
- jmp ??Done
- ??Set360x400:
- cmp [mode],XMODE_360X400 ;360x400
- jne ??Set360x480
- mov eax,MCGA
- int 10h
- mov edx,R_SEQUENCER
- mov eax,0604h
- out dx,ax
- mov eax,0100h
- out dx,ax
- mov edx,R_MISC_OUTPUT
- mov al,067h
- out dx,al
- mov edx,R_SEQUENCER
- mov eax,0300h
- out dx,ax
- mov edx,R_CRT_CONTROLLER
- mov al,011h
- out dx,al
- mov edx,03D5h
- in al,dx
- and al,07Fh
- out dx,al
- mov edx,R_CRT_CONTROLLER
- mov eax,06B00h
- out dx,ax
- mov eax,05901h
- out dx,ax
- mov eax,05A02h
- out dx,ax
- mov eax,08E03h
- out dx,ax
- mov eax,05E04h
- out dx,ax
- mov eax,08A05h
- out dx,ax
- mov eax,04009
- out dx,ax
- mov eax,00014h
- out dx,ax
- mov eax,0E317h
- out dx,ax
- mov eax,02D13h
- out dx,ax
- xor eax,eax
- jmp ??Done
- ??Set360x480:
- cmp [mode],XMODE_360X480 ;360x480?
- jne ??Unknown_mode
- mov eax,MCGA
- int 10h
- mov edx,R_SEQUENCER
- mov eax,0604h
- out dx,ax
- mov eax,0100h
- out dx,ax
- mov edx,R_MISC_OUTPUT
- mov al,0E7h
- out dx,al
- mov edx,R_SEQUENCER
- mov eax,0300h
- out dx,ax
- mov edx,R_CRT_CONTROLLER
- mov al,011h
- out dx,al
- mov edx,03D5h
- in al,dx
- and al,07Fh
- out dx,al
- mov edx,R_CRT_CONTROLLER
- mov eax,06B00h
- out dx,ax
- mov eax,05901h
- out dx,ax
- mov eax,05A02h
- out dx,ax
- mov eax,08E03h
- out dx,ax
- mov eax,05E04h
- out dx,ax
- mov eax,08A05h
- out dx,ax
- mov eax,04009h
- out dx,ax
- mov eax,00014h
- out dx,ax
- mov eax,0E317h
- out dx,ax
- mov eax,00D06h
- out dx,ax
- mov eax,03E07h
- out dx,ax
- mov eax,0EA10h
- out dx,ax
- mov eax,0AC11h
- out dx,ax
- mov eax,0DF12h
- out dx,ax
- mov eax,0E715h
- out dx,ax
- mov eax,00616h
- out dx,ax
- mov eax,02D13h
- out dx,ax
- xor eax,eax
- jmp ??Done
- ??Unknown_mode:
- mov eax,0FFFFFFFFh ;Unknown mode
- ??Done:
- ret
- ENDP SetXMode
- ;****************************************************************************
- ;*
- ;* NAME
- ;* ClearXMode - Clear the XMode VRAM.
- ;*
- ;* SYNOPSIS
- ;* ClearXMode()
- ;*
- ;* void ClearXMode(void);
- ;*
- ;* FUNCTION
- ;*
- ;* INPUTS
- ;* NONE
- ;*
- ;* RESULT
- ;* NONE
- ;*
- ;****************************************************************************
- GLOBAL C ClearXMode:NEAR
- PROC ClearXMode C NEAR USES eax ecx edi es
- IF PHARLAP_TNT
- mov eax,01Ch
- mov es,ax ;Set ES selector to VRAM
- mov edi,0
- ELSE
- mov edi,0A0000h
- ENDIF
- SET_PLANE 0Fh
- mov ecx,((320*240*2)/4/4)
- xor eax,eax
- rep stosd
- ret
- ENDP ClearXMode
- ;****************************************************************************
- ;*
- ;* NAME
- ;* ShowXPage - Set a specific page for XMode display.
- ;*
- ;* SYNOPSIS
- ;* ShowXPage(Offset)
- ;*
- ;* void ShowXPage();
- ;*
- ;* FUNCTION
- ;* Show the page at the specified offset in the bitmap. Page-flip takes
- ;* effect on the next active scan cycle.
- ;*
- ;* INPUTS
- ;* Offset - Offset to set page to.
- ;*
- ;* RESULT
- ;* NONE
- ;*
- ;****************************************************************************
- GLOBAL C ShowXPage:NEAR
- PROC ShowXPage C NEAR USES eax ebx ecx edx
- ARG StartOffset:DWORD
- mov edx,R_CRT_CONTROLLER
- mov bl,CRT_STARTADDR_LOW
- mov bh,[byte ptr StartOffset]
- mov cl,CRT_STARTADDR_HIGH
- mov ch,[byte ptr StartOffset+1]
- mov eax,ebx
- out dx,ax
- mov eax,ecx
- out dx,ax
- ret
- ENDP ShowXPage
- ;****************************************************************************
- ;*
- ;* NAME
- ;* Xmode_BufferCopy_320x200 - Copy 320x200 buffer to Xmode VRAM.
- ;*
- ;* SYNOPSIS
- ;* Xmode_BufferCopy_320x200(Buffer, Screen)
- ;*
- ;* void Xmode_BufferCopy_320x200(char *, char *);
- ;*
- ;* FUNCTION
- ;* BitBlt copy to VRAM.
- ;*
- ;* INPUTS
- ;* Buffer - Pointer to buffer to copy to XMode VRAM.
- ;* Screen - XMode VRAM screen address to copy buffer to.
- ;*
- ;* RESULT
- ;* NONE
- ;*
- ;****************************************************************************
- GLOBAL C Xmode_BufferCopy_320x200:NEAR
- PROC Xmode_BufferCopy_320x200 C NEAR USES eax ecx edx edi esi es
- ARG buffer:NEAR PTR
- ARG screen:NEAR PTR
- LOCAL save_esi:DWORD
- LOCAL save_edi:DWORD
- ;----------------------------------------------------------------------------
- ; Initialize
- ;----------------------------------------------------------------------------
-
- IF PHARLAP_TNT
- mov eax,01Ch ;Set ES selector to VRAM.
- mov es,ax
- ENDIF
- mov esi,[buffer] ;Set pointers
- mov edi,[screen]
- mov [save_esi],esi
- mov [save_edi],edi
- ;----------------------------------------------------------------------------
- ; Copy plane 1
- ;----------------------------------------------------------------------------
- SET_PLANE XPLANE_1
- mov ecx,4000
- x_loop_1:
- mov al,[esi + 8] ;Get pixel
- mov ah,[esi + 12] ;Get pixel
- ror eax,16
- mov al,[esi] ;Get pixel
- mov ah,[esi + 4] ;Get pixel
- mov [es:edi],eax ;Write plane 1 pixels to VRAM
- add esi,16 ;Next source pixel position
- add edi,4 ;Next VRAM position
- dec ecx
- jnz short x_loop_1
- ;----------------------------------------------------------------------------
- ; Copy plane 2
- ;----------------------------------------------------------------------------
- mov esi,[save_esi] ;Restore pointers
- mov edi,[save_edi]
- inc esi ;Adjust source pointer to plane 2
- SET_PLANE XPLANE_2
- mov ecx,4000
- x_loop_2:
- mov al,[esi + 8] ;Get pixel
- mov ah,[esi + 12] ;Get pixel
- ror eax,16
- mov al,[esi] ;Get pixel
- mov ah,[esi + 4] ;Get pixel
- mov [es:edi],eax ;Write plane 2 pixels to VRAM
- add esi,16 ;Next source pixel position
- add edi,4 ;Next VRAM position
- dec ecx
- jnz short x_loop_2
- ;----------------------------------------------------------------------------
- ; Copy plane 3
- ;----------------------------------------------------------------------------
- mov esi,[save_esi] ;Restore pointers
- mov edi,[save_edi]
- add esi,2 ;Adjust source pointer to plane 3
- SET_PLANE XPLANE_3
- mov ecx,4000
- x_loop_3:
- mov al,[esi + 8] ;Get pixel
- mov ah,[esi + 12] ;Get pixel
- ror eax,16
- mov al,[esi] ;Get pixel
- mov ah,[esi + 4] ;Get pixel
- mov [es:edi],eax ;Write plane 3 pixels to VRAM
- add esi,16 ;Next source pixel position
- add edi,4 ;Next VRAM position
- dec ecx
- jnz short x_loop_3
- ;----------------------------------------------------------------------------
- ; Copy plane 4
- ;----------------------------------------------------------------------------
- mov esi,[save_esi] ;Restore pointers
- mov edi,[save_edi]
- add esi,3 ;Adjust source pointer to plane 4
- SET_PLANE XPLANE_4
- mov ecx,4000
- x_loop_4:
- mov al,[esi + 8] ;Get pixel
- mov ah,[esi + 12] ;Get pixel
- ror eax,16
- mov al,[esi] ;Get pixel
- mov ah,[esi + 4] ;Get pixel
- mov [es:edi],eax ;Write plane 4 pixels to VRAM
- add esi,16 ;Next source pixel position
- add edi,4 ;Next screen position
- dec ecx
- jnz short x_loop_4
- ret
- ENDP Xmode_BufferCopy_320x200
- ;****************************************************************************
- ;*
- ;* NAME
- ;* Xmode_Blit - Bit blit a block to the XMode display.
- ;*
- ;* SYNOPSIS
- ;* XMode_Blit(Buffer, Screen, Width, Height)
- ;*
- ;* void XMode_Blit(char *, char *, long, long);
- ;*
- ;* FUNCTION
- ;*
- ;* INPUTS
- ;* Buffer - Pointer buffer to blit to screen.
- ;* Screen - Screen address to blit buffer to.
- ;* Width - Width of buffer.
- ;* Height - Height of buffer.
- ;*
- ;* RESULT
- ;* NONE
- ;*
- ;* WARNINGS
- ;* Assumes the screen to be 320 pixels wide and the source buffer width
- ;* to be divisible by 16.
- ;*
- ;****************************************************************************
- GLOBAL C Xmode_Blit:NEAR
- PROC Xmode_Blit C NEAR USES ecx edx esi edi es
- ARG buffer:NEAR PTR
- ARG screen:NEAR PTR
- ARG imgwidth:DWORD
- ARG imgheight:DWORD
- LOCAL rowcount:DWORD
- LOCAL xplane:DWORD
- LOCAL edi_startval:DWORD
- LOCAL esi_startval:DWORD
- LOCAL xadd:DWORD
- ;----------------------------------------------------------------------------
- ; Initialize
- ;----------------------------------------------------------------------------
- IF PHARLAP_TNT
- mov eax,01Ch ;Set ES selector to VRAM
- mov es,ax
- ENDIF
- mov esi,[buffer]
- mov edi,[screen]
- mov [esi_startval],esi
- mov [edi_startval],edi
- mov edx,320 ;Compute modulo
- sub edx,[imgwidth]
- shr edx,2
- mov [xadd],edx
- ;----------------------------------------------------------------------------
- ; Transfer the data on plane at a time.
- ;----------------------------------------------------------------------------
- mov [xplane],1
- ??Do_plane:
- SET_PLANE [xplane] ;Set plane to transfer to
- mov eax,[imgheight]
- mov [rowcount],eax
- mov edx,[xadd]
- ??Do_row:
- mov ecx,[imgwidth] ;Length of row to copy in DWORDS
- shr ecx,4
- ; Transfer a row of pixels
- ??Not_done:
- mov al,[esi + 8] ;Get pixel
- mov ah,[esi + 12] ;Get pixel
- ror eax,16
- mov al,[esi] ;Get pixel
- mov ah,[esi + 4] ;Get pixel
- mov [es:edi],eax ;Write pixels to VRAM plane
- add esi,16 ;Next source position
- add edi,4 ;Next VRAM position
- dec ecx
- jnz ??Not_done
- add edi,edx ;Next VRAM row
- dec [rowcount] ;Decrement the row count
- jnz ??Do_row
- ; Go to next X-Plane
- inc [esi_startval]
- mov eax,[esi_startval]
- mov esi,eax
- mov eax,[edi_startval]
- mov edi,eax
- shl [xplane],1
- cmp [xplane],16
- jnz ??Do_plane
- ret
- ENDP Xmode_Blit
- END
|