| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594 |
- ;
- ; 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 ***
- ;***********************************************************************************************
- ;* *
- ;* Project Name : Command & Conquer -- launcher program *
- ;* *
- ;* File Name : launch.asm *
- ;* *
- ;* Programmer : Steve Tall *
- ;* *
- ;* Start Date : August 19, 1995 *
- ;* *
- ;* Last Update : Modified for RA, October 14th, 1996 [ST] *
- ;* *
- ;* Build : Compile and link with MASM 6 *
- ;* Note that masm will complain there is no stack because *
- ;* we are not using a simplified segment model *
- ;* *
- ;*---------------------------------------------------------------------------------------------*
- ;* Functions: *
- ;* Start -- Program entry point *
- ;* Mem_Error -- report an out of memory error (not a function) *
- ;* Disc_Error -- report an out of disk space error (not a function) *
- ;* Delete_Swaps -- Deletes old swap files from the game directory *
- ;* Setup_Environment -- Adds environment strings required for DOS4G professional *
- ;* *
- ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- TITLE "Red Alert launcher"
- .386
- ;----------------------------------------------------------------------------------------------
- ; Defines for DOS system functions.
- ;
- DOS_LOAD_AND_EXEC =4B00H
- DOS_ALLOC =48H
- DOS_FREE =49h
- DOS_GET_FREE_DISC_SPACE =36H
- DOS_SET_DIRECTORY =3BH
- DOS =21H
- DOS_SET_DTA =1AH
- DOS_FIND_FIRST =4EH
- DOS_FIND_NEXT =4FH
- DOS_DELETE_FILE =41H
- DOS_SET_ATTRIBUTES =43H
- DOS_SET_DRIVE =0EH
- DOS_RESIZE_ALLOCATION =4Ah
- DOS_EXIT =4ch
- DOS_PRINT_STRING =9
- ;----------------------------------------------------------------------------------------------
- ; Defines for keyboard BIOS functions
- ;
- KEYBOARD_BIOS =16h
- BIOS_CHECK_KEYBOARD =11h
- BIOS_GET_KEYSTROKE =10h
- ;----------------------------------------------------------------------------------------------
- ; Defines for video bios functions
- ;
- VIDEO_BIOS =10h
- BIOS_SET_VIDEO_MODE_3 =0003h
- ;----------------------------------------------------------------------------------------------
- ; Misc defines
- ;
- MEM_REQUIRED =1024 * 400 ;Check for 400k low memory
- INIT_FREE_DISK_SPACE =15*1024*1024 ;C&C requirement for disc space
- MY_ALLOCATION =1536/16 ;only allow myself 1.5k to run in incl. psp and stack
- ;you can find out how much space the program needs
- ;by running WDISASM LAUNCH.OBJ
- ;dont forget to add 256 bytes on for the psp
- include <pcmacro.16>
- ;----------------------------------------------------------------------------------------------
- ; Simplified segment models are for wimmin
- ;
- ; We want 32 bit instructions in a 16 bit segment
- ;
- _code segment para public use16 'code'
- assume ds:_data
- assume es:_data
- assume ss:_data
- assume cs:_code
- ;*************************************************************************************************
- ;* Start -- Program entry point *
- ;* *
- ;* *
- ;* INPUT: nothing *
- ;* *
- ;* OUTPUT: DOS return code from spawning the game *
- ;* *
- ;* HISTORY: *
- ;* 08/19/95 ST: Created. *
- ;*===============================================================================================*
- Start: ;
- ; Set up the segments and the stack pointer
- ;
- cli
- mov ax,_data
- mov ds,ax
- mov [Psp],es
- mov ss,ax
- mov sp,offset MyStack
- sti
- ;
- ; Modify the starting memory allocation to free enough for the game proper
- ;
- save ax
- mov bx,MY_ALLOCATION
- mov ah,DOS_RESIZE_ALLOCATION
- int DOS
- restore ax
- bcs Mem_Error
- ;
- ; See if we have enough free memory to launch
- ;
- mov ah,DOS_ALLOC
- mov bx,-1 ;I want it all! hahaha
- int DOS
- jnc Mem_Error ;shouldnt ever succeed but...
- cmp ax,8
- jnz Mem_Error
- cmp bx,(MEM_REQUIRED/16)-MY_ALLOCATION
- bls Mem_Error ;oh dear
- ;
- ; See if there is enough free disc space to launch
- ;
- xor dl,dl
- mov ah,DOS_GET_FREE_DISC_SPACE
- int DOS
- ; dos get free disc space returns with the following
- ; ax - sectors per cluster
- ; bx - number of available clusters
- ; cx - bytes per sector
- ; dx - cluster on the drive
- mul bx ;clusters avail*sectors per cluster
- shl edx,16
- mov dx,ax
- mov eax,edx
- and ecx,65535
- mul ecx ;*bytes per sector
- cmp eax,INIT_FREE_DISK_SPACE
- blo Disc_Error
- ;
- ; Get the directory we were run from and cd to it
- ;
- mov es,[Psp]
- mov bx,2ch
- mov es,es:[bx] ;es points to env
- xor di,di
- xor al,al
- mov cx,-1
- ;
- ; Search for 0,0 as that aways terminates the environment block
- ;
- @@again: repnz scasb
- cmp_b es:[di],al
- jnz @@again
- lea si,[di+3] ;skip length word and second zero
- ;
- ; Copy the directory name to temporary workspace
- ;
- mov di,si
- mov cx,-1
- repnz scasb
- neg cx
- mov bx,cx
- mov cx,-1
- std
- mov al,'\'
- repnz scasb
- neg cx
- sub bx,cx
- mov cx,bx
- inc cx
- cld
- mov di,offset Dta
- push ds
- mov ax,es
- mov bx,ds
- mov es,bx
- mov ds,ax
- rep movsb
- xor al,al
- stosb
- pop ds
- ;
- ; Actually set the drive and path
- ;
- mov dl,[Dta]
- sub dl,'A'
- mov ah,DOS_SET_DRIVE
- int DOS
- mov dx,offset Dta
- mov ah,DOS_SET_DIRECTORY
- int DOS
- ;
- ; Delete all the old swap files
- ;
- mov dx,offset Dta
- mov ah,DOS_SET_DTA
- int DOS
- call Delete_Swaps
- ;
- ; Add in the environment strings required for DOS4G professional
- ;
- call Setup_Environment
- ;
- ; Set up the parameters to launch c&c
- ;
- mov es,[Psp]
- mov dx,offset GameName
- mov bx,offset GameParameterBlock
- mov ax,[EnvironmentSegment] ;Initialised by Setup_Environment
- mov_w [bx],ax ;ptr to environment
- ;
- ; just pass the command tail we got straight through
- ;
- mov ax,80h
- mov [bx+2],ax ;offset of command tail
- mov ax,[Psp]
- mov [bx+4],ax ;segment of command tail
- mov es,ax
- mov ax,es:[2ch]
- mov [bx+8],ax ;segment of first fcb
- mov [bx+12],ax ;segment of second fcb
- mov ax,_data
- mov es,ax
- ;
- ; Run the main game program
- ;
- mov ax,DOS_LOAD_AND_EXEC ;load and execute program
- int DOS
- ;
- ; Restore teh environment memory
- ;
- mov ax,[EnvironmentSegment]
- test ax,ax
- jz @@no_free
- mov es,ax
- mov ah,DOS_FREE
- int DOS
- @@no_free: ;
- ; Quit to DOS
- ;
- mov ah,DOS_EXIT
- int DOS
- ;*************************************************************************************************
- ;* Mem_Error -- Print a memory error message and quit *
- ;* *
- ;* *
- ;* INPUT: nothing *
- ;* *
- ;* OUTPUT: undefined *
- ;* *
- ;* HISTORY: *
- ;* 08/19/95 ST: Created. *
- ;*===============================================================================================*
- Mem_Error: mov ax,BIOS_SET_VIDEO_MODE_3
- int VIDEO_BIOS
- mov dx,offset MemErrorTxt
- mov ah,DOS_PRINT_STRING
- int DOS
- mov dx,offset MoreInfoTxt
- Error_In: mov ah,DOS_PRINT_STRING
- int DOS
- ;
- ; wait for keypress
- ;
- nochar: mov ah,BIOS_CHECK_KEYBOARD
- int KEYBOARD_BIOS
- beq nochar
- ;
- ; get the ket out of the buffer
- ;
- mov ah,BIOS_GET_KEYSTROKE
- int KEYBOARD_BIOS
- ;
- ; Quit to DOS
- ;
- mov ah,DOS_EXIT
- int DOS
- ;*************************************************************************************************
- ;* Disc_Error -- Prints a disk error message and exits *
- ;* *
- ;* *
- ;* INPUT: nothing *
- ;* *
- ;* OUTPUT: DOS return code from spawning the game *
- ;* *
- ;* HISTORY: *
- ;* 08/19/95 ST: Created. *
- ;*===============================================================================================*
- Disc_Error: mov ax,BIOS_SET_VIDEO_MODE_3
- int VIDEO_BIOS
- mov dx,offset DiscErrorTxt
- jmp Error_In
- ;*************************************************************************************************
- ;* Setup_Environment -- Create a new environment block with the set DOS4GVM= stuff *
- ;* *
- ;* *
- ;* INPUT: nothing *
- ;* *
- ;* OUTPUT: nothing *
- ;* *
- ;* Note: Modifies the global variable 'EnvironmentStrings' to point to the start of our new *
- ;* environment block. This memory will need to be freed later. *
- ;* *
- ;* HISTORY: *
- ;* 10/14/96 ST: Created. *
- ;*===============================================================================================*
- Setup_Environment proc near
- ;
- ; Point to default environment.
- ;
- mov [EnvironmentSegment],0
- ;
- ; Get the address of our environment block into es
- ;
- mov es,[Psp]
- mov bx,2ch
- mov es,es:[bx] ;es points to env
- ;
- ; Search for the end of the block to get its length
- ;
- xor di,di
- xor al,al
- mov cx,-1
- @@search: repnz scasb
- cmp_b es:[di],al
- jnz @@search
- ;
- ; di is length of environment block
- ;
- lea bx,[di+256] ; a little extra to be sure.
- ;
- ; Allocate memory for a copy of the environment.
- ;
- push di
- mov ah,DOS_ALLOC
- shr bx,4 ;needs to be number of paragraphs
- int DOS
- jnc @@ok
- ;
- ; Oops. Not enough memory. We are screwed so just exit.
- ;
- pop di
- jmp @@out
- @@ok: ;
- ; Save the pointer to our new environment
- ; We can also use this to free the memory later
- ;
- mov [EnvironmentSegment],ax
- ;
- ; Copy the original environment to the newly alloced memory
- ;
- mov es,ax
- pop cx ; size to copy
- push ds
- mov ds,[Psp]
- mov bx,2ch
- mov ds,ds:[bx] ;ds points to original environment
- xor si,si
- xor di,di
- rep movsb
- pop ds
- mov si,offset Dos4gEnvironment
- @@copy_loop: lodsb
- stosb
- test al,al
- jnz @@copy_loop
- ;
- ; Copy the final zero. The environment must be terminated by 2 zeros.
- ;
- movsb
- @@out: ret
- Setup_Environment endp
- ;*************************************************************************************************
- ;* Delete_Swaps -- Delete any swap files left over from a previous game *
- ;* *
- ;* *
- ;* INPUT: nothing *
- ;* *
- ;* OUTPUT: nothing *
- ;* *
- ;* HISTORY: *
- ;* 08/19/95 ST: Created. *
- ;*===============================================================================================*
- Delete_Swaps proc near
- ;
- ; Use 'Find first/next' to find the swap files
- ;
- mov dx,offset SwapName
- mov cx,7 ;attributes
- mov ah,DOS_FIND_FIRST
- int DOS
- bcs @@out ;no matching files
- ;
- ; Make sure it isn't read only
- ;
- @@loop: mov dx,offset Dta+1eh
- mov ah,DOS_SET_ATTRIBUTES
- mov al,1
- xor cx,cx ;attributes
- int DOS
- ;
- ; Delete the file
- ;
- mov dx,offset Dta+1eh
- mov ah,DOS_DELETE_FILE
- int DOS
- ;
- ; Find the next one
- ;
- mov ah,DOS_FIND_NEXT
- int DOS
- bcc @@loop
- @@out: ret
- Delete_Swaps endp
- _code ends ;end of code segment
- ;----------------------------------------------------------------------------------------------
- ;
- ; Complex data segment
- ;
- ;
- _data segment dword public use16 'data'
- EnvironmentSegment dw 0 ;ptr to environment to pass to child process
- Psp dw 0 ;segment addr of program segment prefix
- GameParameterBlock db 16h dup (0) ;required parameters for DOS launch
- GameName db "GAME.DAT",0 ;this is the name of the app to be spawned
- SwapName db "*.SWP",0 ;swap files always have a .SWP extension
- ;
- ; Environment to be set for DOS4G professional
- ;
- Dos4gEnvironment db "DOS4GVM=SwapMin:12M,SwapInc:0",0,0
- ;
- ; Error and warning messages
- ;
- MemErrorTxt db "Warning - There is very little free conventional DOS memory in the system.",13,10,"$"
- DiscErrorTxt db "Error - insufficient disk space to run Red Alert."
- db 13,10,"Red Alert requires 15,728,640 bytes of free disk space.",13,10 ;this string will
- ;run into the next because
- ;there is no '$'
- MoreInfoTxt db "Please read the Red Alert manual for more information.",13,10,13,10
- db "Press a key to continue.",13,10,"$"
- Dta db 128 dup (0) ;enough for complete path
- ;*************************************************************
- ;
- ; The stack
- ;
- StackSpace db 256 dup (0) ;256 byte stack!
- MyStack label byte ;The stack starts here and grows down.
- EndCode label byte ;The end of the data segment
- _data ends
- end Start
|