diff options
Diffstat (limited to 'doc/devel')
42 files changed, 4117 insertions, 0 deletions
diff --git a/doc/devel/aniformat b/doc/devel/aniformat new file mode 100644 index 0000000..65703a5 --- /dev/null +++ b/doc/devel/aniformat @@ -0,0 +1,37 @@ +For *.ani, *.sml, *.med, *.big files, each line is in following format: + +filename transparent_color colormap_index hotspot_x hotspot_y + +Filename is string, all others are int. + +filename + relative to the directory that .ani file is in. + +transparent_color + -2 : use PNG tRNS chunk transparency specification + -1 : transparent color is not used; not transparency in the image + (this behavior is enforced, even when tRNS is present) + 0 : for paletted images, transparent color index 0; + special for truecolor images, makes RGB (0,0,0) transparent + N>0 : for paletted images, transparent color index N; + meaningless for truecolor images + +colormap_index + -1 : colormaps are not used for the image + for paletted images, the palette from the image itself + will be used + N : for paletted images, the palette from the colormap N will + be used (so some .ct file somewhere defines the palette); + meaningless for truecolor images + +hotspot_x, hotspot_y + can both be positive of negative (or 0) + the position of the image on the screen will be + (draw_x - hotspot_x, draw_y - hotspot_y) + so a positive hotspot *usually* defines the logical center of + an image, and a negative hotspot *usually* defines the position + of an image within some larger compound image; there are of course + exceptions to this general rule + +This information is parsed in libs/graphics/sdl/3do_getbody.c + diff --git a/doc/devel/battleinput b/doc/devel/battleinput new file mode 100644 index 0000000..19eea87 --- /dev/null +++ b/doc/devel/battleinput @@ -0,0 +1,13 @@ +The UQM source now has a concept of input context for melee control. + +A base InputContext structure is defined in battlecontrols.h. It defines +the common fields of all the specific structures for each control method. + +Among these fields is a BattleInputHandlers structure, which defines the +functions which handle various input actions for melee, such as frame input, +selecting the next ship, and querying readiness at the end of a battle. + +Structures ComputerInputContext, HumanInputContext, and NetworkInputContext +are "derived" from InputContext and can contain additional fields for the +specific control method. + diff --git a/doc/devel/blue-gas-giant-pal.png b/doc/devel/blue-gas-giant-pal.png Binary files differnew file mode 100644 index 0000000..0142f21 --- /dev/null +++ b/doc/devel/blue-gas-giant-pal.png diff --git a/doc/devel/checklist b/doc/devel/checklist new file mode 100644 index 0000000..23eed02 --- /dev/null +++ b/doc/devel/checklist @@ -0,0 +1,52 @@ + -== Checklist for releases ==- + + +Preparing for the release: +- update the 'version' file in the content dir +- update 'uqmversion.h' +- update uqm.lsm (needs to be done after the content packages are generated) +- test on all relevant platforms +- make sure the documentation files are up-to-date + - Clean up the ChangeLog file + - generate Whatsnew from the ChangeLog + - doc/users/manual.txt + - doc/users/unixinstall + - Contributing + - AUTHORS + - INSTALL (and platform variants) + - unix man pages (in the future) + + +Building the release: +- make a final build in release mode +- for the source archive: + - use a clean subversion checkout. + Just using 'svn update' and watching the output will not be + enough, as the files not in repository will be ignored. + - be sure to include content/version +- Building the content packages: + - make sure the permissions in the .zip files are ok (0644 for data files + and 0755 for executables and dirs) + - don't compress .ogg files + + +Announcing the release: +- provide md5 sums for the released files +- add a new entry for the release in the bugs database +- update the home page + - http://sc2.sourceforge.net/index.php (News item) + - http://sc2.sourceforge.net/downloads.php + - http://sc2.sourceforge.net/info.php + - http://sc2.sourceforge.net/WhatsNew + - http://sc2.sourceforge.net/screenshots.php +- send a mail to sc2-announce +- set the forum 'news' +- set the #sc2 irc channel topic +- update the version number in http://uqm.stack.nl/wiki/Template:Uqmversion + + +Moving on to the next version: +- update the snapshots page so that content diffs are generated to the + most recent release +- update doc/devel/versions with the release revision + diff --git a/doc/devel/contentfiles b/doc/devel/contentfiles new file mode 100644 index 0000000..fdcd478 --- /dev/null +++ b/doc/devel/contentfiles @@ -0,0 +1,28 @@ +<race>/*icons.0.png + small (16x16) icon, used for + - picking the next ship for combat in Supermelee + - picking the next ship for combat in the full game + - the selection grid in the Supermelee fleet editor + - the escorts in the status window in the full game when not in + battle + - loading a game + - loading a melee fleet + - (others?) + +<race>/*icons.0.png + large icon with shadow, used for + - current selection in the right middle of the Supermelee fleet editor + - ship status window in battle + - (others?) + +<race>/*micon.0.png + large icon without shadow, used for + - images in the fleet when in the Supermelee fleet editor + - images in the fleet when in the shipyard + - current selection in the bottom right in the shipyard + - (others?) + +<race>/*micon.1.png + small icon, used for + - representing a battle group in a solarsystem + diff --git a/doc/devel/debug b/doc/devel/debug new file mode 100644 index 0000000..22be628 --- /dev/null +++ b/doc/devel/debug @@ -0,0 +1,74 @@ +The file src/sc2code/uqmdebug.c and src/sc2code/uqmdebug.h contain various +debugging functions, which are included in the binary when the game +is built in debug mode. +These functions can be called from anywhere in the code, though some +require the game to be in a specific state. +The function debugKeyPressed() in uqmdebug.c is called when the debug key +is pressed. This function is a suitable place to put various debugging +calls. +There are also global variables 'debugHook' and 'doInputDebugHook', +which can be set to a function to be called from the Starcon2Main thread. +If if is set, 'debugHook' is called the next iteration of the main game loop +(which will occur when the current activity (IP, HyperSpace, Communication, +Battle) changes. The game will be in a well defined state here. +If 'doInputDebugHook' is set, the function it is set to is called from +doInput(), which is called all throughout the game. +By setting one of these hooks, a function can be called from the Starcon2Main +thread, thereby eliminating threading issues that may otherwise arrise. +The debug key can be specified in user's override.cfg by adding a line +with a text similar to "debug.1 = STRING:key F12". +An interactive way to access various debugging code, similar to +the uio debug mode (see below) is in the works. + +The most interesting debugging functionality available at the moment is +listed below: +- the function equipShip() + When this function is called, the SIS is equiped with various useful + modules (a possible Precursor Bomb is left in place), all + fuel tanks and crew pods are filled to the maximum, you are given + the maximum number of landers, and all possible lander shields are + installed. +- the boolean variable instantMove + When this variable is set to TRUE, you can select a location on the + star map, and your HyperSpace/Quasispace coordinates will immediately + be set to them. Your realspace coordinates are not changed, so if you + are exploring a solar system, you'll only notice it when you leave to + HyperSpace. +- the function showSpheres() + When this function is called, all spheres of influence of the active + races will be shown. +- the function activateAllShips() + When this function is called, it will make all ships available for + purchase in the shipyard. +- the function forwardToNextEvent() + Fast forwards the clock until the next event. If TRUE is given as an + argument, the HYPERSPACE_ENCOUNTER_EVENTs, which normally happen every + day, are skipped. +- the function dumpEvents() + Outputs information on all scheduled events to a FILE. +- the function dumpPlanetTypes() + Outputs information on all planet types to a FILE. +- the function dumpUniverseToFile() + Outputs information on the universe to "./PlanetInfo". This function + should only be called from debugHook, as threading issues would otherwise + arrise. +- the functions resetCrewBattle() and resetEnergyBattle() + This function, when called in melee, sets the current crew or energy + level of the bottom player's ship to its maximum. This works both in + Supermelee and in the full game. +- the function uio_debugInteractive() + This function is not defined in sc2code/uqmdebug.h, but in libs/uio.h. + This function can interactively (tty-based) display information on + the state of the uio file system, and modifications can be made. +- the function dumpStrings() + This function prints all the game strings, and is useful to check whether + the various string bases, as defined in gamestr.h, are correct. +- the function debugContexts() + Prints and visually displays the various graphics contexts. + This function should only be called from doInputDebugHook(), as threading + issues would otherwise arrise. + + +The first version of this document was created by Serge van den Boom, +on 2004-05-15. + diff --git a/doc/devel/dialogs b/doc/devel/dialogs new file mode 100644 index 0000000..91ca306 --- /dev/null +++ b/doc/devel/dialogs @@ -0,0 +1,74 @@ +This file describes how the conversation system works. + +Functions: + +DoResponsePhrase(RESPONSE_REF R, RESPONSE_FUNC response_func, + UNICODE *ConstructStr) + Adds a line to the list of remarks the player may choose from. + R - The index for the line in the .txt dialog file. + response_func - the function where to continue the dialog if this + remark was chosen. + ConstructStr - A user-constructed string to display. If it is 0, + the string from R is used; if it is 0, the string identified + by R is not displayed, but R is still used to report what choice + a player made. + In practice ConstructStr is always the result of a call + to construct_response() and R is set to the first part of + the constructed phrase. + Note: ConstructStr must still be valid after the function calling + DoResponsePhrase() returns, so it can't be on the stack. + Also, if there are multiple constructed responses at one + point in the dialog, they will need separate buffers. + In practice, a global buffer shared_phrase_buf is used when + only one buffer is required. + Note: In practice, when R is 0, the call is always made through the + macro Response() + +Response(RESPONSE_REF R, RESPONSE_FUNC response_func) + Macro that calls DoResponsePhrase() with 0 for ConstructStr. + +construct_response(UNICODE *buf, int R, ...) + Concatenates strings from a dialog .txt file with strings from + the source. The arguments after *buf are alternatingly an int R, + and a UNICODE * str, until either R is -1, or str is NULL. + buf - the destination + R - The index for the line in the .txt dialog file. + str - A UNICODE * string. + +NPCPhrase_cb(int index, TFB_TrackCB cb) + Display the NPC speech with identifier 'index' (and play the + associated sample). The callback function 'cb' is called when + the displaying is done (usually when the sample ends). + index - The index for the line in the .txt dialog file. + cb - the callback function to called when the line is over. + NULL indicates no callback function. + +NPCPhrase(int index) + Display the NPC speech with identifier 'index'. + This is a macro to NPCPrhase_cb(). + index - The index for the line in the .txt dialog file, or + GLOBAL_PLAYER_NAME for the name of the captain, + GLOBAL_SHIP_NAME for the name of the flagship, + GLOBAL_PLAYER_LOCATION, for the player's hyperspace coordinates, + GLOBAL_ALLIANCE_NAME, for the name of the new alliance, or + a negative number for the absolute number as speech + +DISABLE_PHRASE(int index) + Mark a player line as not to be offered as a choice anymore. Not in + this conversion, nor in any future conversations. + index - The index for the line in the .txt dialog file. + +PHRASE_ENABLED(int index) + Check if a player phrase was formerly marked as not to be offered anymore + (by call to DISABLE_PHRASE). + index - The index for the line in the .txt dialog file. + +PLAYER_SAID(RESPONSE_REF said, RESPONSE_REF test) + Test whether a player the player reply 'said' is equal to the reply + 'test'. + said - the response that the player selected + test - a response to test 'said' against + + +Initial version by Serge van den Boom, 2005-01-10 + diff --git a/doc/devel/files b/doc/devel/files new file mode 100644 index 0000000..ea4df38 --- /dev/null +++ b/doc/devel/files @@ -0,0 +1,115 @@ +battle.c +border.c Draws the screen borders. +build.c +cleanup.c Cleanup routines for when the game is done. +clock.c Manages the game clock. +collide.c Process a collision of objects in combat. +comm.c Handles communication with aliens. +commglue.c Helper functions for communication with aliens. +confirm.c Asks for confirmation on exit. +credits.c Shows the credits after a victory. +cyborg.c Handles combat AI. +debug.c Debugging functions. +demo.c Code for demo mode and game journal. +displist.c Generic doubly linked list, which can keep its own pool + of preallocated link structures. + This generic list is used in various places throughout + the game source, but without preallocaded link structures. +dummy.c +encount.c Handles what to do when a player encounters an alien. +fmv.c Handles video sequences. +galaxy.c Starmap? Hyperspace background? +gameinp.c +gameopt.c Game options menu, including save and load selection. +gendef.c Defines functions to be called for generating star systems. +getchar.c Routines for entering characters with the joystick. +globdata.c Sets up global data, creates the main ship, and the radar. +gravity.c Maths regarding gravity in combat. +gravwell.c Handles objects that generate gravity in combat. +grpinfo.c Handles battle groups. +hyper.c Handles hyperspace movement and actions. +init.c Initialization of various game data. +intel.c Passes input of computer or player along (?) +intro.c Alternative functions for beginning and ending sequences + to those in fmv, unused. (PC version?) +ipdisp.c Something with spheres of influence? +load.c Loading a saved game. +loadship.c Loading of ship resource data. +master.c Preloading of all ships? +melee.c All supermelee menu related code. +misc.c Miscelaneous routines related to combat but not directly to + the fighting. +oscill.c Code for the oscilloscope and speech sample progress slider. + (during communication with aliens) +outfit.c Things related to outfiting the starship. +pickmele.c Ship selection in Supermelee (not in Full Game) +pickship.c Ship selection in Full Game (not in Supermelee) +plandata.c Some const data relating stars and planets. +process.c Some combat calculations. +restart.c Main menu (start new, load, supermelee). +save.c Saving of a game. +settings.c The back end of the game options. +setup.c Initialisations for key config, and loading of various + resources. +ship.c Ship movement in combat. +shipstat.c Routines for showing information about ships in combat + (name, crew, energy). (also status.c) +shipyard.c Things related to selection of your companion ships. +sis.c Drawing various game state information (ship, ship name, + captains name, hyperspace coordinates, date, melnorme credits, + landers, storage bays, crew, fuel, game menu) +starbase.c Code for the Earth starbase. +starcon.c Code for various events (Arilou portal, Kohr-Ah genocide, + Pkunk exodus, Thraddash attack Kohr-Ah, Ilwrath attack + Thraddash, Utwig+Supox attack Kohr-Ah, Mycon colonization + attempt, hyperspace ship spawned, zoqfot signal, zoqfot under + attack, Shofixti return, Spathi build shield, Arilou give + the Dnyarri to the Umgah, Yehat rebellion, Slylandro plague + worsening) +starmap.c Code to find a star by it's coordinates and compose star names. +state.c Saving and loading the temporary planet information, + like resource information. +status.c Maintain and draw some information like the captain picture, + crew, energy. (also shipstat.c) +tactrans.c Code for some additional combat events (explosions, dying, + new ship, ion trail, escape). +trans.c Integer variant of atan2(). +utils.c Various auxiliary utils, code for pausing. +velocity.c Velocity computation routines. +weapon.c Routines for weapons fire in combat. + + +build.h +clock.h +coderes.h +collide.h +commglue.h +demo.h +displist.h +element.h +encount.h +globdata.h +hyper.h +ifontres.h +igfxres.h +ikey_con.h +imusicre.h +intel.h +ires_ind.h +isndres.h +istrtab.h +melee.h +nameref.h +races.h +resinst.h +respkg.h +restypes.h +sis.h +sounds.h +starbase.h +starcon.h +state.h +units.h +velocity.h +weapon.h + diff --git a/doc/devel/fontres b/doc/devel/fontres new file mode 100644 index 0000000..c70cb6c --- /dev/null +++ b/doc/devel/fontres @@ -0,0 +1,75 @@ +This is the format for resources of type GFXRES (font variantion -- these +have the extension .fon in the original source). + +All fonts have exactly 96 character descriptors starting with ASCII +code 32 (space). + +Everything is stored MSB first unless otherwise specified. + +position length meaning + 4 0xffffffff if the file is uncompressed. + Otherwise, the file is compressed. When uncompressed, the + file complies with the rest of the format as described + below. + 4 Unused in file, always 0x00000000 + 1 Font leading: the vertical distance between lines of text + in pixels. + 1 Max ascender: the maximum extent of the font upwards from + the baseline in pixels. + 1 Max descender: the maximum extent of the font downwards + from the baseline in pixels. + 1 Char spacing: the number of pixels in between the + successive characters. + 1 Kern amount: the number of pixels (out of char spacing) + that are used for kerning (explained later). Cannot be + more than char spacing. + 96 Kerning table: each byte corresponds to a character: + bits 0-1: right-hand side kerning mask + bits 2-3: left-hand side kerning mask + For each pair of chars printed the code figures out whether + the kerning should be used by taking the right mask of a + preceeding char and ANDing it with the left mask of a + succeeding char. If the result is 0, the Kern amount is + subtracted from Char spacing. + 3 alignment padding: aligns the following char descriptors + on 8-byte boundary. + + +Then for all 96 chars: +Char descriptors (these are frame descriptors from .ani format and some +bits are most likely never used): + 4 Type index and flags (TypeIndexAndFlags) + Low 2 bytes: + bits 0-11 is the index of this frame + bits 12-15 are the type flags: + - bit 12-13: + - 0: (ROM_DRAWABLE) + - 1: Direct drawable (RAM_DRAWABLE) + - 2: (SCREEN_DRAWABLE) + - 3: (OVERLAY_DRAWABLE) + High 2 bytes (frame flags): + - bits 0-7: global PLUT to use (probably unused) + - bit 12: Frame is in cel format (DATA_HARDWARE) + - bit 13: (DATA_COPY aka DATA_SCREEN) + - bit 14: (DATA_PACKED) + - bit 15: (X_FLIP) + 4 Hot spot information (definition of (0, 0) in the image): + - low 2 bytes: x location of hot spot + (probably never used) + - high 2 bytes: y location of hot spot + This is the baseline of a character. The hotspot Y aligns + with the baseline of the text. + 4 Image bounds: + - low 2 bytes: Image width + - low 2 bytes: Image height + 4 Offset from beginning of the char descriptor for this + char to the beginning of the frame data. + +Frames: +Then for all frames: + See "Frames" in gfxres. + + +Initial version 2003-09-02, by Alex Volkov +Frame descriptors and data from gfxres by Serge van den Boom + diff --git a/doc/devel/generate b/doc/devel/generate new file mode 100644 index 0000000..a7108bb --- /dev/null +++ b/doc/devel/generate @@ -0,0 +1,155 @@ +Note: this file (still) describes the way in which various things were +generated in the original source. It is still useful, but there are some +changes: +- all of this functionality used to be handled through a single function, + either the function returned by GenerateIP(), or GenerateRandomIP(). + Now, there is a structure GenerateFunctions, which contains a function + for each of the type of generation. See generate.h. +- most functions don't use the global variables pSolarSysState, pOrbitalDesc, + and pPlanetDesc anymore. Instead, where these are needed, they are passed + along through a parameter. + +Files related to this system: +- planets/generate.h + Defines GenerateFunctions. +- planets/generate/gendefault.c + Default generation functions for when no specific one is specified. +- planets/generate/gen*.c + Specific generation functions. +- gendef.c + Glue code. + +This file should eventually be updated to reflect the new system. +See the file 'orggenerate' for a description on how the system originally +worked. + +============================================================================ + +The various universe related game data is generated through a call +to a solar system dependant generation function. +This function is of type PLAN_GEN_FUNC, which is a typedef to + void (*PLAN_GEN_FUNC) (BYTE control) +, where the 'control' argument specifies what type of data needs to be +generated (one of GENERATE_PLANETS, GENERATE_MOONS, GENERATE_ORBITAL, +INIT_NPCS, REINIT_NPCS, UNINIT_NPCS, GENERATE_MINERAL, GENERATE_ENERGY, +GENERATE_LIFE, or GENERATE_NAME). + +The generation function for a solar system is kept in the 'GenFunc' +field of the SOLARSYS_STATE structure. +The SOLARSYS_STATE structure contains the data for a solar system. +Currently, only one SOLARSYS_STATE structure is used at once, and +the global variable pSolarSysState points to the current one. +The GenFunc field is initialised in ExploreSolarSys(), to the value +returned by GenerateIP() in sc2code/gendef.c. Usually, this will be +'GenerateRandomIP', but for some specific solar systems a (pointer to a) +custom generation function is returned. This depends on the value of +CurStarDescPtr->Index, which contains values such as SOL_DEFINED, +MELNORME0_DEFINED, AQUA_HELIX_DEFINED, etc (see sc2code/encount.h +for the complete list). +The starmap_array in sc2code/plandata.c specifies Index for all +the solar systems in the game. + +Following are the possible values of the 'control' argument to the +generation function, with the description of how the generation function +acts on this. As the custom generation functions often only need to +change one specific aspect of this game data generation, they will +often call GenerateRandomIP() for the rest. +StarBases are handled as if they were moons. + +GENERATE_PLANETS +Pre: the global variable pSolarSysState points to the relevant solar system. +Pre: the RNG is initialised with a seed to be used for the generation. + In practice, this seed is generated from the HyperSpace coordinates + of the solar system (which are hardcoded in sc2code/plandata.c), + followed by exactly one call to TFB_Random(). +Post: the RNG is in an undefined state. +This function determines how many planets the system has, and fills in +pSolarSysState->PlanetDesc[] for all planets, including the NumPlanets +field, which determines how many moons the planet will have. +It also sets the random seed that is used for data generated for this planet +(including the number of moons), based on its coordinates (which are in the +general case randomly determined themselves). + +GENERATE_MOONS +Pre: the global variable pSolarSysState points to the relevant solar system, + which is initialised by a GENERATE_PLANETS call. +Pre: the RNG is initialised with a seed to be used for the generation. + In practice, this seed is the seed stored by GENERATE_PLANETS + in the rand_seed field for the planet around which the moon(s) orbit. +Pre: pSolarSysState->pBaseDesc points to the the relevant planet + of pSolarSysState->PlanetDesc[]. +Post: The RNG is in an undefined state. +This function fills in pSolarSysState->MoonDesc[] for all moons around +the planet pointed to by pSolarSysState->pBaseDesc. +It also sets the random seed that is used for data generated for the moon +based on its coordinates (which are in the general case randomly determined +themselves). + +GENERATE_ORBITAL +Pre: the global variable pSolarSysState points to the relevant solar system, + which is initialised by a GENERATE_PLANETS call. +Pre: pSolarSysState->pOrbitalDesc points to the relevant planet or moon from + pSolarSysState->PlanetDesc[] or pSolarSysState->moonDesc[] +Pre: the planet or moon that pSolarSysState->pOrbitalDesc points to + is initialised by a GENERATE_PLANETS or GENERATE_MOONS call. +This function fills in pSolarSysState->SysInfo with the characteristics +of the planet or moon, as seen from orbit. +It also initialises the random seeds used for the generation of bio, +minerals, and energy nodes on the surface. +It also sets the discovery report string (if appropriate), initialises +the surface graphics, and start the planet music. +For specific planets, it may initiate race communication and possibly combat, +and will only return once these are over. +NB. The GENERATE_ORBITAL code should be split up into separate calculation +and activation (graphics and music) parts. + +GENERATE_MINERAL, GENERATE_ENERGY, GENERATE_LIFE +Pre: the global variable pSolarSysState points to the relevant solar system, + which is initialised by a GENERATE_PLANETS call. +Pre: pSolarSysState->pOrbitalDesc points to the relevant planet or moon from + pSolarSysState->PlanetDesc[] or pSolarSysState->moonDesc[] +Pre: the planet or moon that pSolarSysState->pOrbitalDesc points to + is initialised by a GENERATE_PLANETS or GENERATE_MOONS call. +Pre: pSolarSysState->SysInfo is filled in by a GENERATE_ORBITAL call +This function determines the properties of one mineral deposit, energy node, +or life form on a planet or moon. On entry the caller sets +pSolarSysState->CurNode to the index of the requested item. This function +will then fill in pSolarSysState->SysInfo.PlanetInfo.CurPt, +pSolarSysState->SysInfo.PlanetInfo.CurType, and in the case of minerals also +pSolarSysState->SysInfo.PlanetInfo.CurDensity. +In case pSolarSysState->CurNode is set to a value larger than or equal to +the number of items of the requested kind ((COUNT) ~0 in practice), it is +set to the real number of nodes. In this case the CurXXX fields of +pSolarSysState->SysInfo.PlanetInfo are set to the values corresponding to +the largest valid CurNode index, but should probably be considered to be +undefined. +These functions may also change the game state, cause the lander +to take off (by setting InTransit to true in the active PLANETSIDE_DESC +structure), or mark an energy node as not retrieved, usually in response +to an item having been picked up since the last call. The game makes +a GENERATE_MINERAL, GENERATE_ENERGY or GENERATE_LIFE call (whatever +is relevant) for each item right after it is picked up. + +GENERATE_NAME +Pre: pSolarSysState is set to the relevant solar system. +Pre: The planet is initialised by GENERATE_PLANETS. +Pre: pSolarSysState->pBaseDesc points to the relevant planet, which should + be in the system. +This function fills GLOBAL_SIS (PlanetName) with the name of the planet +pointed to by pSolarSysState->pBaseDesc. +It also sets the GAME_STATE flag BATTLE_PLANET to the type of this planet, +so that it will be shown appropriately in melee if combat follows. +There is no generate function for the names of moons. The few moons that +are named (those in the Sol system), are handled as a special case of +the routines that prints these names (PrintCoarseScan3DO and +PrintCoarseScanPC). + +INIT_NPCS +REINIT_NPCS +UNINIT_NPCS +[TODO] + + +Initial version of this document created by Serge van den Boom, on 2005-07-11. + + diff --git a/doc/devel/gfxlib b/doc/devel/gfxlib new file mode 100644 index 0000000..82ce6b7 --- /dev/null +++ b/doc/devel/gfxlib @@ -0,0 +1,328 @@ + The TFB Graphics Libraries + + Initial documentation by Michael Martin, 4 Feb 2003 + +The graphics system in UQM has three major subsystems: + +- The "legacy" system, which most of the core code uses. This + involves the foo_blt () routines in 3do_blt.c, and the data + types CONTEXT, FRAME, DRAWABLE, and possibly others. I'm + less familiar with this code, and want to eradicate as much of it as + I can, but for now, its lowest level has been rewritten as direct + calls to: + +- The TFB_Draw* commands, documented below in great detail. These + routines deal with the datatype TFB_Image, and the more primitive + TFB_Canvas. They also support drawing to one of several 'screens', + but since only one thread should be allowed to touch the screen, + the TFB_DrawScreen routines end up constructing inputs to: + +- The DCQ/DrawCommand library. This is a ring queue with commands for + rendering graphics on the actual screen. It interacts to some + degree with the CONTEXT datatype, but otherwise is defined entirely + in terms of TFB_Images and TFB_Canvases. + + THE LEGACY LIBRARY + -------------------- + +The datatypes the code uses directly are CONTEXT, FRAME, and FONT, all +of which are really pointers to void. Pointers to those are PCONTEXT, +PFRAME, and PFONT. Then there's DRAWABLE, which is a DWORD, and its +pointer type PDRAWABLE. (These are defined in sc2code/libs/gfxlib.h.) +I'm not sure how DRAWABLE values are transformed into actual drawable +entities. + +The full structures for these are in various files in +sc2code/libs/graphics. + +context.h: defines CONTEXT_DESC and PCONTEXT_DESC (and the equivalent + CONTEXTPTR -- insert various sorts of incomprenshible + muttering here), + +display.h: defines a DISPLAY_INTERFACE and PDISPLAY_INTERFACE type (as + well as a global _pCurDisplay). + +drawable.h: defines FRAME_DESC and DRAWABLE_DESC, and the pointer + types PFRAME_DESC and PDRAWABLE_DESC. FRAME_DESC has a + TFB_Image pointer as a member. DRAWABLE_DESC currently + still uses a rather annoying technique where the last + member of a struct is a 1-element array, more memory than + that is actually allocated, and the array's bounds are + deliberately overflowed to get at multiple frames. + +font.h: defines FONT_DESC and PFONT_DESC. + +(Details on how all these data types work is forthcoming.) + + THE TFB_DRAW LIBRARY + ---------------------- + +The TFB_Draw commands have a single header file: +sc2code/libs/graphics/tfb_draw.h. This file declares the following +data types: + +SCREEN: This is an enum, naming the various screens that the DrawCmd + library can draw to. Valid values at present are + TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA, and TFB_SCREEN_TRANSITION. + These correspond to various objects that are of type TFB_Canvas. + + (The maximal number of screens is provided by a bogus last + element, TFB_GFX_NUMSCREENS. Keep that as the last element + and the allocators will operate properly regardless of any + screens you may later want to add.) + +TFB_Canvas: This is, for the purposes of most of the code, a void + pointer. The implementations of TFB_DrawCanvas commands + cast them to the appropriate type. (The only + implementation of these commands casts them to + SDL_Surface*.) + +TFB_Palette: Four UBYTES, r, g, b, and 'unused'. This is designed at + present to be directly castable to SDL_Color, which most + things do. We should probably do something about that at + some point. + +TFB_Image: The most important image structure. This has two + TFB_Canvases (one for the 'core' image, one for a scaled + version of it), a pointer to a TFB_Palette array, a + colormap index, a scaling constant, a Mutex from the + threading library (to ensure internal consistency if + multiple threads are doing stuff), and a 'dirty bit' which + means that, if the image is scaled, the ScaledImg needs to + be recomputed. + +TFB_DrawScreen +-------------- + +When you wish to draw graphics directly on the screen, you call these +routines, which enqueue the DrawCommands: + +---- + +void TFB_DrawScreen_Line (int x1, int y1, int x2, int y2, + int r, int g, int b, + SCREEN dest); + +Draws a line from (x1, y1)-(x2, y2) of a color specified by r, g, and +b on the specified screen. + +We have a known bug here in that if a corner of one of these lines is +outside of the context's clipping rectangle, the slope of the line may +change. + +---- + +void TFB_DrawScreen_Rect (PRECT rect, + int r, int g, int b, + SCREEN dest); + +Draws a (filled) rectangle with the specified color on the destination +screen. PRECT is part of the legacy library. + +void TFB_DrawScreen_Copy (PRECT r, SCREEN src, SCREEN dest); + +Copies data between screens. The PRECT defines the region to copy. +This can be handy in saving and restoring background information. + +---- + +void TFB_DrawScreen_Image (TFB_Image *img, + int x, int y, + BOOLEAN scaled, + TFB_Palette *palette, + SCREEN dest); + +void TFB_DrawScreen_FilledImage (TFB_Image *img, + int x, int y, + BOOLEAN scaled, + int r, int g, int b, + SCREEN dest); + +These two routines draw images. img, x, and y are all straightforward +(x and y refer to the upper left of the image), and scaled indicates +whether or not the NormalImg or ScaledImg should be used, and dest +names the target screen. + +For TFB_DrawScreen_Image, the 'palette' argument refers to a +256-element array of TFB_Palette that describes the palette to use. +(The default is cached in TFB_Image itself.) Various techniques are +used to cache the palette values to keep spurious palette-switch +commands from flooding the DrawCmd queue. However, switching the +palette many times per frame is likely to seriously degrade +performance. + +TFB_DrawScreen_FilledImage draws every non-transparent pixel in img in +the color specified by r, g, b. (Fonts and some menus do this.) + +---- + +void TFB_DrawScreen_WaitForSignal (void); + +Puts this thread to sleep until all commands queued to this point are +executed. Mostly used to keep from spamming the DrawCmd queue, and to +ensure proper operation of the next two routines. + +---- + +void TFB_DrawScreen_CopyToImage (TFB_Image *img, + PRECT lpRect, + SCREEN src); + +Load the pixels from the rectangle lpRect in screen src into img. If +you're actually working with the pixels directly, you'll want to do a +TFB_DrawScreen_WaitForSignal () to ensure the image has actually been +updated. (If you're just passing it to other TFB_DrawScreen commands, +that's unnecessary, because ordering within a thread is guaranteed.) + +---- + +void TFB_DrawScreen_DeleteImage (TFB_Image *img); + +Deallocates all memory associated with img. This REALLY doesn't +belong here. It should be a TFB_DrawImage command, with a requirement +that you WaitForSignal lfirst. + +---- + +TFB_DrawImage +------------- + +These routines are similar to a subset of the TFB_DrawScreen commands, +except that instead of drawing on the screen at some later time, they +draw directly and immediately onto a TFB_Image. The arguments all +mean the same things as they did for TFB_DrawScreen. + +---- + +void TFB_DrawImage_Line (int x1, int y1, int x2, int y2, + int r, int g, int b, + TFB_Image *dest); + +void TFB_DrawImage_Rect (PRECT rect, + int r, int g, int b, + TFB_Image *image); + +void TFB_DrawImage_Image (TFB_Image *img, + int x, int y, + BOOLEAN scaled, + TFB_Palette *palette, + TFB_Image *target); + +void TFB_DrawImage_FilledImage (TFB_Image *img, + int x, int y, + BOOLEAN scaled, + int r, int g, int b, + TFB_Image *target); + +---- + +TFB_DrawCanvas +-------------- + +These routines are, quite literally, identical in every way to the +TFB_DrawImage routines, except that they draw on TFB_Canvases instead. +They are defined in graphics-library-specific locations. There is, at +present, only one implementation of these, in +libs/graphics/sdl/canvas.c. + +void TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2, + int r, int g, int b, + TFB_Canvas dest); + +void TFB_DrawCanvas_Rect (PRECT rect, + int r, int g, int b, + TFB_Canvas image); + +void TFB_DrawCanvas_Image (TFB_Image *img, + int x, int y, + BOOLEAN scaled, + TFB_Palette *palette, + TFB_Canvas target); + +void TFB_DrawCanvas_FilledImage (TFB_Image *img, + int x, int y, + BOOLEAN scaled, + int r, int g, int b, + TFB_Canvas target); + +---- + +Creation and Destruction of TFB_Images, TFB_Canvases, and TFB_Palettes +---------------------------------------------------------------------- + +Various commands exist for creating and destroying the TFB_Draw data +types. The concept of "ownership" is critical here. If a data object +owns a pointer inside of it, that pointer's referent is deallocated +when the data object is deallocated. If a pointer variable owns its +referent, it's permissible to delete it. + +TFB_Canvas and TFB_Palette are primitives. TFB_Image owns NormalImg, +ScaledImg, and Palette, and will delete them when it is itself +deleted. + +That said, here are the routines: + +--- + +TFB_Image *TFB_DrawImage_New (TFB_Canvas canvas) + +Creates a new TFB_Image, which the caller then owns. The caller must +own the canvas, and transfers ownership of that canvas to the image. +The Palette value is automatically created (and the image owns it); +ScaledImg will be NULL until you scale the image and draw it to the +screen. + +--- + +void TFB_DrawImage_Delete (TFB_Image *image) + +Deletes the image, and all non-NULL components. You must own the +image you delete. + +--- + +TFB_Canvas TFB_DrawCanvas_New_TrueColor (int w, int h, BOOLEAN has_alpha); + +TFB_Canvas TFB_DrawCanvas_New_Paletted (int w, int h, + TFB_Palette *palette, + int transparent_index); + +These create new TFB_Canvases, which the caller will then own. Width +and height are straightforward. The TrueColor variant produces Canvases +with the same color depth and pixel format as the screen. The +has_alpha flag indicates whether or not the canvas has an alpha +channel. + +The Paletted variant produces 8-bit paletted canvases. The palette +argument is optional (it can be NULL, in which case you'll need to set +it later - TFB_Images tend to do this when drawn), as is the +transparent_index (if -1, there is no transparency; otherwise, it's +the index of the transparent color). + +--- + +TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas); + +Returns a canvas that, if possible, matches the graphics configuration +of the screen. You must own the source canvas. If the conversion is +possible, it makes the conversion, deletes its argument, and returns +the converted version; if conversion is not possible, the canvas is +returned intact. + +Regardless of success or failure, the caller owns the result. + +--- + +TFB_Palette *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas); + +Allocates and returns a 256-entry TFB_Palette array that describes the +palette of the canvas, or returns NULL if the canvas is true-color. +If the result is non-NULL, the caller owns the result. The caller +need not own canvas. + + + DRAWCMD LIBRARY + ----------------- + +Documentation yet to be written. UQM code shouldn't really mess with +the DrawCmd library directly. diff --git a/doc/devel/gfxres b/doc/devel/gfxres new file mode 100644 index 0000000..d0b30bb --- /dev/null +++ b/doc/devel/gfxres @@ -0,0 +1,64 @@ +This is the format for resources of type GFXRES (these have the extension +.ani in the original source). + +Everything is stored MSB first unless otherwise specified. + +position length meaning + 4 0xffffffff if the file is uncompressed. + Otherwise, the file is compressed. When uncompressed, the + file complies with the rest of the format as described + below. + 4 Unused in file, always 0x00000000 + 4 FlagsAndIndex: + bits 0-11: 1 less than the number of frames in this + graphics resource + bits 12-15: flags: + - bit 0: (WANT_MASK) + - bit 1: (WANT_PIXMAP) + - bit 2: (WANT_COMPRESSED) + - bit 3: (DOUBLE_RES) + bits 16-31: unknown (0x0000) + +Frame descriptions: +Then for all frames: + 4 Type index and flags (TypeIndexAndFlags) + Low 2 bytes: + bits 0-11 is the index of this frame + bits 12-15 are the type flags: + - bit 12-13: + - 0: (ROM_DRAWABLE) + - 1: Direct drawable (RAM_DRAWABLE) + - 2: (SCREEN_DRAWABLE) + - 3: (OVERLAY_DRAWABLE) + High 2 bytes (frame flags): + - bits 0-7: global PLUT to use + - bit 12: Frame is in cel format (DATA_HARDWARE) + - bit 13: (DATA_COPY aka DATA_SCREEN) + - bit 14: (DATA_PACKED) + - bit 15: (X_FLIP) + 4 Hot spot information (definition of (0, 0) in the image): + - low 2 bytes: x location of hot spot + - high 2 bytes: y location of hot spot + 4 Image bounds: + - low 2 bytes: Image width + - low 2 bytes: Image height + 4 Offset from beginning of the frame description for this + frame to the beginning of the frame. + +Frames: +Then for all frames: + If DATA_HARDWARE is set in the flags for this frame: + 4 Size of image data + ? .cel image data + If DATA_PACKED is set in the flags for this frame: (from 3do/imageint.c) + for every line in the image (bounds.height lines): + 2 number of bytes used to encode this line + The actual number of bytes is computed like so: + (number-of-bytes + 2) * 4 + a number of packets of this format: + + + +Initial version 2002-10-22, by Serge van den Boom + + diff --git a/doc/devel/gfxversions b/doc/devel/gfxversions new file mode 100644 index 0000000..d82706e --- /dev/null +++ b/doc/devel/gfxversions @@ -0,0 +1,60 @@ +Chnages between DOS and 3DO graphics. +[Unless stated otherwise, UQM does things 3DO way] + +---------------------------------------------------------------------- +Melee +---------------------------------------------------------------------- +1. Minor ship small icon changes +Icon offset horz by 1 pixel: VUX, ZoqFot, Melnorme, Supox +Facelifted: Utwig + +2. Ship/weapon rendering changes +*Yehat* +On DOS, Yehat shield was a set of separate shield-only images which +were composited with the ship; on 3DO, the shield images already include +the ship. +*Umgah* +On DOS, Umgah cone was a composite of a cone mask + spritz images; +on 3DO, cone images multiplied 3x and are already a combination of +cone + spritz. +*Blackurq* [Kohr-Ah] +Ship images were regenerated for 3DO with a light source +at a different position (so the angle is diff). This improved the overall look +of the ship, especially frame 14, which was simply ugly on DOS. +And, of course, the FRIED is blue on 3DO and was yellow on DOS. +*Chenjesu* +Not really a change, med.14 frame has bad transparency info on DOS. +*Utwig* +DOS has apparently derelict ship frames (16-18). +HYPOTHESIS: ship special was originally intended to be some entirely +different. +*Sa-Matra* +The captain portrait is bigger in UQM (same size on DOS and 3DO). + +4. Misc +lbm/stars has an extra frame (2) in 3DO, afaik, it is not used. + +5. Planet images +On DOS, planet images were paletted, and there were 14 topographical types +(2 were identical) with ~60 palettes; on 3DO, images are truecolor (except +for Shielded planet), and the 2 identical topographies have been fixed (so +they are different now). + +---------------------------------------------------------------------- +Inter-planetary (IP) +---------------------------------------------------------------------- +1. Planets +On DOS, IP planets were all pre-generated (all phases, colors, sizes); +On 3DO, planet phases and size are pre-generated and rendered using colormaps +that define planet color. + +2. Many changes in Planet Rotation (scan view) + +3. Suns +On DOS, suns have different colors; on 3DO, they are all yellow; UQM has +been patched to render suns in different colors like DOS. + +---------------------------------------------------------------------- +Misc +---------------------------------------------------------------------- +1. SIS engine color was green-yellow on DOS and is red on 3DO diff --git a/doc/devel/glossary b/doc/devel/glossary new file mode 100644 index 0000000..2ecbba5 --- /dev/null +++ b/doc/devel/glossary @@ -0,0 +1,6 @@ +Abbreviations used in the code: + +IP interplanetary +NPC non-player character +SIS Super-Integrated-Starship (the flagship) + diff --git a/doc/devel/historical b/doc/devel/historical new file mode 100644 index 0000000..63697ff --- /dev/null +++ b/doc/devel/historical @@ -0,0 +1,39 @@ +This file is intended as a place to document historically interesting +curiosities in the UQM source and content, which have been deleted from +the current source/content tree. + +This file is probably not complete. + + +== .res files === + +The Star Control source code contained files with the extension .res, which +contained a description of the packages (.pkg or .ndx) files to be generated. + +There were .res files for each ship and each race which you can communicate +with. These files 'included' the file 'star3do.res', which itself included +'star3do.typ'. + +There were also header files icode.h, igfxres.h, imusicre.h, isndres.h, +istrtab.h, resinst.h, respkg.h and restypes.h in each of the ship and comm +directories, which defined a few resource constants, which were presumably also +generated from these .res files. + + +== Outtake not taken out == + +There was an outtake accidentally left in the original speech for the Druuge. +It can still be found at + http://sc2.svn.sourceforge.net/viewvc/*checkout*/sc2/trunk/sc2/content/comm/druuge/druug011.ogg?revision=133&pathrev=1113 + + +== Original title screen and menu == + +The original title screen -- which included the text 'Star Control' and +'Accolade' and could hence not be used in UQM -- can be found at + http://sc2.svn.sourceforge.net/viewvc/sc2/trunk/sc2/content/lbm/title.tga?revision=6&pathrev=6 +The original main menu (which did not include 'setup' or 'quit' options) +can be found at + http://sc2.svn.sourceforge.net/viewvc/sc2/trunk/sc2/content/lbm/newgame0.tga?revision=6&pathrev=6 + + diff --git a/doc/devel/input b/doc/devel/input new file mode 100644 index 0000000..ca48e00 --- /dev/null +++ b/doc/devel/input @@ -0,0 +1,126 @@ +Input system notes + +Code that reads the input state defines a routine that goes through +the DoInput routine. This is handled in a pseudo-OOP style. + +An "INPUT_STATE_DESC" has the following members: + +BOOLEAN (*InputFunc) (PVOID pInputState); +COUNT MenuRepeatDelay; + +Although a "PVOID", pInputState has to be safely castable to +INPUT_STATE_DESC. There are various "subclasses" that are used for +this purpose throughout the code. They are also pased to the first +argument of DoInput. + +The InputFunc returns TRUE if it still will be keeping control next +frame. + +MenuRepeatDelay is an "internal" variable for making keyrepeat work +right. + +"Subclasses": + +MENU_STATE - in starbase.h. The "pMenuState" global is usually the +element referenced. This is used by: + + encount.c: DoSelectAction + gameopt.c: DoGameOptions, DoSettings, DoTextEntry, DoNaming, + DoQuitMenu, DoPickGame + outfit.c: DoOutfit + pickship.c: DoPickBattleShip + restart.c: DoRestart + shipyard.c: DoModifyShips, DoShipYard + starbase.c: DoStarBase + + cargo.c: DoDiscardCargo + devices.c: DoManipulateDevices + lander.c: DoPlanetSide + pstarmap.c: DoMoveCursor, DoFlagshipCommands + roster.c: DoModifyRoster + scan.c: DoScan, PickPlanetSide + +VIDEO_INPUT_STATE - in vidplayer.c. Used by TFB_DoVideoInput. + +ENCOUNTER_STATE - in comm.c. Used by DoCommunication. + +MELEE_STATE - in melee.h. Used by DoPickShip, DoLoadTeam, DoEdit, DoMelee. + +The game logic itself that uses DoInput treats it as a stack of state +machines. The "current state" is in the InputFunc field of the +argument. + +The state machines are (with the calls that initialize and allocate them): + +InitCommunication: DoCommunication +DoMenuOptions, ExploreSolarSys: DoFlagshipCommands <-> DoDiscardCargo + <-> DoManipulateDevices +Roster: DoModifyRoster +DoMelee <-> DoEdit <-> DoLoadTeam <-> DoPickShip +VisitStarBase: DoStarBase <-> DoOutfit <-> DoInstallModule + <-> DoShipyard <-> DoModifyShips +DoStarMap: DoMoveCursor +GameOptions: DoGameOptions <-> DoNaming <-> DoSettings <-> DoQuitMenu + <-> DoPickGame +GetArmadaStarShip: DoPickBattleShip +StartGame: DoRestart +ScanSystem: DoScan <-> PickPlanetSide <-> DoPlanetSide +InitEncounter: DoSelectAction +TFB_VideoInput: TFB_DoVideoInput + +These are called from the following points: + +InitCommunication: Called by the outtakes, the starbase, and the gen* + files; generally anywhere where you need to + transfer over to a conversation sequence. + RaceCommunication () is the toplevel call for + starcon.c. + +DoMenuOptions: Called by the postprocess operation for the sis_ship. + +ExploreSolarSys: Called by Starcon2Main. + +VisitStarBase: Called by Starcon2Main. + +DoStarMap: Called internally by DoFlagshipCommands. + +GameOptions: Called internally by DoOutfit, DoShipyard, + DoSelectAction, and DoFlagshipCommands. Basically + handles the GAME menu wherever it appears. + +GetArmadaStarShip: Called internally by + GetEncounterStarShip. UninitShips calls + GetEncounterStarShip, apparently to do cleanup. + Everyone else calls GetNextStarShip. This is done + by the Battle() routine, and by the new_ship + function, which is assigned as a "death_func" for + normal ships, and a "preprocess_func" for dead + ships. + +StartGame: Called by Starcon2Main. + +ScanSystem: Called by DoFlagshipCommands + +InitEncounter: Called by InitCommunication when the player has an option. + +TFB_VideoInput: UQM's game logic will reach it by calling DoFMV. + +Starcon2Main +------------ + +This is a loop for the game. Right now I just have a list of +top-level calls, and a list of checks made against +GLOBAL(CurrentActivity). The actual significance of these things +comes later. + +Activities: CHECK_LOAD, START_ENCOUNTER, CHECK_ABORT, + IN_INTERPLANETARY, START_INTERPLANETARY, WON_LAST_BATTLE, + CHECK_RESTART, IN_HYPERSPACE + +Game states: CHMMR_BOMB_STATE, GLOBAL_FLAGS_AND_DATA, KOHR_AH_KILLED_ALL + +Functions: Logo(), StartGame(), VisitStarBase(), RaceCommunication(), + ExploreSolarSys(), Battle(). Note that Battle() here is + actually for hyperspace travel. Super Melee combat is + handled in DoMelee, and full-game combat is handled by + EncounterBattle, called by InitCommunication. diff --git a/doc/devel/livecd b/doc/devel/livecd new file mode 100644 index 0000000..a3e3bb9 --- /dev/null +++ b/doc/devel/livecd @@ -0,0 +1,80 @@ +This file contains notes about considerations for developing a live CD +for UQM. + + +Information on creating boot CD's: +- http://www.geocities.com/potato.geo/bootlinuxcd.html +- man mkisofs +- http://linuxfromscratch.org/~jhuntwork/livecd/ +- http://www.tldp.org/HOWTO/Bootdisk-HOWTO/ + + +Desirable features: +- Both Linux native mode (when booting directly from the CD), + an MS Windows autorun. And perhaps even MacOS boot. +- install from the CD (for Windows) +- Support saving + + +- Needed software: + - boot loader + syslinux: ftp://ftp.kernel.org/pub/linux/utils/boot/syslinux/ + - init (simpleinit?) + - libc (including libpthread) (uClibc)? + - libSDL + - libSDL_image + - libpng (needed for libSDL_image) + - libvorbisfile + - libvorbis (for libvorbisfile) + - libogg (for libvorbis) + - libmikmod + - libm (for libvorbis) + - libz (for zipped content) + - syslogd+klogd? + + Some audio library: + - libasound (prefered) + + Some graphics output: one of + - x11 (larger than necessary) + - nanox + - fbcon (may be the best solution) + - directfb + - svgalib (directly accesses the VGA card. No acceleration support) + (may be the most portable) + Having hardware acceleration support may be useful. + + For basic debugging: + - sulogin + - sash or busybox (minimal features) + + For hardware detection: + - udev + - ... + +- Other needed files: + - boot scripts + - /etc/ld.so.conf + - ... + +- Sources + Sources must be provided in some way (check the licenses of the + dependencies). + +- Warranty disclaimer on boot + + +For saving: +- USB memory stick and other memory devices +- Windows hard drive (where to put the files?) +- Linux hard drive (where to put the files?) +- Floppies? Probably not worth it. + + + +Tools for testing before burning: +- vmware +- QEMU (http://fabrice.bellard.free.fr/qemu/) + + + diff --git a/doc/devel/meleeteams b/doc/devel/meleeteams new file mode 100644 index 0000000..524f2cf --- /dev/null +++ b/doc/devel/meleeteams @@ -0,0 +1,56 @@ +This file describes the binary file format for SuperMelee teams. +The saving and loading is handled in sc2code/loadmele.c. + +This file format will be replaced by a human-readable format in the future. + +A SuperMelee team consists of the following data: + struct TEAM_IMAGE { + 0 - 13 uint8_t ShipList[MELEE_FLEET_SIZE]; + /* Originally 6*2 ships, now 7*2 */ +14 - 68 char TeamName[MAX_TEAM_CHARS + 1 + 24]; + /* \0-terminated */ + }; + +The file melee.cfg contains: + 0 - 0 Player Control for the bottom player + One of: + 1 - Human controlled + 6 - Computer controlled + 8 - Network controlled (added later) + or'ed with one of: + 16 - Standard computer control rating (was 8 originally) + 32 - Good computer control rating (was 16 originally) + 64 - Awesome computer control rating (was 32 originally) + 1 - 69 TEAM_IMAGE for the top player, as described above +70 - 70 Player Control for the top player, as byte 0 +71 - 139 TEAM_IMAGE for the bottom player, as described above +Note the mixed up order for top and bottom player. + +The entries in ShipList are: + 0 - Androsynth Guardian + 1 - Arilou Skiff + 2 - Chenjesu Broodhome + 3 - Chmmr Avatar + 4 - Druuge Mauler + 5 - Human Earthling + 6 - Ilwrath Avenger + 7 - Kohr-Ah Marauder + 8 - Melnorme Trader + 9 - Mmrnmhrm X-Form + 10 - Mycon Podship + 11 - Orz Nemesis + 12 - Pkunk Fury + 13 - Shofixti Scout + 14 - Slylandro Probe + 15 - Spathi Eluder + 16 - Supox Blade + 17 - Syreen Penetrator + 18 - Thraddash Torch + 19 - Umgah Drone + 20 - Ur-Quan Dreadnought + 21 - Utwig Jugger + 22 - VUX Intruder + 23 - Yehat Terminator + 24 - Zoq Fot Pik Stinger +255 - Unused slot + diff --git a/doc/devel/musicres b/doc/devel/musicres new file mode 100644 index 0000000..780ee2b --- /dev/null +++ b/doc/devel/musicres @@ -0,0 +1,18 @@ +This is the format for resources of type MUSICRES (these have the extension +.mod in the original source). + +If the first 3 characters are 'CDA', from the next character to the first +nul char, or 3 characters after the first period (whatever comes first) is +used as a filename with aif audio data to play. (CDA stands for CD-audio. +The source code mentions 'red book', but it's not (red book is the standard +for audio CD's)). The rest of the file (just a few more chars) seems to be +garbage. + +If the first 3 characters are something else, the entire file (including the +first 3 characters) are used as a MOD file. (As the mod file uses those char +as the title of the song, a mod file with the title beginning with 'CDA' +will go wrong). + + +Initial version of this file 2002-10-26 by Serge van den Boom. + diff --git a/doc/devel/netplay/notes b/doc/devel/netplay/notes new file mode 100644 index 0000000..afac628 --- /dev/null +++ b/doc/devel/netplay/notes @@ -0,0 +1,21 @@ +As the game currently unfortunately works with polling, this is how +to integrate network handling with the game. + +In the function called periodically by DoInput(), there should be a call +to netInput() somewhere at the beginning, and a call to flushPacketQueues() +somewhere at the end. + +netInput() checks all connections for incoming packets, and calls +the appropriate packet handlers. + +flushPacketQueues() sends all pending packets on their way, for all +connections. + +In between, you can call functions that enqueue packets. +You would also check the network state here to determine whether you need to +act on some packet that has been delivered to the local party. + + + + + diff --git a/doc/devel/netplay/protocol b/doc/devel/netplay/protocol new file mode 100644 index 0000000..5b82a1f --- /dev/null +++ b/doc/devel/netplay/protocol @@ -0,0 +1,336 @@ +There are several types of negotiations used to synchronised the parties +of a network connection. + +- Continue when we know the other is ready ("Ready") + This is used when both parties need to sending information to the + other side, but what each party is doing does not interfere with + what the other party is doing. +- Agree on changes ("Update") + This is used when the parties have changes to make to common data. +- Mutual agreement on an action ("Confirm") + This is used to end a state where both parties are modifying + common data. Both parties have to agree with the data for either + party to continue. +- Reset a connection. This is used to abort a game in progress and return + to the fleet setup menu. + +============================================================================ + +"Ready" negotiation. + +Sometimes the parties need to notify eachother of their local state, +and then go on when both are ready. For this purpose both parties signify +that they are ready by sending the READY message. When a party is ready +and has received notice that the other party is ready, it can go on. + +States: +0. notReady - send nor received READY + !localReady && !remoteReady +1. localReady - sent READY, not yet received READY + localReady && !remoteReady +2. remoteReady - received READY, not yet sent READY + !localReady && remoteReady +3. ready - sent and received READY + +Messages: +- READY - "I have nothing further to send at this point" + + +From state 0 (notReady): +local decision -> Send READY, goto 1 +received READY -> goto 2 + +From state 1 (localReady): +received READY -> goto 3 + +From state 2 (remoteReady): +local decision -> Send READY goto 3 + + +============================================================================ + +"Update" negotiation. + +During configuration, both sides may change the same properties. So that the +two sides don't have to take turns, the changes are made locally, and then +the changes are synchronised. + +To this end, each side has a state containing two copies of each property: + 1. The value of the property as it is locally + 2. The last value which it sent to the other side (until it is no longer + relevant for the protocol) + +The basic idea of the Update protocol is: +- both sides each send and receive one packet before being allowed to + send another one (we'll call this a "turn" here) +- when a packet has been sent and one has been received in a turn, + and the sent and received values are the same, then that value is the + agreed upon value. If the sent and received values differ, then a + tie breaker determines which one prevails. +- when the first local change of a turn is made, the change is sent to + the other side +- when a local change has been made while a packet has already been + sent this turn, the change will be made locally, but communicating the + change will be postponed +- when a turn ends while a change has been postponed, and this change isn't + negated by a remote change, then the change will be sent +- when a remote change arrives, and a packet has not been sent this turn, + the local state is updated with the change, and the same packet is sent + to the other side to confirm the change + +The tie breaker is required to always let one side win, and the other +side lose, given the same property. +Any function satisfying this requirement is usable, but the currently +used one will return true for the side which 'owns' the property, and +false on the other side. +Another tie breaker could be one which always lets the same side win, +regardless of the property. + + +The protocol: + +From state 1, {own=x0, sent=--}: +1a Local change x1 -> send(x1); state=2:{own=x1,sent=x1} +1b Received UPDATE(x1) -> send(x1); state=1:{own=x1,sent=--} + +From state 2, {own=x0, sent=x0}: +2a Local change x1 -> state=3:{own=x1,sent=x0} +2b Received UPDATE(x0) -> state=1:{own=x0,sent=--} +2c+ Received UPDATE(x1) -> state=1:{own=x0,sent=--} if winTieBreak +2c- Received UPDATE(x1) -> state=1:{own=x1,sent=--} if !winTieBreak + +From state 3, {own=x1, sent=x0}: +3a Local change x0 -> state=2:{own=x0,sent=x0} +3b Local change !x0 -> state=3:{own=xN,sent=x0} +3c Received UPDATE(x0) -> send(x1); state=2:{own=x1,sent=x1} +3d+ Received UPDATE(!x0) -> send(x1); state=2:{own=x1,sent=x1} if winTieBreak +3d- Received UPDATE(!x0) -> state=1:{own=x?,sent=--} if !winTieBreak + + +Explanation: +We keep track of the local value ('own'), and whether or not we sent a packet +in this turn ('sent' != '--'), and if we did, the last packet which we sent +('sent'). When we proceed to the next turn, 'sent' is set to '--'. + +State 1: We have not yet sent a packet this turn (which implies that we +haven't made a local change this turn). +1a. A local change is made. We update our local value, and send this to + the remote side. +1b. A remote change arrives. We don't have any local change ourselves, + so we accept the remote change, and sent it back to confirm. + With both a packet sent and one received, the turn ends, and 'sent' + is set back to '--'. + +State 2: We have sent a packet this turn (after making a local change), and +have not changed our local value since (or we have changed it and changed +it back). +2a. A local change is made. We update our local value, but we have already + sent a packet this turn, so we can't report it until the next turn. +2b. A remote change arrives, and it is equal to both our local value and + the value which we sent to the other side this turn. + This remote notification may be a confirmation of our update, or a + coincidental identical remote change. + Either way, the packet acts as a confirmation, and we do not need + to change anything. With both a packet sent and received, the turn ends + and so 'sent' is set back to '--'. +2c. A remote change arrives, and it is not equal to our local value (which + is the same as the value which we sent). + The tie breaker decides which value prevails. The same value will + prevail on the remote side, so there is no need to send any confirmation + packets. The turn ends, and 'sent' is set back to '--'. + +State 3: We have sent a packet this turn, and have made a local change since. +3a. A local change is made back to the value which we sent. No action + is required. +3b. A local change is made. We update our local value, but we have already + sent a packet this turn, so we can't report it until the next turn. +3c. A remote change arrives, and it is equal to the value which we sent + (which isn't equal to the current local value). + The sent/received value is the accepted value and the turn ends. + But we have changed our value since already, so as the next turn + starts, we immediately send an update. +3d. A remote change arrives, and it is not equal to the value which we sent + this turn. + + We win the tie break, so the value which we sent prevails. + But we have changed our value since already, so as the next turn + starts, we immediately send an update. + - We lose the tie break, so the value which the remote value sent + prevails. We accept the value and the turn ends. + (An alternative would be to consider the local change(s) which + we made after our change was sent as made in the following turn, + in which case we would send our current local value in the next turn. + The advantage would be that 3d- would become equal to 3d+, + so these could be joined (with 3c too), which saves a few + if-statements in the code, but this requires another packet to be sent + and replied to in what currently is 3d-.) + + +Proof outline that this works: +- The states can never get out of sync: + After both a packet has been sent and received, both sides (temporarilly) + have accepted the same value +- There can be no indefinite loop without ongoing local changes. + Once there are no more local changes: + from state 3 we always go to state 2 or 1, + from state 2 we always go to state 1 + from state 1 we can only go back to state 1, and only when a packet + has been received. + So eventually, both sides are in states 1. With both sides in state 1, + no packets have been sent in the current turn, so no more packets are + there to be received. +- Both sides can make changes, as long as the side which wins the tie breaks + stops making changes now and then: + Without making local changes, a side will go to state 1 eventually. + If a side makes a local change, and this is received by the other side + while it is in state 1, then that other side will accept the change. + + +The Confirm negatiation is used to finish the Update negotiation. +This works because local changes triggered by the reception of remote changes +are treated as local modifications for the purpose of the Confirm negotiation. +And this can be done because whenever the Confirm negotiation is in a state +where remote changes may be expected, local modifications are still allowed +(possily after sending a CANCEL packet). + + +============================================================================ + +"Confirm" negotiation. + +Some actions (like agreeing on a configuration) require confirmation +from both parties. This section documents the handshaking protocol involved. + +Each player must manually confirm the action. +After a player has confirmed an action, he may cancel it as long as +he hasn't received a confirmation from the other party. + +All messages arrive in the order sent. + + +States: +0. waiting + !handshake.canceling && !handshake.localOk && !handshake.remoteOk +1. localOk (cancelable) - sent CONFIRM1 (since last CANCEL) + !handshake.canceling && handshake.localOk && !handshake.remoteOk +2. remoteOk (cancelable) - received CONFIRM1 + !handshake.canceling && !handshake.localOk && handshake.remoteOk +3. committed - sent CONFIRM1 (since last CANCEL, + received CONFIRM1, + sent CONFIRM2 (since last CANCEL) + !handshake.canceling && handshake.localOk && handshake.remoteOk +4. cancelWaiting - sent CANCEL + handshake.canceling && !handshake.localOk && !handshake.remoteOk +5. cancelLocalOk - sent CANCEL and ready to send CONFIRM1, + but received no CANCELACK + handshake.canceling && handshake.localOk && !handshake.remoteOk +6. cancelRemoteOk - sent CANCEL and received CONFIRM1, + but received no CANCELACK + handshake.canceling && !handshake.localOk && handshake.remoteOk +7. cancelCommitted - sent CANCEL and ready to send CONFIRM2, + received CONFIRM1, + but received no CANCELACK + handshake.canceling && handshake.localOk && handshake.remoteOk +8. done - sent and received CONFIRM1 and CONFIRM2 + (since last CANCEL) + + +Handshake messages: +- CONFIRM1 - "the current local configuration is OK for me" +- CONFIRM2 - "acknowledging your CONFIRM1; my own configuration is unchanged + since I sent CONFIRM1 (after the last CANCEL)" +- CANCEL - "forget about my earlier CONFIRM1" +- CANCELACK - "received your CANCEL" +MESSAGE(x) indicates any other message. + + +From state 0: (waiting) +local confirmation -> Send CONFIRM1, goto 1 +local changes -> Send MESSAGE(changes) (goto 0) +received CONFIRM1 -> goto 2 +received MESSAGE(changes) -> Process(changes) (goto 0) + +From state 1: (localOk) +local cancel -> Send CANCEL, goto 4 +received CONFIRM1 -> Send CONFIRM2, goto 3 +received CONFIRM2 -> Send CONFIRM2, goto 8 +received MESSAGE(changes) -> Send CANCEL, Process(changes), goto 4 + +From state 2: (remoteOk) +local confirmation -> Send CONFIRM2, goto 3 +local changes -> Send MESSAGE(changes), (goto 2) +received CANCEL -> Send CANCELACK, goto 0 + +From state 3: (committed) +received CONFIRM2 -> goto 8 +received CANCEL -> Send CANCELACK, goto 1 + +From state 4: (cancelWaiting) +local changes -> Send MESSAGE(changes), (goto 4) +local confirmation -> goto 5 +received CONFIRM1 -> goto 6 +received CONFIRM2 -> goto 6 +received CANCELACK -> goto 0 +received MESSAGE(changes) -> Process(changes), (goto 4) + +From state 5: (cancelLocalOk) +local cancel -> goto 4 +received CONFIRM1 -> goto 7 +received CONFIRM2 -> goto 7 +received CANCELACK -> SEND CONFIRM1 goto 1 +received MESSAGE(changes) -> Process(changes), goto 4 + +From state 6: (cancelRemoteOk) +local confirmation -> goto 7 +local changes -> Send MESSAGE(changes), (goto 6) +received CONFIRM2 -> (goto 6) +received CANCEL -> Send CANCELACK, goto 4 +received CANCELACK -> goto 2 + +From state 7: (cancelCommitted) +received CONFIRM2 -> (goto 7) +received CANCEL -> Send CANCELACK, goto 5 +received CANCELACK -> Send CONFIRM2, goto 3 + +On receiving local confirmation, sending CONFIRM2 is a shortcut for +sending CONFIRM1 followed by CONFIRM2. Receiving CONFIRM2 from localOk +and cancelLocalOk is accepted just for this shortcut. + + +To prove there are no race conditions, I examine all the combinations +of states and messages that are underway. Whenever the order of actions +isn't fixed, the result should be the same (eg. recv(CONFIRM1) followed +by send(CANCEL) should leave the party in the same state as when +the send(CANCEL) preceded the recv(CONFIRM1)). +I also check whether it is possible for packets to arrive that +aren't expected. + + +============================================================================ + +"Reset" negotiation. + +See src/sc2code/netplay/proto/reset.c + + +============================================================================ + +Battle ending negotiation. + +This negotation consists of: +1. a 'Ready' negotiation, before stopping sending frame data +2. communication of each sides current battle frame count +3. the side running behind processes more frames to catch up + + +States: + +0. Playing +1. localReady +2. remoteReady +3. countSent +4. catchingUp +5. awaitingCatchup + +// Unfinished... partially described in readyForBattleEndPlayer() + + diff --git a/doc/devel/netplay/states b/doc/devel/netplay/states new file mode 100644 index 0000000..9727172 --- /dev/null +++ b/doc/devel/netplay/states @@ -0,0 +1,178 @@ +== Any connected state == +Some packets may be sent and received in any state except +NetState_unconnected. +These are: PING, ACK, ABORT, RESET +These are not listed below at each individual state. + +Whenever a connection is aborted, the state is returned to +NetState_unconnected. This state transition is not listed below at each +individual state. + + +== NetState_unconnected == +NetState_unconnected is the initial state. + +NetConnection.state: NULL + +Packets ok to send: none +Packets ok to receive: none + +Next state: + NetState_connecting -- connection attempt in progress + + +== NetState_connecting == +NetState_connecting indicates that a connection is in progress. + +When the connection is established, the state is changed to NetState_init +and InputFunc is set to DoNetworkInit. + +NetConnection.state: instance of ConnectStateData + +Packets ok to send: none +Packets ok to receive: none + +Next state: + NetState_init -- connection established + + +== NetState_init == +NetState_init is for initialising the connection before actual game +information is sent. + +As this state is entered, an INIT packet is sent. When an INIT packet +has also been received, the state is set to NetState_inSetup and +InputFunc is set to DoMelee. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: INIT +Packets ok to receive: INIT + +Next state: + NetState_inSetup -- received an INIT packet + + +== NetState_inSetup == +NetState_inSetup is the state in which the fleet configuration is negotiated. + +This does not necessarilly mean that the fleet setup screen is visible; +this state is also held after a battle when the battle outcome is still +displayed. + +Each side may send fleet configuration changes to the other side, by means of +FLEET and TEAMNAME packets. Agreement on configuration settings is provided +through the Update negotiation. +The Confirm negotiation is used to end this state and go to +NetState_preBattle. At this time InputFunc is set to DoPreMelee. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: FLEET, TEAMNAME, HANDSHAKE0, HANDSHAKE1, + HANDSHAKECANCEL, HANDSHAKECANCELACK +Packets ok to receive: FLEET, TEAMNAME, HANDSHAKE0, HANDSHAKE1, + HANDSHAKECANCEL, HANDSHAKECANCELACK + +Next state: + NetState_preBattle -- configuration has been confirmed + + +== NetState_preBattle == +NetState_preBattle is used for non-interactive battle negotiations. + +One side sends the random seed; the other receives it. +Both sides send their input delay value. +The Ready negotiation is used to end this state and go to +NetState_interBattle. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: SEEDRANDOM, INPUTDELAY, READY +Packets ok to receive: SEEDRANDOM, INPUTDELAY, READY + +Next state: + NetState_interBattle -- ready to continue + + +== NetState_interBattle == +NetState_interBattle is used to allow each side to do some local +initialisations before moving on. +The Ready negotiation is used to end this state and go to +NetState_selectShip, or if all sides have selected a ship, to +NetState_inBattle, or if there are no more ships in a fleet, +to NetState_inSetup. + +If there are no more ships, the the Ready negotiation is used to +enter NetState_inSetup. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: READY +Packets ok to receive: READY + +Next state: + NetState_selectShip -- ready to select the next ship + NetState_inBattle -- ready to start the battle + NetState_inSetup -- no more ships; game over + + +== NetState_selectShip == +NetState_selectShip is where a side may select their ship. The other +side is waiting for notice of this selection. +As soon as the selection has been sent or received, the state is changed +back to NetState_interBattle. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: SELECTSHIP +Packets ok to receive: SELECTSHIP + +Next state: + NetState_interBattle -- a selection has been made + + +== NetState_inBattle == +NetState_inBattle is where the actual melee takes place. +Both sides send their input until the game is over, at which point +the Ready negotiation is used to end this state and go to +the NetState_endingBattle state. Until the Ready negotiation has been +completed, the simulation is continuing. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: BATTLEINPUT, READY +Packets ok to receive: BATTLEINPUT, READY + +Next state: + NetState_endingBattle -- ready to end the battle + + +== NetState_endingBattle == +NetState_endingBattle is where the local side waits for the remote +battle frame count, after it has sent its own. When it arrives, +the state changes to NetState_endingBattle2. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: BATTLEINPUT, FRAMECOUNT +Packets ok to receive: BATTLEINPUT, FRAMECOUNT + +Next state: + NetState_endingBattle2 -- we know when to end the battle + + +== NetState_endingBattle2 == +NetState_endingBattle2 is where the side with the lowest battle frame count +catches up with the other other side, while the other side waits. +The Ready negotiation is used to signal that each side is ready, +and the state changes to NetState_interBattle. + +NetConnection.state: instance of BattleStateData + +Packets ok to send: BATTLEINPUT, READY +Packets ok to receive: BATTLEINPUT, READY + +Next state: + NetState_interBattle -- get ready for the next ship + + diff --git a/doc/devel/netplay/todo b/doc/devel/netplay/todo new file mode 100644 index 0000000..33102c7 --- /dev/null +++ b/doc/devel/netplay/todo @@ -0,0 +1,120 @@ +High priority items: + + +Medium-priority: +- For the battle ending synchronisation, set the end at at least + getBattleInputDelay() + 1 frames in the future (instead of just 1), + so that there will be no hickup during the end synchronisation. + Also check this value for incoming packets. +- If a player only moves away from 'Battle!' there's no need for the other + to have to reconfirm. +- decent pause handling +- make compilation of crc.c and checksum.c conditional. +- negotiate checksum interval +- Closing and destroying of NetConnections is a terrible mess. +- Checks allConnected() shouldn't be needed if CHECK_ABORT is set + on disconnect. +- Shorten or lengthen the time between frames depending on how full the input + buffer is, to prevent one side constantly stalling when the connection in + one direction is slower than in the other direction. + + +Low-priority: +- Some difference in pictures to indicated confirmed/unconfirmed. + A check mark perhaps. +- Check whether the random seed and frame delay have been agreed before + continuing (in doConfirmSettings). +- Replacement for TOS. It is IPv4 only. +- Integrate network check functions with doInput + It will be easy to get rid of the separate threads then too. +- The state changes from interBattle to interBattle. That shouldn't happen, + but it doesn't seem to cause any problems. Need to investigate. + Addition: negotiateReadyConnections() is called again just to make sure + all sides pass this checkpoint. This is not a problem. It should be + documented in STATES though. +- More files define NETCONNECTION_INTERNAL than they should. +- voice transmission during the game (using an external lib) + read ramjee94adaptive.pdf +- Keep-alive packets. Store time of last packet sent, use alarms to determine + when to send the next one. Count received messages? +- Some way to (optionally) hide your fleet setup until the start of the + game? With either a previously determined maximum fleet value, or + just display a number to the opponent. +- (when ships stats are in the content) Negotiate the ship stats, so people + can play with non-default ships. +- Pre-fleet-setup setup + The values negotiated could include handicapping (different values for + each player) + - hide fleets (also handicapping here) + - maximum number of ships per side + - maximum ship cost per side + - ship properties +- Send taunts (prerecorded samples) at the touch of a button? + Use taunt add-on packages? Send the opponent's package before the start + of a game? + + +Future improvements/optimisations: +- For BSD sockets: use dup2() to move fds to lower values, so that less fds + have to be checked on select(). +- Use writev() to send multiple packets in one syscall, instead of + calling send() for each packet. +- Refusing games with both parties network controlled is not always + necessary. In theory it should be possible to have a client work + as "proxy". The client can watch as the actual players play the game. + Checking for "loops" would be tricky (eventually there should be a human + or computer controller for each side). +- Concurrent selection of ships. Note that if this is handled properly, it + will also be easy to take care of the "Allow Shofixti to choose last" bug. + Note that one party will still have to send his choice to the other side + first, which may be "exploited". Encryption would take care of this, + but at the least make sure the same player who gets to chose first + every time. +- meta-server. Use HTTP? Existing libs can be used, no problems with NAT, + human-readable. Speed is not an issue. +- move to UDP. Repeat past battleinput packets for each new packet that + is sent until they are confirmed. +- Once the protocol is stable: register the port number with IANA +- Per state data (in NetConnection.stateData) is unnecessarilly complicated. + Putting all fields directly in NetConnection simplifies things a lot. + It's not as generic, but this code won't be used elsewhere anyhow. +- Send captain names to the other side + + +Bugs: +- as positions are dependant on the screen resolution, you won't be able + to keep sync on games with a different resolution. +- collision detection is dependant on the images used. Using different + graphics packs will result in a desync. +- Both sides need identical battle frame rates. This value is not + negotiated. +- If one player closes the connection while the other player is selecting + a ship to put in his fleet, or loading a fleet, the "Network Control" + button won't be updated. +- If one side is computer-controlled, sync loss will occur, because the AI + uses the RNG. It needs its own RNG context. +- Pressing F10 to exit the supermelee setup when a connection is active + will cause an attempt to draw a NULL frame. (possibly the disconnect + feedback) + + +Final actions: +- Check out TODO, XXX, WORK tags +- memleak testing + - check for and remove mtrace()/muntrace() calls. +- update documentation + - FILES, also note which part of the separation they are in +- check coding style (search for '\>(') +- compile with maximum warnings + + +To put in the announcement of Netplay: +- Slow connections is acceptable. Packet loss isn't. + + +Bugs and todos unrelated to netplay. +- other player being able to choose the next ship after 3 seconds + of inactivity +- DoRunAway() shouldn't be handled in ProcessInput() + + diff --git a/doc/devel/orggenerate b/doc/devel/orggenerate new file mode 100644 index 0000000..fce2207 --- /dev/null +++ b/doc/devel/orggenerate @@ -0,0 +1,133 @@ +Note: this file describes the way in which various things were generated +in the original source. See the file 'generate' for the current system. + +============================================================================ + +The various universe related game data is generated through a call +to a solar system dependant generation function. +This function is of type PLAN_GEN_FUNC, which is a typedef to + void (*PLAN_GEN_FUNC) (BYTE control) +, where the 'control' argument specifies what type of data needs to be +generated (one of GENERATE_PLANETS, GENERATE_MOONS, GENERATE_ORBITAL, +INIT_NPCS, REINIT_NPCS, UNINIT_NPCS, GENERATE_MINERAL, GENERATE_ENERGY, +GENERATE_LIFE, or GENERATE_NAME). + +The generation function for a solar system is kept in the 'GenFunc' +field of the SOLARSYS_STATE structure. +The SOLARSYS_STATE structure contains the data for a solar system. +Currently, only one SOLARSYS_STATE structure is used at once, and +the global variable pSolarSysState points to the current one. +The GenFunc field is initialised in ExploreSolarSys(), to the value +returned by GenerateIP() in sc2code/gendef.c. Usually, this will be +'GenerateRandomIP', but for some specific solar systems a (pointer to a) +custom generation function is returned. This depends on the value of +CurStarDescPtr->Index, which contains values such as SOL_DEFINED, +MELNORME0_DEFINED, AQUA_HELIX_DEFINED, etc (see sc2code/encount.h +for the complete list). +The starmap_array in sc2code/plandata.c specifies Index for all +the solar systems in the game. + +Following are the possible values of the 'control' argument to the +generation function, with the description of how the generation function +acts on this. As the custom generation functions often only need to +change one specific aspect of this game data generation, they will +often call GenerateRandomIP() for the rest. +StarBases are handled as if they were moons. + +GENERATE_PLANETS +Pre: the global variable pSolarSysState points to the relevant solar system. +Pre: the RNG is initialised with a seed to be used for the generation. + In practice, this seed is generated from the HyperSpace coordinates + of the solar system (which are hardcoded in sc2code/plandata.c), + followed by exactly one call to TFB_Random(). +Post: the RNG is in an undefined state. +This function determines how many planets the system has, and fills in +pSolarSysState->PlanetDesc[] for all planets, including the NumPlanets +field, which determines how many moons the planet will have. +It also sets the random seed that is used for data generated for this planet +(including the number of moons), based on its coordinates (which are in the +general case randomly determined themselves). + +GENERATE_MOONS +Pre: the global variable pSolarSysState points to the relevant solar system, + which is initialised by a GENERATE_PLANETS call. +Pre: the RNG is initialised with a seed to be used for the generation. + In practice, this seed is the seed stored by GENERATE_PLANETS + in the rand_seed field for the planet around which the moon(s) orbit. +Pre: pSolarSysState->pBaseDesc points to the the relevant planet + of pSolarSysState->PlanetDesc[]. +Post: The RNG is in an undefined state. +This function fills in pSolarSysState->MoonDesc[] for all moons around +the planet pointed to by pSolarSysState->pBaseDesc. +It also sets the random seed that is used for data generated for the moon +based on its coordinates (which are in the general case randomly determined +themselves). + +GENERATE_ORBITAL +Pre: the global variable pSolarSysState points to the relevant solar system, + which is initialised by a GENERATE_PLANETS call. +Pre: pSolarSysState->pOrbitalDesc points to the relevant planet or moon from + pSolarSysState->PlanetDesc[] or pSolarSysState->moonDesc[] +Pre: the planet or moon that pSolarSysState->pOrbitalDesc points to + is initialised by a GENERATE_PLANETS or GENERATE_MOONS call. +This function fills in pSolarSysState->SysInfo with the characteristics +of the planet or moon, as seen from orbit. +It also initialises the random seeds used for the generation of bio, +minerals, and energy nodes on the surface. +It also sets the discovery report string (if appropriate), initialises +the surface graphics, and start the planet music. +For specific planets, it may initiate race communication and possibly combat, +and will only return once these are over. +NB. The GENERATE_ORBITAL code should be split up into separate calculation +and activation (graphics and music) parts. + +GENERATE_MINERAL, GENERATE_ENERGY, GENERATE_LIFE +Pre: the global variable pSolarSysState points to the relevant solar system, + which is initialised by a GENERATE_PLANETS call. +Pre: pSolarSysState->pOrbitalDesc points to the relevant planet or moon from + pSolarSysState->PlanetDesc[] or pSolarSysState->moonDesc[] +Pre: the planet or moon that pSolarSysState->pOrbitalDesc points to + is initialised by a GENERATE_PLANETS or GENERATE_MOONS call. +Pre: pSolarSysState->SysInfo is filled in by a GENERATE_ORBITAL call +This function determines the properties of one mineral deposit, energy node, +or life form on a planet or moon. On entry the caller sets +pSolarSysState->CurNode to the index of the requested item. This function +will then fill in pSolarSysState->SysInfo.PlanetInfo.CurPt, +pSolarSysState->SysInfo.PlanetInfo.CurType, and in the case of minerals also +pSolarSysState->SysInfo.PlanetInfo.CurDensity. +In case pSolarSysState->CurNode is set to a value larger than or equal to +the number of items of the requested kind ((COUNT) ~0 in practice), it is +set to the real number of nodes. In this case the CurXXX fields of +pSolarSysState->SysInfo.PlanetInfo are set to the values corresponding to +the largest valid CurNode index, but should probably be considered to be +undefined. +These functions may also change the game state, cause the lander +to take off (by setting InTransit to true in the active PLANETSIDE_DESC +structure), or mark an energy node as not retrieved, usually in response +to an item having been picked up since the last call. The game makes +a GENERATE_MINERAL, GENERATE_ENERGY or GENERATE_LIFE call (whatever +is relevant) for each item right after it is picked up. + +GENERATE_NAME +Pre: pSolarSysState is set to the relevant solar system. +Pre: The planet is initialised by GENERATE_PLANETS. +Pre: pSolarSysState->pBaseDesc points to the relevant planet, which should + be in the system. +This function fills GLOBAL_SIS (PlanetName) with the name of the planet +pointed to by pSolarSysState->pBaseDesc. +It also sets the GAME_STATE flag BATTLE_PLANET to the type of this planet, +so that it will be shown appropriately in melee if combat follows. +There is no generate function for the names of moons. The few moons that +are named (those in the Sol system), are handled as a special case of +the routines that prints these names (PrintCoarseScan3DO and +PrintCoraseScanPC). + +INIT_NPCS +REINIT_NPCS +UNINIT_NPCS +[TODO] + + +Initial version of this document created by Serge van den Boom, on 2005-07-11. + + diff --git a/doc/devel/pkgformat b/doc/devel/pkgformat new file mode 100644 index 0000000..69a2513 --- /dev/null +++ b/doc/devel/pkgformat @@ -0,0 +1,174 @@ +The .pkg/.ndx format as used for Starcon.pkg on the 3DO cd. +Acquired directly from the source. + +This format is used both in the file and is memory. There are some +little differences; where this is this is the case, this is +mentioned below in square brackets. + +Everything is stored LSB first. + +This document talks about packaged files. +Packaged files have multiple resources stored in one file. All the resources +in one package are stored in a single file, whose name is specified in +p.packmem. The name may be '\0', in which case the package file itself +is used. +Non-packaged files have one resource per file. The name is specified +in each resource instance info field. + +Main header: (resinit.c, _GetResFileData()) +position length meaning +0x00 2 Whether or not the file is packaged (res_flags) + bit 0: 0 - the .pkg file is not packaged + 1 - the .pkg file is packaged +0x02 4 offset from the beginning of the file where the list + of package information is stored (packmem_list_offs) +0x06 4 offset from the beginning of the file where the list + of pathnames is stored (path_list_offs) +0x0a 4 offset from the beginning of the file where the list + of file names is stored (file_list_offs) +0x0e 2 number of packages in the file (num_packages) +0x10 2 number of types of packages present in the file (num_types) +0x12 4 length of this header. (index_info.header_len) + (unused if the .pkg file is not packaged) +0x16 8*num_packages: + On position i the information for package i + 1 is + stored. There is no package 0. + 4 p.packmem_info + bits 0-7: number of resource types + bits 8-20: number of resource instances + bits 21-31: + For packaged files: index in file_list_offs of the + file name for this resource + For non-packaged files: unused (0) + 4 p.flags_and_data_loc + MSB is flags, rest is data_loc, + if MSB == 0, then of the data_loc only the low 16 bits + are used as a MEM_HANDLE [only in memory], + if MSB == 0xff, then the data_loc is an offset in the + file to the actual data +0x16+8*num_packages Type information + 2*num_types + t.instance_count + The number of instances there are of this type. + On position i the instance count for type i + 1 is + stored. There's no type 0. +packmem_list_offs (should be directly after the index info): + for each of the num_packages packages: + for each of the resource types for this package + (as in p.packmem_info): + 4 bits 0-7: The type number for this type. What that + number means isn't specified, and may + vary per .pkg file. + For the 3DO SC2 starcon.pkg file these are: + 0 - not a type + 1 - Graphics data (GFXRES) + 2 - String data (STRTAB) + 3 - Music data (MUSICRES) + 4 - Resource index (RES_INDEX) + 5 - Code (CODE) + bits 8-20: The instance number of the first instance + of this type in this package. Every + following instance has a number 1 higher + than the one before. + bits 21-31: number of resources of this type in the + package + for each of the resource instances for this package + (as in p.packmem_info): + 2 if this is a packaged file: multiply by 4 to get + the length of this resource. [1] + if this is a file that is not packaged: + index in file_list_offs of the file name for + this resource. + [the same position is in memory used as a MEM_HANDLE + to the actual data] +path_list_offs (should be directly after the packmem list) + ? null terminated path strings, indexed from the file list + table +file_list_offs (should be directly after the path list) + ? A number of file info structures. For packaged files, + these are indexed from the p.packmem_info (so (at most) + one per package). For non-packaged files, these are + indexed from an entry for an instance from + p.packmem_list (so possibly more per package) + These structures are in this form: + 13 file info: + 2 location relative to path_list_offs of the + the path to this file, or 0xffff if no path. + 8 file name (8 chars or null-terminated) + 3 extension (3 chars or null-terminated) + +The following section is present in the package only for packaged files. +For non-packaged files, the fields below exist in the external file indicated +by p.packmem_info.file_index. +For each package p: +p.data_loc for each type p.t: + for each instance p.t.i: + p.t.i.length + the data for the resource + As the length always is a multiple of 4, the last + few bytes may not belong to the resource itself. + Their content is unspecified. + + +Resources with type 'resource index' (type 4 in the 3DO sc2 starcon.pkg file) +are files with the same format as this .pkg file itself. + + +The information above, about the format used on the 3DO, is gathered from +the resource library sources itself. +The information below, about the format used on the PC, and for SC1, +is induced from the packed files themselves. + + +The format used in SC1 is somewhat different. The differences are listed +here: +0x02 4 offset from the beginning of the file where the list + of pathnames is stored (path_list_offs) +0x06 4 offset from the beginning of the file where the list + of file names is stored (file_list_offs) +0x0a 4 offset from the beginning of the file where the list + of package information is stored (packmem_list_offs) +0x0e 2 number of types of packages present in the file (num_types) +0x10 2 ? +0x12 2 number of packages in the file (num_packages) +0x14 2 ? +packmem_list_offs + 4 as for the 3DO + 2 if this is a packaged file: the length of this resource. + No multiplication by 2 or 4 as on other platforms. [1] + + +The format used in the DOS version of SC2 is different yet again. +The differences to the 3DO version are listed here: +0x10 1 number of types of packages present in the file (num_types) +0x11 1 unknown +packmem_list_offs + 4 as for the 3DO + 2 if this is a packaged file: multiply by 2 to get + the length of this resource. [1] + + +[1]. In some of the packaged .pkg files used in the Toys For Bob games, +the length field of a resource instance is overflowed for some resources, +even though the use of a multiplier will have had the purpose of preventing +this. The actual size is a multiple of 0x10000 times the multiplier larger. +This occurs in 18 packages in the PC version of Star Control II, in +1 package of the Amiga version of Star Control 1, and in 2 packages of +the PC version of The Horde. The PC version of Star Control 1, and the 3DO +version of Star Control II don't have such overflows. +The actual size of a package can be determined by looking at the +difference in offset between two subsequent packages. +Where the package contains only one resource instance, the extra data can +only belong to that instance. Where a package contains more than one +resource instance, the extra data most likely belongs to the last resource, +as an incorrect size results in an incorrect offset for all subsequent +instances in the package, which would most likely have been noticed due to +corruption in the game. + + +The part pointed to by file_list_offs is frequently followed by a bit of +unused space, which may contain garbage. + + +Initial version of this file 2002-10-10 by Serge van den Boom. + diff --git a/doc/devel/planetrender b/doc/devel/planetrender new file mode 100644 index 0000000..aa3c908 --- /dev/null +++ b/doc/devel/planetrender @@ -0,0 +1,54 @@ +Planet surface rendering code +-------------------------------------------------------------- + +The way the planets appear on the screen (based on planet type +definition in plandata.c) is determined by several factors: + +1. Topography algorithm (PlanetFrame.Type) +2. Color map (PlanetFrame.CMapInstance) +3. Elevation -> colormap index xlat table (PlanetFrame.XLatTabInstance) +4. Base elevation (PlanetFrame.base_elevation) +5. Several others not covered here: faults, craters (blemishes) + +First, the planet topography is generated according to the algorithm +selected for the planet: TOPO_ALGO, CRATERED_ALGO, GAS_GIANT_ALGO. +TOPO_ALGO and CRATERED_ALGO use a fractal algorithm to pseudo-randomly +generate a surface, then 'craters' are added and, at the end, the map is +dithered for CRATERED_ALGO. GAS_GIANT_ALGO is of course different +because it needs to produce a series of ring-like structures with +'storms' added at the end. + +The topographical map is a rectangle with each pixel representing an +elevation level relative to 0, so the topography is expressed in terms +of elevation relative to base elevation. Base elevation is applied to +the generated map. Topography is created with elevations -128..127, +and base elevations, currently, range from 100 to 200 (plandata.c) for +normal worlds and are always 29 for gas giants. Since the gas giants +do not have a real topography or a surface to speak of, their surfaces +are rather simulated with elevations. + +At this point, the elevation levels are translated to the actual colors +using the xlat table and color map. First, the elevation is translated +to an index into the colormap using the xlat table (.xlt files), and +after that, the actual RGB color is drawn from the colormap (.ct files) +at this index. + +There are 3 colormaps per instance specified in PlanetFrame. The active +colormap is selected from these 3 based on the surface temperature of +the planet: cold, normal and hot. The framework is also laid down for +3 xlat tables (one per surface temperature), but, AFAIK, distinct xlat +tables are never actually used. Currently, there is only 1 xlat table +per instance in each file. + +The colormap files (.ct) seem to be in original DOS format. Probably +because they do not translate to the CLUT system very well. The colormaps +are carefully crafted and synchronized across all planet types to make +the entire system function properly. They are composed of 4 gradients of +different hue, 32 colors each (4*32=128 colors). Gradients go from the +most intense color to near black. For the most planet types, the three +colormaps per instance are all the same, so that the way a planet +surface looks does not change with the surface temperature. Notable +exceptions are: h2o_cts_ (water world) and mtl_cts_ (metal world); there +could be others as no byte-identical examination was done. +See blue-gas-giant-pal.png for an example colormap. + diff --git a/doc/devel/planetrotate b/doc/devel/planetrotate new file mode 100644 index 0000000..387c455 --- /dev/null +++ b/doc/devel/planetrotate @@ -0,0 +1,31 @@ +Planet-rotate code rev3: +written by PhracturedBlue +Date: Nov 1, 2002 + +This is the code to make the planets spin when in orbit view. +The planet will zoom in (as in the 3do version) +Shield support is very preliminary, mosly becuase I have not figured +out how to get the 'look' right. + +The planet rotation speed is controlled by ROTATION_TIME which is defined in plangen.c. +The default is '22' which gives a speed comparable to the DOS version of the game + +The planet zoom speed is defined by PLANET_ZOOM_SPEED which is defined in pl_stuff.c + +The lighting algorithm is really just a hack. All lighting code is in plangen.c +Currently, lighting is performed by placing the light source at a certain distance +(LIGHT_MULT) from the center of the planet (a value of 1 would place the light at +the planet's radius. (The angle is determined by the planet's position in orbit with +respect to the sun). The brightest poinnt will have the original color of the topo-map. +The light falls off as the cos(r^2/(LIGHT_RADIUS^2)). +The light can never be dimmer than AMBIENT_LIGHT + +The shield is done in 2 parts: the halo and the planet-mask. Whether this is needed or +not, I don't know, but it gives a bit more flexibility in how the effect is applied. + +The code works by blitting directly to an SDL_Surface, rather than using DrawBatch (and +the rendering thread). This gives a huge performance win (My P3-1000 went from ~40fps +using the DrawBatch to ~500fps using the current method). All lighting, planet tilt, and +sphere->plane mapping is precomputed into the 'map_rotate' and 'phong' tables (in plangen.c) +To optimize performance (there is no floating-poinnt code used during the actual frame +generation) diff --git a/doc/devel/planettopo b/doc/devel/planettopo new file mode 100644 index 0000000..7f27a39 --- /dev/null +++ b/doc/devel/planettopo @@ -0,0 +1,92 @@ +Planet Topography Code: sc2code/planets/gentopo.c +---------------------------------------------------- + +This text covers only topography generation code. It does NOT cover the +craters (blemishes) nor the smoothing. Variables names are the same in +"sc2code/planets/gentopo.c". + +A brief overview: + +The algorithm works by applying several elevation/lowering steps on the +same terrain. Each step works by randomly generating two non-intersecting +lines, LineDDA0 and LineDDA1. That delimits two regions. Each region is +then displaced by a certain height delta (depth_delta). That step is +repeated several times. + +There's a pseudocode below, with detailed information about it in the next +section. + +The DeltaTopography() function works as follows: + + Function parameters: + + COUNT num_iterations // Number of height displacements on the + // planet's surface + PSBYTE DepthArray // Target surface, receives topography data + PRECT pRect // Surface dimensions + SIZE depth_delta // The amount of height units to raise/lower + // on each displacement + + for i from 1 to num_iterations + randomly either negates depth_delta's or not, influencing + the displacement direction + randomly pick two line segments, LineDDA0 and LineDDA1 + increase the height of the region between LineDDA0 and + LineDDA1 by depth_delta + decrease the height of the region between LineDDA1 and + LineDDA0 by depth_delta (by wrapping around the surface) + end for + +Detailed information about the algorithm's steps: + +First, in half the steps (randomly) depth_delta is negated. +That influences on the direction of the displacements. +Note that in each step exactly two height displacements occur: +a lifting and a lowering. + +Next, it sets both w1 and w2 to different random WORD values. Those are +used in the line segment generation process. + +LineDDA0 starts on a random position on the top of the surface, and ends +at another random position on the bottom of the surface. +LineDDA0 never wraps around the surface, since their X coordinates are +generated in the range 0..width-1: + + LineDDA0.x_top = LOBYTE (w1) % width; + LineDDA0.x_bot = HIBYTE (w1) % width; + +LineDDA1 is generated much like the way LineDDA0 is, the difference being +LineDDA1's x coordinates are displaced by LineDDA0 ones: + + LineDDA1.x_top = (LOBYTE (w2) % (width - 1)) + LineDDA0.x_top + 1; + LineDDA1.x_bot = (HIBYTE (w2) % (width - 1)) + LineDDA0.x_bot + 1; + +Y coordinates are 0 for top, and 'height' for bottom in both line +segments. + +This delimits basically two regions. One delimited by LineDDA0 on the left +side, and LineDDA1 on the right right, which we call "0->1". The other is +delimited by LineDDA1 on the left, and LineDDA0 on the right, which we call +"1->0". +Note that, since we're talking about a planet, the rightmost side of the +surface if "connected" to the leftmost side. At least one of those regions +"wrap around" the surface. + +The final step in the iteration is to increase the height of the region +0->1 by depth_delta, and decreasing 1->0 by the same value. Note that since +delta_depth may be negative, raising part of the surface by delta_depth +may result in the surface being lowered. + +This step is repeated num_iteration times. + +About the terrain generation algorithm: This method of displacing +line-delimited subsets of a surface is commonly known as Fault Formation. + +The DDA acronym stands for "Digital Differential Analyzer". Hence the names +LineDDA0 and LineDDA1. + +The first version of this document was written by: +Daniel Ribeiro Maciel <daniel.maciel@gmail.com> +on 2006-11-24 + + diff --git a/doc/devel/plugins b/doc/devel/plugins new file mode 100644 index 0000000..505d7d1 --- /dev/null +++ b/doc/devel/plugins @@ -0,0 +1,129 @@ +UQM Code DataPlate modules +===================================================================== +Terminology: +------------ +cdp Code DataPlate + refers to either a module or the architecture + itself; + +module cdp module (ditto ^) + +interface a set of functions defined by either the core + engine or a module aimed at performing various + tasks on a specific part of the game + +itf interface; short form + +host the game itself or core engine; also a top-level + interface for use by modules + +interface kind a unique identifier of a particular defined + interface (not of the interface instance); + there can be several interfaces of the same + kind registered, but they all have to cover + different API versions (version ranges may + overlap though) + +standard interface interface *defined* by the core engine + all host, sound, video, gfx, threads, time, + input, io (uio), memory, resource interfaces + are standard, including all subdivisions like + 'sound mixer' and 'sound decoder'; + a module can implement standard behavior of + the game or extend the game by implementing and + registering a corresponding interface + +built-in interface interface *provided* by the core engine + e.g. host, sound, video, gfx, etc. lib wrappers + anything except 'host' can theoretically be + implemented as a 'standard' interface rather + than built-in; sound and video interfaces, + for example, would not make sense to rip out + from the core, but parts of 'gfx' might be good + candidates (gfx should probably be more than + 1 interface); do not confuse 'sound' interface + with 'sound decoder' and 'sound mixer', mixers + (MixSDL and OpenAL) are also prime candidates + +custom interface interface *defined and provided* by a module, + other than a standard interface + a module may decide to provide (expose) some + interfaces so that other modules can utilize + them; a module will register such interface + the same way it would register a standard + interface it implements + +vtbl virtual table; a table of interface functions; + pointer to vtbl is semantically equivalent to + an interface pointer + +event a bindable point in code of the engine or any + module; event observer recieves event + notifications via event handlers it installs + +h_foo handle to 'foo' + +plate cdp module +fork interface; something to poke a plate with +spoon event; + "hit the plate with a spoon" == "notify via + event handler" + + +Typical calling sequence: +------------------------- +1) something calls adlm_LoadModule(the_mod) ('the_mod' is used here + to identify the module and to *logically* group module properties + and operations performed on the module for the sake of this + document); the_mod gets dlopen()ed; + +2) adlm_LoadModule() looks up the only exported symbol 'adlminfo'. + This symbol is the adlm_ModuleInfo struct; + +3) adlm_LoadModule() verifies that the_mod is compatible with current + engine and API versions and calls + adlm_GetInterface(HOST,the_mod.api_ver) to lookup the host interface + with the correct API version for the module; + +4) adlm_LoadModule() either increments module ref-count (if the module + has already been loaded previously) or calls + the_mod.module_init(host_itf) + +5) the_mod.module_init() stores off the host_itf pointer and performs + internal initialization; + +6) [Optional; but not useful w/o] the_mod.module_init() calls + host_itf->GetInterface(kind) to get access to whatever standard or + custom interfaces it requires (for example, it requests a sound + interface to register an audio decoder); + +7) [Optional] the_mod.module_init() calls + host_itf->RegisterItf(kind,...,itf_vtbl,...) to register the custom + or standard (do not confuse with built-in) interfaces it wishes to + expose to the core engine or other modules; + +8) [Continuous normal operation] module calls members of the interfaces + it acquired to perform various game-related tasks; core engine + and/or other modules call members of the interfaces that module + exposed (if it did so); + +9) something calls adlm_FreeModule(h_the_mod) either when the game + quits or when the module is dynamically unloaded for whatever + reason: possibly when user decides to dump the game-mod and use + something else in its place or nothing at all, but for now there + is no mechanism to ensure safe mid-game unloading of modules -- + interfaces are not ref-counted and anything can hold a pointer to + an interface at any given time (creating a safe system to do this + is probably not cost-effective); + +10) adlm_FreeModule() decrements module ref-count and, when ref-count + reaches 0, calls the_mod.module_term(); + +11) the_mod.module_term() calls host_itf->UnregisterItf(h_itf) to + unregister the interfaces it had exposed previously; then it + unregisters any other objects it registered, releases all objects + it acquired through interfaces and destroys any objects it is + responsible for; + +12) the_mod.module_term() performs internal cleanup; + diff --git a/doc/devel/queues b/doc/devel/queues new file mode 100644 index 0000000..274828e --- /dev/null +++ b/doc/devel/queues @@ -0,0 +1,62 @@ +The various ship queues used in the game: + +GlobData.Game_state.avail_race_q: + Contains fleet information, ship template and other info about the + alien races present in the game. All races are present that are + defined by the enum in races.h that defines NUM_AVAILABLE_RACES, + except for, technically, SAMATRA_SHIP. URQUAN_PROBE_SHIP is a + very incomplete 'race'. + Elements are of type FLEET_INFO. + Filled in InitGameStructures(). + Partially included in savegames. + +GlobData.Game_state.built_ship_q: + The fleet accompanying the flagship (escorts). + Elements are of type SHIP_FRAGMENT. + which_side is always GOOD_GUY here. + Partially included in savegames. + +master_q: + List of templates for all the ships that are available in SuperMelee. + Elements are of type MASTER_SHIP_INFO. + Sorted on the (abbreviated) race name (see doc/devel/racestrings). + Filled in LoadMasterShipList(). + +GlobData.Game_state.npc_built_ship_q: + The npc ships in an encounter, or list of ship groups when in IP; + empty otherwise. + Elements are of type SHIP_FRAGMENT. IP group list will most likely + change to contain GROUP_INFO instead. + For encounters with an infinite number of ships, the queue consists + of a single ship with ShipInfo.crew_level set to (BYTE)~0. + and the side that this ship is on. + Partially included in savegames. + +race_q[NUM_PLAYERS]: + Contains the ships participating in a battle for each player. + Elements are of type STARSHIP. + Filled in BuildBattle(). + RaceDescPtr points to a loaded ship's descriptor once the ship data + is loaded in spawn_ship(); NULL otherwise. + + +Other queues: + +GlobData.Game_state.GameClock.event_q: + Queue of game events. + Elements are of type EVENT. + +disp_q: + Display queue. This contains all visible elements; everything + that floats in TrueSpace, HyperSpace/QuasiSpace, battle. + Elements are of type ELEMENT. + +GlobData.Game_state.encounter_q: + Contains information regarding the black globes flying around + in HyperSpace. + Elements are of type ENCOUNTER. + + +Initial version of this document created by Serge van den Boom, on 2006-03-08. + + diff --git a/doc/devel/racestrings b/doc/devel/racestrings new file mode 100644 index 0000000..2993a65 --- /dev/null +++ b/doc/devel/racestrings @@ -0,0 +1,45 @@ +This file describes the use for each entry of the +content/base/ships/<race>/<ship>.txt files. + + +Entry #0: + Battle group name + Used in uppercase on the "debris scavanged" message after destroying + a battle group in the full game, from UninitEncounter(). + +Entry #1: + Race name + Displayed on the starmap, from DrawStarMap() (and GetSphereRect()). + Used in combat (both in the full game and in SuperMelee) as the + name of the race, from InitShipStatus(). + +Entry #2: + Abbreviated race name. + Used when sorting the races in LoadMasterShipList(). + +Entry #3: + Ship name. + Unused (?) + +Entry #4: + Abbreviated ship name. + Unused (?) + +Entry #5 (NAME_OFFSET) through #20 (NAME_OFFSET + NUM_CAPTAINS_NAMES - 1): + The names of the captains of the ships of this race, as displayed + during combat. + + +For some races, some plot-specific captain names follow: +Shofixti: + - Entry #21: Tanaka + - Entry #22: Katana +Spathi: + - Entry #21: Fwiffo + + +Note that the race/ship name combinations shown when adding a ship to your +fleet in the shipyard are actually images (lbm/shipyard.3.png through +shipyard.23.png). They are displayed from DrawRaceStrings(). + + diff --git a/doc/devel/resources b/doc/devel/resources new file mode 100644 index 0000000..20db1b7 --- /dev/null +++ b/doc/devel/resources @@ -0,0 +1,196 @@ +This file documents both the currently used resource system and the +legacy system used in the original implementations. It also describes +how to update the resources while keeping everything functional. + + THE UQM RESOURCE SYSTEM + ----------------------- + +Resources are identified by "resource IDs", which are arbitrary +strings. The UQM convention is to treat them as paths or qualified +names, with the period being the separator. An example would be +"comm.arilou.dialogue", which is conceptually grouped with all other +resources beginning with "comm." or "comm.arilou." + +Resources are mapped to files via "resource map files" or RMPs. These +files are full of key-value pairs. Each line of an RMP file matches +this format: + + resource_ID = RESOURCE_TYPE:resource_data + +The currently defined resource types and their accompanying data are: + +GFXRES: A single animation. The resource data is the name of the + .ani file that defines it. See the "aniformat" file for + details. +FONTRES: A font. The resource data is the name of the directory + in which the font is defined. +MUSICRES: A music file. The resource data is the filename of the + relevant file in OGG or MOD format. +SNDRES: A set of related sounds. Points to a text file, + traditionally suffixed ".snd", that lists each sound + file in the collection, one per line. These sounds are + in WAV format. +STRTAB: An unadorned string table. The resource data is the file + name. +BINTAB: Indexed binary data, mostly used for palettes and + topological data for planet terrain generation. The + resource data is the file name. See the "strtab" file, but + be aware that all information not regarding .ct or .xlt + files has been obsoleted. +CONVERSATION: All data corresponding to an individual conversation + tree. The resource data has three components, separated + by colons: the conversation text (similar to the + STRTAB), the directory in which voiceovers may be + found, and the timestamp file corresponding to those + voiceovers. The second and third values are optional, + but if either is present, both must be. +SHIP: This is an integer that specifies which ship corresponds + to a specified resource. The mapping of SHIP integers + to actual ship_info structures is done by the dummy.c + routines. +STRING: A string. The resource data is the string itself. +INT32: A 32-bit integer. The resource data is the integer as a + string giving its representation in decimal. +BOOLEAN: A true/false value. Any value of the resource data that + is not the exact case-insensitive string "true" will be + treated as false. +UNKNOWNRES: A catch-all internal type for any type the system does + not recognize. It is functionally equivalent to STRING, + mainly so that sensible debug messages may be emitted. + +When UQM is started, each RMP file in the content directory (but not +its subdirectories) is read and indexed. Then, for each addon pack +rqeuested, it reads each RMP file in the addons/(addon name)/ +directory and updates the resource index accordingly. Generally +speaking, this will overwrite older values of the resources with +pointers to the new content. + +It is permissible to have multiple RMP files in a single directory; +however, if this is done, there should be no overlap between the +resources defined. The UQM resource system makes no guarantees about +the loading order of RMP files within a unit. + +It is not required for an addon to restrict its references to its own +subdirectory; all paths are relative to the base of the content +directory. This allows fonts to be shared across addons, for an "addon +pack" to simply reorganize content within the base directory. (For +instance, a popular modification to the original games involved +juggling .SHP files and renaming them so that the "Earthling Cruiser" +was actually a much more powerful ship like the Utwig Jugger or Chmmr +Avatar. This may be effected in the current system by making an addon +pack that redefines the relevant SHIP-typed resources.) + + UPDATING THE CORE RESOURCES + --------------------------- + +The officially supported content is kept in three indices: + +- content/uqm.rmp: The core content. +- content/addons/3domusic/3domusic.rmp: 3DO music. +- content/addons/3dovoice/3dovoice.rmp: The 3DO conversations. + +These latter two are treated the same as any other addons, except that +they are guaranteed to be loaded first if selected by the +configuration file. + +These files do not house all the necessary data, however. The code +itself uses a set of automatically generated header files to #define +constants that correspond to each resource. In order to add new +resources or change currently defined resource IDs, the .h files must +also be updated. + +To keep all information in one place, the tools/resmap directory +contains a master data file for all core resources ("resource.csv") +and a number of Python scripts for manipulating it. + +If files have simply been moved, renamed, or re-typed, one may reflect +these changes in uqm.rmp and run the "reverse_rmp.py" script. This +will reflect changes in uqm.rmp back into resources.csv. + +If the header constants or resource IDs have changed, changes will +need to propagate to the .h files. Edit or add the relevant lines to +resources.csv and run "gen_resfiles.py". This will read resources.csv +and regenerate uqm.rmp and all the relevant header files. + +The resources.csv file is a comma-separated-values file suitable for +importing into most spreadsheet programs. It has one line for each +resource, and each line has five "columns": + + C constant, resource id, header file, resource type, resource data + +If a resource exists in the code, but not in the base content the +resource type and resource data are both the string "--". The C +constant and header file are still mandatory - otherwise UQM will not +compile. Such resources will not be reflected in the RMP files, but +will have their headers defined appropriately so that addon packs may +provide values. + +Major reorganization of files may be done with the transform.py file; +its usage string describes its script format. + + LEGACY SYSTEM + ------------- + +The resource files the resource system in SC2 uses, comes in two flavours. +There are 'packaged' files, which contain the data in the file itself, +and 'non-packaged' (index) files, which only point to other files. +The internal formats are described in pkgformat, and are mostly the same. + +A resource file is opened by a calling OpenResFile(), after which a +MEM_HANDLE to a resource can be acquired from it by calling GetResource(). + +The argument of GetResource() is an integer value specifying the resource. +There are defines for this defined in (files included from) the various +resinst.h file. The defines are unique to a resource file. +A resource id can be something like this: 0x00400002 +Bits 21-31 specify the package. (resources are grouped together in a + resource file in packages) (a number >= 0). +Bits 0-7 specify the resource type of the resource (a number >= 1). +Bits 8-20 specify the instance number (the number of the resource of a + type in a package) (a number >= 0). + +The resource type is a number. What kind of resource that actually is, +is not specified in the package. The program registers functions for +loading data of a specific type number, by calling InitResTypeVectors(). + +In the original 3DO version, the following types are used: +GFXRES (1) - graphics data +STRTAB (2) - string table +MUSICRES (3) - music and sound data +RES_INDEX (4) - a resource 'file' +CODE (5) - identifies code to use (the resouce file itself does not + contain any code) + + +In the PC version of Star Control II, the following types are used +(the names are taken from the other versions): +KEY_CONFIG (1) - keyboard configuration +GFXRES (2) - graphics data +SNDRES (3) - waveform audio +STRTAB (4) - string table +MUSICRES (5) - mod audio +RES_INDEX (6) - a resource 'file' +CODE (7) - actual PC code (compressed; used for ships as well as comm; + may include other resources) + (8) - Deluxe Paint .ANM + + +In the UQM project pre-resmap, the following types were used: +KEY_CONFIG (1) - keyboard configuration (not used in the 3do packages) +GFXRES (2) - graphics data +FONTRES (3) - font data +STRTAB (4) - string table +SNDRES (5) - waveform audio +MUSICRES (6) - music +RES_INDEX (7) - a resource 'file' +CODE (8) - identifies code to use (the resouce file itself does not + contain any code) + +The resource files, resinst.h, restypes.h, and respkg.h files were +originally generated from information from the .res and .typ files. The +resource library should be compiled with 'PACKAGING' defined for this. + +--- + +Initial version of this file 2002-10-23 by Serge van den Boom. +Updated for the 0.7.0 system by Michael Martin. diff --git a/doc/devel/savefile b/doc/devel/savefile new file mode 100644 index 0000000..306c1ab --- /dev/null +++ b/doc/devel/savefile @@ -0,0 +1,149 @@ + SAVEFILE FORMAT + --------------- + +This document represents a work in progress. The save format described +here will evolve before finalization for 0.8. + +The old save file format used a custom compressor and was very finicky +about padding and alignment for machines that were not even in use +anymore. It was also extremely fragile and hard for modders to extend. + +The new save format seeks to alleviate these problems. + + GENERAL FORMAT + -------------- + +All multibyte values are little-endian. There are no alignment +restrictions inherent in the format. + +The save file begins with a 32-bit identifier and version number (a +"magic number") that identifies it as a particular version of an UQM +save file. If the format changes in a way that older versions of UQM +cannot read it, either the identifier or the version number should +change. + +The vanilla UQM system has a save number of 0x01534d55, which, if +interpreted as a byte stream is UMS (Ur-quan Masters Save) and a +binary 1 (version 1). Vanilla UQM reserves the tags "UMSx" for all x +for use to evolve the core save format. Modders are encouraged, but +not required, to also use the fourth bit as a version number. + +Following the 32-bit file identifier comes a series of chunks. All +chunks have the same general format: a 32-bit tag, similar to that of +the file as a whole, followed by a 32-bit integer specifying the size +of the chunk, and then that many bytes of data. + +Bytes in a chunk tag should all be in the range 0x20-0x7E -- that is, +they should be printable ASCII characters. Chunks are traditionally +referred to by their tag names. + +Chunks whose tag has a least significant byte in the range 0x41-0x5a, +inclusive---that is to say, whose names start with a capital +letter---are mandatory. If you extend the set of mandatory chunks, you +must increase the version of the file. Tags that do not start with a +capital letter may be ignored by other versions of UQM that otherwise +understand that data version. + +(Why would you want to have ignorable bits of save file? Such chunks +may contain helpful but ancillary information. For instance, at the +time of this writing, there is an outstanding bug that life forms are +un-stunned if you save and load in orbit. One could add a new chunk +that tracks the stunned status of life forms on the planet you're in +orbit around, and just revert to the old behavior if it's not there or +if you're running on a version without that fix. Such an ancillary +data chunk would have a tag like "stun" or "biot".) + +Note also that despite being "mandatory", it is not the case that all +chunks will be present in all save files. Different data is saved out +depending on the situation you saved in. + +Unless otherwise specified, chunks may be stored in any order in the +save file. + + CHUNK INVENTORY + --------------- + +- "Summ": Summary. This chunk must come first. This chunk + carries the flagship configuration information and some overview + information that is displayed on the savegame view screen. It is of + variable length, because the last element of this chunk is the name + of the save as chosen by the user. + +- "GlSt": Global State. This chunk must come second, after + Summ. Represents most of the data in the global state structure in + globdata.h. BattleGroupRef is excised from this; its value is + computed later on. + +- "GmSt": Game State. This chunk must come third, after GlSt. This is + the gigantic bitfield that the GET_GAME_STATE macros modify. It is + variably-sized; excess bytes in this array will be ignored, and if + there are insufficient bytes in the save file, the remaining bits + will be initialized to zero. Modders setting extra event flags may + be able to import a legacy game into a sensible state by choosing + their defaults judiciously. + +- "Evts": Events. An array of values describing scripted future + events. + +- "Enct": Encounters. Details of battle groups that are pursuing you + through HyperSpace. + +- "RacQ": Available Race Queue. Which species are active in the game, + where they are, etc. Corresponds to avail_race_q. + +- "IGpQ": Interplanetary Group Queue. Battlegroup information for + ships in your current star system, if you're in a current star + system. It is currently unclear whether or not this ever needs to + exist, but in keeping with legacy logic, it will appear whenever you + are in a star system but not in the middle of an encounter. + +- "NpcQ": NPC Queue. Battlegroup information for ships you are in the + middle of encountering. This should only appear if your loaded + activity is "IN_ENCOUNTER" and loading the game will trigger the red + alert. + +- "ShpQ": Ship Queue. Battlegroup information for your flagship's + escort fleet. + +- "Star": Star Description. Basic indexing information to indicate + which star system you are in. + +- "Scan": Scanner Masks. This is a semi-structured tree of DWORDs that + represents which planetary resources have been captured or + removed. It is a format roughly similar to the old star info + statefile format (see doc/devel/statefile) but little-endianness is + enforced, making this chunk endian-safe where the old statefile dump + was not. + +- "BtGp": Battle Group. Defines the relevant information for all ships + in a given star system. This includes an "encounter ID" - randomly + generated fleets have an encounter ID of zero, and ones built by the + plot have an 32-bit identifier. Vanilla UQM reserves the first 32 + encounter IDs for itself, and uses 15 of them (random encounter, + Ur-Quan Probe, Shofixti Survivor, Zoq-Fot-Pik Emissary, Unzervalt + Guardian, nine Melnorme Traders, and the final boss). This also + includes the expiration date for random encounters and which system + they are relevant to. Much of this information was originally stored + in randgrp.dat, but it has echoes in defgrp.dat as well. The data + here is a ragged 2D array of a slight extension of the SHIP_FRAGMENT + structure. There is one BtGp chunk per defined group. (Since one of + these is defined at game start, and the random encounter structure + has values that mean 'no encounter present', there should always be + at least two of these chunks in any save.) + +- "Grps": Active Battle Groups. These are IP_GROUP structures to + supplement the SHIP_FRAGMENTs specified in BtGp chunks. They give + more detailed information about the precise location and disposition + of each ship in the system you are either in or most recently left. + + THINGS LEFT TO DO + ----------------- + +The last 448 bits in GmSt probably shouldn't exist. However, we should +not remove them from the source base (and thus the save file) until +after other pending commits have been merged. When this happens, we +can break out those bits into an array of DWORDs instead. The loading +code basically ignores those GmSt bits by overwriting them while +loading later chunks, and GmSt is an expandable array in the first +place, so removing those final bits from the Game State array should +be compatible in both directions. diff --git a/doc/devel/sc1 b/doc/devel/sc1 new file mode 100644 index 0000000..373ac16 --- /dev/null +++ b/doc/devel/sc1 @@ -0,0 +1,186 @@ +This file documents the file formats used in Star Control 1. + +The .pkg files are in the format described in the file "pkgformat". +The extracted files are described in this document. + +The following describes the format used in the DOS version of SC1. + +Resource types used in starcon.pkg: + 1 - key config + 2 - some graphics type (flags = 7) + 3 - some graphics type (flags = 1) + 4 - some graphics type (flags = 2) 5 - some graphics type (flags = 3) + 6 - font + 7 - scenario + 8 - palette + 9 - strtab +10 - ? (sound?) + + +Files of types 2, 3, 4, 5, 9, and 10 may be compressed; they have +a header of the following format: have the following format: + +Uncompressed files: + off len + 0x00 1 0 (means: not compressed) + 0x01 1 flags, 0 in practice + 0x04 2 Number of bytes that follow (MSB first) + 0x06 start of data + +Compressed files: + off len + 0x00 1 6 (means: compressed) + 0x01 1 flags + bit 0: unused + bit 1: (table2CodeLen) + if not set: table2 results are shifted by 6 bits. + if set: table2 results are shifted by 7 bits. + (never set in PC SC1 files) + bit 2: (litencoded) set if literal bytes are Huffman encoded + (never set in PC SC1 files) + rest: unused + 0x02 4 uncompressed size (MSB first) + 0x06 Huffman table 0 (8-bit codes) (only present if litencoded set) + used for encoding literal bytes + Huffman table 1 (6-bit codes) + used for encoding lengths + Huffman table 2 (6-bit codes) + used for the most significant table2CodeLen bits of an offset + + + +Huffman table: +(numbers are in bits) + 8 one less than the number of lengths of codes + in the table (lenCnt) + 8 * lenCnt LONIBBLE: one less than one of the code lengths + HINIBBLE: one less than the number of codes with + this length +This is enough to construct the huffman table. + +TODO: document the rest of the compression format; for now, look at the + code of sc1-decomp. + + +Resource type 1 (key config): + off len + 0x00 1 bottom player special key ('n') + 0x01 1 top player special key ('1') + 0x02 1 bottom player left key ('m') + 0x03 1 top player left key ('2') + 0x04 1 bottom player right key (',') + 0x05 1 top player right key ('3') + 0x06 1 bottom player thrust key ('.') + 0x07 1 top player thrust key ('4') + 0x08 1 bottom player fire key ('/') + 0x09 1 top player fire key ('5') + 0x0a 1 ? + 0x0b 1 ? + 0x0c 1 ? + 0x0d 1 ? + 0x0e 1 ? + 0x0f 1 ? + 0x10 1 ? + 0x11 1 ? + 0x12 1 ? + 0x13 1 ? + + +Resource types 2, 3, 4, and 5 (graphics): +The difference between those types is the flags parameter that is passed +to the load functions (see above in the table of resource types). +bit 0: ? +bit 1: probably indicates whether a palette is used +bit 2: ? +rest: unused + +(after decompression/removing packing header) + off len + 0x00 4 "IANM" + 0x04 2 frame count (MSB first) + 0x06 2 MSB first + LOBYTE: bits per pixel. All SC1 files are either 1 bpp or 4 bpp. +For every frame: + 2 width (MSB first) + 2 height (MSB first) +For every frame: + 2 x hotspot + 2 y hotspot + 1 if not zero, the file includes palettes + 1 transparant color + 16 (optional) (CGA?) palette (16 entries of 1 byte) + 16 (optional) (EGA/Tandy?) palette (16 entries of 1 byte) + 16 (optional) (MCGA/VGA?) palette (16 entries of 1 byte) + ? pixel data (indicees in palette) + + + +Resource type 6 (font): + off len + 0x00 1 ? + 0x01 1 ? + 0x02 1 LONIBBLE: + HINIBBLE: + 0x03 48 + +The letters are actually readable if you do 'xxd -b'; it shouldn't be too +hard to RE this one. + + +Resource type 7 (scenario): + off len + 0x00 16 Title (\0 terminated) + 0x10 ? Short description (\0 terminated) + ? ? Unknown (probably description of star systems, Space Spines, + fleets and bases (maybe random seeds?)) + 0x80 840(?) Long description (\0 terminated) + + +Resource type 8 (palette): + off len + 0 768 palette data: +for each of the 256 entries (with index 0 through 255): + 1 red value + 1 green value + 1 blue value + + +Resource type 9 (string): + off len + 0x00 2 Number of strings (MSB first) + 0x02 2 unknown (always 0x0000) +for each string s: + 2 len[s]: length of the string (MSB first) +for each string s: + len[s] String data (not '\0'-terminated) + + +starcon.exe: +compressed using lzexe +(http://fabrice.bellard.free.fr/lzexe.html) +Using PLINK86 to load starcon.ovl as an overlay. + + + +The Amiga version of SC1: + +Resource types used in starcon.pkg: + 1 - key config (presumed; different from the DOS version) + 2 - graphics + 3 - graphics + 4 - graphics + 5 - graphics + 6 - font + 7 - scenario (as with the DOS version) + 8 - strings as on DOS, but also other data in the same format + (presumably including sound) + +Files of types 2, 3, 4, 5, 8 may be compressed as in the DOS version. + +Graphics files are in a different file format as on DOS. I haven't worked +on these files yet. + + +Initial version created on 2007-06-01 by Serge van den Boom. + + diff --git a/doc/devel/script b/doc/devel/script new file mode 100644 index 0000000..07dbf0f --- /dev/null +++ b/doc/devel/script @@ -0,0 +1,117 @@ +SCRIPT CONVENTIONS +------------------ + +The .txt files in the content/comm directories are unlikely to stay in +their current form forever, as it's a rather fragile format. However, +in the the meantime, and for those who seek to edit the script files +(to conform to 3DO, PC, and/or director's cut versions). + +This file will describe the format, and how it relates to the source +code in the src/sc2code/comm directory. + +The .txt files +-------------- + +The text files should all have a set of records, optionally separated +by newlines. Each record has a header, then one or more lines of +text. + +The header is a hash (#), an identifier in parentheses, and (if it's +an alien voice) a tab, then the name of the file corresponding to that +voice. Alien voices have identifiers in ALL_CAPITAL_LETTERS, while +Zelnick's lines are in_lower_case. Often one line is broken into +several parts - in these cases the full line is knitted together by +the communications code (usually inserting the name of the Captain, or +the flagship, or whatever). + +A modest example: + +#(HAVING_FUN_WITH_ILWRATH_2) thrad103.wav +The exploding starships! The screaming crew! +The direct hits, the cunning escapes! +These are the moments we live for! +Now we must return to the great battles! +Farewell, Great Teacher. + +Zelnick's lines must be ON ONE LINE ONLY; line breaking is handled by +the communication code and anything after the first newline is +IGNORED. So don't do it while repairing his lines, and if you find +one (a lowercase id with multiple lines following it) delete the +newlines and make it all one line. + +It appears that newlines may appear in the middle of speeches; +however, most of the lines by aliens have pauses represented by a +single space or tab. It seems reasonable to duplicate this. + +When multiple records are used to define a single speech line (as +often happens when they say your name, for instance), only the first +line has an audio file associated with it. + +Lines that do not end in a punctuation mark or a space have a "..." +added to the end of them by the communications code. If the previous +line had "..." appended to it and this line does not START with a +space, this line will have "..." prepended to it. The "scriptcheck" +tool looks for all cases where "..." does not occur in midsentence. +When editing the script files, check your intended results against +this. + +The .h files (src/sc2code/comm) +------------------------------- + +Each race has its own directory in src/sc2code/comm, and there is a +file marked strings.h in each directory. This file defines a single +enum which should list every record identifier in the appropriate +race's .txt file over in content/comm/{race}, IN THE PRECISE ORDER +THOSE RECORDS ARE GIVEN. Due to the non-symbolic nature of C, there +is no relation whatsoever between the identifiers in the record and in +the enum (though it would be reasonably straightforward to generate +the strings.h files from the .txt files) The values of the enum are +used in the {racec}.c files in the same directory. + +The scriptcheck utility also checks for proper correlation between the +.h file and the associated .txt file. It assumes that one enum value +is listed per line, and that the general format of the file matches +the current one. + +Types of script bugs +-------------------- + +Script bugs can fall into three broad categories. + +- Voice/Speech mismatch. These are easy. The wrong audio file is + associated with this clip. Merely change the clip to make it fit. + If a clip is expected but is not specified, this appears to crash the + game. Example: The Zoq-Fot-Pik's "Goodbye Captain." "See ya." lines + had no clips associated with them, which both caused the game to loop + forever on those lines and misaligned all clips after that so that the + voices did not match the subtitles. + +- Subtitling error. These are also easy. The voice and text more or + less match, but the phrasing is slightly different. This is also + easy. Change the text to match. If the speech is *wildly* different, + make sure that it's not a misfiled audio file. NOTE: The PC and 3DO + versions had slightly different texts, and the texts we are working + with here match neither one. The voices are to be taken as the + ultimate authority on the 3DO text. + +- Communications Logic errors. Basically, this means the enum in the + appropriate strings.h was defined wrong, or, worse, was misused by the + {race}c.c file. One fixed example was the Spathi Ruling Council (Race + name: spahome), where strings.h defined *two* enums, one for the + Captain's lines, one for the Spathi. This would have horribly garbled + everything were it not for the fact that it made their initial + challenge and your responses invalid, thus causing the game to lock up + on your first visit. An example of one of these that made it into the + final game (PC version, anyway) is when the Umgah are trying to reward + you as Great Hero - the responses for the "I act purely from largesse" + and "Yep! You guys owe me BIG time" are clearly reversed. No + decision has yet been made on how to handle these (whether to + reproduce them precisely, or fix them, or only fix them in a + "director's cut" which would presumably require input from the + director) so leave them alone for now unless they crash the game. (To + my knowledge, the only truly serious error of this type was the Spathi + Homeworld, which has since been repaired.) + + + + (Initial version: Michael Martin, 10/10/02) diff --git a/doc/devel/sfx b/doc/devel/sfx new file mode 100644 index 0000000..67a29d5 --- /dev/null +++ b/doc/devel/sfx @@ -0,0 +1,202 @@ +The Ur-Quan Masters Sound Effects + +Path/File/Duplicates Description +=========================== ============================================================ +androsyn + androsyn/primary.wav Molecular acid (bubble sounds) + androsyn/secondary.wav Blazer form (comet "burner") + +arilou + arilou/primary.wav Ventral auto-aiming laser (yellow laser) + (lastbat/primary.wav) + arilou/secondary.wav Shortrange hyperdriver (transporter) + (lastbat/secondary.wav) + +blackurq + blackurq/fightret.wav not used + (urquan/fighter_get.wav) + blackurq/fightzip.wav not used + (ipanims/land_sht.wav) + (urquan/fighter_laser.wav) + blackurq/primary.wav Spinning blade + blackurq/secondary.wav F.R.I.E.D. Emitter plasma + +chenjesu + chenjesu/dogibark.wav D.O.G.I. hit (kind of "space" dog bark) + chenjesu/dogidie.wav D.O.G.I. dies (kind of "space" dog whine/yelp) + chenjesu/primary.wav Photon crystal shard firing + chenjesu/secondary.wav D.O.G.I. launching, low humming + chenjesu/sharpnel.wav Photon crystal shard explode (sharp sound) + +chmmr + chmmr/primary.wav Terawatt Laser (sharp "crystal" phaser beam) + chmmr/secondary.wav Tractor beam hum (cut resonance) + +druuge + druuge/primary.wav High-recoil cannon (a bit like shotgun) + (orz/primary.wav) + druuge/secondary.wav "Aarrghf" sacrifice scream + +human + human/primary.wav Nuclear warhead (rocket) + human/secondary.wav Point defence laser shot (white laser) + +ilwarth + ilwarth/cloak.wav Cloacking hum (quite bassy) + ilwarth/primary.wav Hellfire (flame thrower) + ilwarth/uncloak.wav Decloacking hum (less bassy, and sounds a bit like reversed clock.wav) + +ipanims + ipanims/land_awa.wav Lander takes of from the planet surface + ipanims/land_bit.wav Lander gets bitten by bio (teeth clank) + (vux/limpet_bite.wav) + ipanims/land_can.wav Bio canned by stun shot (weird sound) + ipanims/land_die.wav Lander explodes (long explosion) + (lbm/shipdies.wav) + ipanims/land_ful.wav Lander cargo hold full, cannot pick up ("burp") + ipanims/land_get.wav Lander picks up item/mineral (sounds like somone sucking) + ipanims/land_hit.wav Lander gets hit by something (snappy sound) + ipanims/land_hot.wav Firelava hot hum on planet surface + (thradd/secondary.wav) + ipanims/land_hrt.wav Lander crew dies (just "ugh" human sound) + ipanims/land_lau.wav Lander launching + (mmrnmhrm/primaryy.wav) + ipanims/land_lig.wav Lightning on planet surface + ipanims/land_qua.wav Earthquake on planet surface + ipanims/land_sht.wav Lander blaster shot + (urquan/fighter_laser.wav) + (blackurq/fightzip.wav) + +lastbat + lastbat/primary.wav not used + (arilou/primary.wav) + lastbat/secondary.wav not used + (arilou/secondary.wav) + +lbm + lbm/boom1.wav Tiny hit to planet/asteroid on melee (same sound, but higher pitch as ipanims/land_hit.wav) + ((ipanims/land_hit.wav)) + lbm/boom23.wav Small hit to planet/asteroid on melee + lbm/boom45.wav Larger hit to planet/asteroid on melee + lbm/boom67.wav Big hit/explosion to planet/asteroid on melee + lbm/getcrew.wav Get crew back to ship (Syreen called crew) (notes: should be in syreen/ ?) + lbm/menusnd01.wav Enter menu item + lbm/menusnd02.wav Select menu item + lbm/menusnd03.wav Cannot do (cancel) menu item (same as sis_ship/secondary.wav, but with echo) + lbm/menusnd04.wav Use device + (yehat/secondary.wav) + lbm/shipdies.wav Ship explosion (long explosion) + (ipanims/land_die.wav) + +melnorme + melnorme/primary.wav Confusion Ray (same as melnorme/secondary.wav, but reversed and one octave higher) + melnorme/secondary.wav Powerblaster (synth bass slap a like) + +mmrnmhrm + mmrnmhrm/primaryx.wav Laser cannon (sharp red laser beam) + mmrnmhrm/primaryy.wav Rocket launcher + (ipanims/land_lau.wav) + mmrnmhrm/secondary.wav Transformer + +mycon + mycon/primary.wav Plasma (long sound) + mycon/secondary.wav Crew regeneration (strange howling) + +orz + orz/argh.wav High pitched "Argh" + orz/intruder.wav Echoed and reverbed "Intruder" + orz/primary.wav Howitzer cannon + (druuge/primary.wav) + orz/secondary.wav "Go!" + orz/zap.wav Pulse cannon zap + +pkunk + pkunk/insult01.wav "Baby" + pkunk/insult02.wav "Dou-Dou" + pkunk/insult03.wav "Fool" + pkunk/insult04.wav "Idiot" + pkunk/insult05.wav "Jerk" + pkunk/insult06.wav "Looser" + pkunk/insult07.wav "Moron" + pkunk/insult08.wav "Nerd" + pkunk/insult09.wav "Nitwit" + pkunk/insult10.wav "Stupid" + pkunk/insult11.wav "Twig" + pkunk/insult12.wav "Whimp" + pkunk/insult13.wav "Worm" + pkunk/insult14.wav "Dummy" + pkunk/primary.wav Small blaster gun + (spathi/primary.wav) + (zoqfot/primary.wav) + pkunk/rebirth.wav Short piece of Handel played on Pkunk resurrection + +shofixti + shofixti/primary.wav Blaster gun + (thradd/primary.wav) + shofixti/secondary.wav Self-destruct, explosion and "ayeee!" yell + +sis_ship + sis_ship/primary.wav Precursors gun + sis_ship/secondary.wav Cancel sound, almost the same as lbm/menusnd03.wav, but no delay echo + (spathi/secondary.wav) + +slyland + slyland/primary.wav Electric discharger (kind of lightning) + slyland/secondary.wav Robotic "Energize" + +spathi + spathi/primary.wav Small blaster gun + (pkunk/primary.wav) + (zoqfot/primary.wav) + spathi/secondary.wav Rear launcher + (sis_ship/secondary.wav) + +supox + supox/primary.wav Sprout Gun + +syreen + syreen/primary.wav Partical Beam Stiletto + syreen/secondary.wav Syreen call + +thradd + thradd/primary.wav Blaster gun + (shofixti/primary.wav) + thradd/secondary.wav Afterburner + (ipanims/land_hot.wav) + +umgah + umgah/primary.wav Antimatter (like shaver) + umgah/secondary.wav Retro Propulsion (Zap sound) + +urquan + urquan/fighter_get.wav Fighter returning (a bit like end of tincan hit reversed) + (blackurq/fightret.wav) + urquan/fighter_laser.wav Fighter laser + (ipanims/land_sht.wav) + (blackurq/fightzip.wav) + urquan/primary.wav Photon torpedo (Star Trek sound) + urquan/secondary.wav Low pitched voice "Launch fighters" + +utwig + utwig/primary.wav Wide area guns (Low humming) + utwig/secondary.wav Battery (sounds a bit like reversed water drops) + utwig/shieldbattgain.wav Battery gain (sounds a bit like reversed water drops, plus some hum) + +vux + vux/limpet_bite.wav Limpet attaching to ship hull + (ipanims/land_bit.wav) + vux/primary.wav Gigawatt laser (beam sound) + vux/secondary.wav Limpet launch (reversed *plup* sound) + +yehat + yehat/primary.wav Rapid fire pulse cannon + yehat/secondary.wav Shield generator + (lbm/mainmenu04.wav) + +zoqfot + zoqfot/primary.wav Antimatter spray gun + (spathi/primary.wav) + (pkunk/primary.wav) + zoqfot/secondary.wav Plasma injector tongue ("yak" voice) + + diff --git a/doc/devel/statefiles b/doc/devel/statefiles new file mode 100644 index 0000000..3007bdf --- /dev/null +++ b/doc/devel/statefiles @@ -0,0 +1,123 @@ + Ur-Quan Masters State Files + --------------------------- + +Statefiles are a legacy component of the UQM runtime and savegame +format. They represent largish (10-64KB) chunks of semi-structured +data that the engine used to keep on disk during gameplay, checking +and updating it as needed. These files were then dumped into and +restored from save files in a compressed form. + +In UQM as it exists now (0.7), these files exist as expandable memory +arrays that are consulted as if they were files. UQM 0.8 will change +the savegame format to remove the compression (64K just isn't much +anymore) and put more structure to the data within. The statefile +abstraction itself is not guaranteed to be retained, and indeed core +team considers it kind of horrible and would like to destroy it. + +There are three state files. + + STARINFO_FILE aka "starinfo.dat" + -------------------------------- + +This is probably the most reasonable of the three. It keeps track of +which star systems you have visited, and which mineral deposits and +interesting life forms and gadgets you have harvested from the worlds +therein. + +The file begins with one DWORD for every star system in the +game. (There are 502 star systems, defined in a gigantic array in +starmap_array in plandata.c). The DWORD is 0 if the star system is +unvisited. It is otherwise an absolute offset within the state file. + +Generally speaking, UQM star systems are procedurally generated with a +PRNG and various properties of the star including its type and +location. Thus, the information in starmap.c is sufficient to provide +an accounting of the number and quality of worlds in any given +system. Each world can have up to 32 each of mineral deposits, energy +signatures, or life forms. Thus, each world, in order, in the system +will be listed at its offset with three DWORDS, representing mineral, +energy, and biological entities respectively. Captured entities have a +1 bit set. + +With a little over 3,800 visitable celestial bodies, this state file +is capped at a little under 50 KB. + + RANDGRPINFO_FILE aka "randgrp.dat" + ---------------------------------- + +This is a "battle group file" - it tracks the information regarding +groups of ships that you can encounter in interplanetary space. This +file gives the location information for all ships in the last solar +system you visited, and it tracks the fleet composition, health, &c +for ships randomly generated due to visiting a solar system in some +species's sphere of influence. Random battle groups are reset after a +week in HyperSpace or upon arrival in some other star system. + +The data structures, and the reader/writer functions for them, are +primarily defined in grpinfo.c. + +The RANDGRPINFO file starts with a GROUP_HEADER struct, specifying +which star this information is for, when the data expires, and then 65 +offsets into the file. This is a *one-indexed array* for +randomly-generated groups. + +This is because the offset for group zero points to an entirely +different data structure: the "Group List". This gives the starmap +depiction and location on the Interplanetary map of every battle group +in the system, whether it is randomly generated or pre-defined. This +comprises two bytes (the ID of the most recently encountered group, +and then the number of groups), followed by a series of 17-byte chunks +representing battle groups. These are a byte indicating the race +identifier of the fleet (battle groups can be mixed-composition, but +only one ship appears on the map at a time; this specifies that) +followed by 16 bytes that represent an IP_GROUP structure. See the +Read/WriteIpGroup functions in gengrp.c for the exact layout in the +virtual file. There's a lot of wasted space there, a legacy of the +time when these files were actually structure dumps on 32-bit machines +with very specific memory layouts. + +The offsets that are not Group Zero have a similar layout, interpreted +differently. Each of these represents a single battle group. It +retains the two-byte prologue, the second of which specifies the +number of 17-byte chunks to follow. The first byte here is the +displayed race identifier, again, and then each 17-byte chunk is that +ship's particular race ID followed by a 16-byte representation of a +SHIP_FRAGMENT. + +There are no requirements about order of layout or total size of this +file; the only requirement is that there is a GROUP_HEADER at offset +zero and that the extents described in the valid offsets do not +overlap. + + DEFGRPINFO_FILE aka "defgrp.dat" + -------------------------------- + +This is a random-access scratch space for battle groups that are +deliberately placed by the plot. There's one GROUP_HEADER in this +file, somewhere, for each star system that has ever had predefined +ships and that the player has visited. There is *no guarantee of any +kind* as to where they are, a priori. + +This information instead lives within the game state array, a +155-byte-long bitfield that is mostly used for storing plot events and +event flags. 32-bit values within this array store the relevant +offsets for their fleets, or a 0 if they have not yet been +encountered. In vanilla UQM, there are 14 of these values, +corresponding to the Ur-Quan Probe, the Zoq-Fot-Pik scout, the +Shofixti Survivor, the Unzervalt Guardian, the Sa-Matra, and the nine +Melnorme traders in TrueSpace. Each of these has a corresponding entry +in the game state array that ends in _OFFS0. (Due to the +implementation of GET_GAME_STATE, these values actually are stored as +four eight-bit values each, but this can be ignored pretty much +everywhere but the definition of the states themselves). + +If one of these offsets is non-zero, then that offset in the +DEFGRPINFO_FILE will have a SHIP_FRAGMENT-based group definition in +the same format as the ones in RANDGRPINFO_FILE. + +The Game State array uses 0 as a special value to mean "this +predefined battle group has not yet been spawned." Because of that, 0 +is not a legal offset to place a GROUP_HEADER. To ensure that no +GROUP_HEADER is placed there, a zero is written to the first byte of +the file. That way, the first defined group (which, for vanilla UQM, +will always be the Ur-Quan Probe) thus begins at offset 1. diff --git a/doc/devel/strtab b/doc/devel/strtab new file mode 100644 index 0000000..11170c2 --- /dev/null +++ b/doc/devel/strtab @@ -0,0 +1,76 @@ +This is the format for resources of type STRTAB. It contains a number of +items of unspecified data (not necessarilly strings). +This is used for game strings (extension .txt), colour tables (.ct), +colour translation tables (.xlt), and sound-effect tables (.snd) + +Everything is stored MSB first unless otherwise specified. + +position length meaning + 4 0xffffffff if the file is uncompressed. + Otherwise, the file is compressed. When uncompressed, the + file complies with the rest of the format as described + below. + 2 Unused in file, always 0x0000 + 2 number of items in the file (StringCount) + +Followed by: + In file: + 4 Placeholder, always 0x00000000 + numitems times: + 4 length of string + In memory: + numitems times: + 4 offset from &StringCount to the string + followed by: + 4 offset from &StringCount until one char past the end + of the last string. + +For .ct files an item is as follows (new 256x24bit format): + 1 Index of first clut in this item. + 1 Index of last clut in this item. + For each clut: + 256 palette entries: + 1 red value + 1 green value + 1 blue value + +For old .ct files an item is as follows (obsoleted by new 256x24bit format): + 1 Index of first clut in this item. + 1 Index of last clut in this item. + For each clut: + 32 palette entries: + 2 bits 0-4: blue value + bits 5-9: green value + bits 10-14: red value + bit 15: specifies the interpolation mode for 3DO scaling + (is ignored now) +The full palette contains 256 values, which are the original 32 values + multiplied by 1 to 8. + + +For .ct files (planet surface version; in ipanims) an item is as follows: + 1 Index of first color in this colortab. + 1 Index of last color in this colortab. + Then for each color (6 bits per channel): + 1 bits 0-5: red value + 1 bits 0-5: green value + 1 bits 0-5: blue value +The planet surface palette files were probably copied verbatim from DOS version +and left alone because they do no exactly fit into the whole CLUT system. + +For .xlt files (planet surface; in ipanims) an item is as follows: + 2*3 3 elevation levels (not used, probably informational) + 1*256 256 colormap indices each corresponding to a particular + elevation level 0..255; only colormap indices 128..255 + can be used currently because colormaps only define + colors 128..255 +The .xlt files combined with planet surface .ct files are used to select colors +for planet surface rendering. + + +For .snd files an item is as follows: + N-2 Signed, 8-bit, 1 channel PCM samples of the sound + effect, where N = (length of string) + 2 Sampling frequency of the sound, *LSB first* + (the frequencies themselves seem to be remnants of + the DOS version) diff --git a/doc/devel/threads b/doc/devel/threads new file mode 100644 index 0000000..5d1d65b --- /dev/null +++ b/doc/devel/threads @@ -0,0 +1,165 @@ +The UQM Threading and Synchronization library + +This document describes the function and API for the many threading and +synchronization routines that UQM uses. People attempting to port this +to thread systems that aren't covered by SDL (such as OS 9, for +instance) will find the necessary API descriptions here. + +#defines + +NAMED_SYNCHRO: When #defined, all synchronization objects are named. +This should be kept on all the time, at least until 1.0. + +TRACK_CONTENTION: implies NAMED_SYNCHRO. Spits out status messages +whenever a thread goes to sleep because of an object matching +TRACK_CONTENTION_CLASSES. + +TRACK_CONTENTION_CLASSES: This is an ORring of enums defined in +threadlib.h. + +Constructs +---------- + +The operation of each construct is given; these operations map to the +API in fairly straightforward ways. + +The locking constructs have an argument called "sync_class"; this +indicates which value must be defined in TRACK_CONTENTION_CLASSES to +see reports from this object. Valid values are SYNC_CLASS_TOPLEVEL +for game logic synchronizers, SYNC_CLASS_AUDIO and SYNC_CLASS_VIDEO +for audio and video systems, and SYNC_CLASS_RESOURCE for low-level +resource allocators like memory systems. + +- Task + +This is the construct that the UQM game logic sees. In our +multithreaded code tasks map directly to threads. A task is +"assigned" to be started. One of its arguments demands that a stack +size be specified; UQM ignores this. + +Tasks can voluntarily yield their timeslice by calling TaskSwitch(). +This is mandatory inside busywait loops; otherwise priority inversion +problems surface under BSD and even on other systems it causes undue +CPU utilization. + +Tasks have "states" that can be read or modified by various other +threads. The only state that is ever checked in the UQM code is +TASK_EXIT, which is set when the task needs to be shut down. + +Task functions themselves return an integer and take a void pointer +that can be cast to "Task". This is a reference to the Task itself, +and is used to check its own state and properly de-initialize itself. + +The last thing a Task function must do before exiting is call +FinishTask. + +If another thread wishes to terminate a Task, it can call +"ConcludeTask" upon it. ConcludeTask will wait for the Task to +recognize the TASK_EXIT state and exit; this can produce deadlocks if +the thread requestion the Task's termination is holding a resource +that the concluding Task needs. Program with care. + +API: +Task AssignTask (ThreadFunction task_func, SDWORD Stacksize, + const char *name); +DWORD Task_SetState (Task task, DWORD state_mask); +DWORD Task_ClearState (Task task, DWORD state_mask); +DWORD Task_ToggleState (Task task, DWORD state_mask); +DWORD Task_ReadState (Task task, DWORD state_mask); +void TaskSwitch (void); +void FinishTask (Task task); +void ConcludeTask (Task task); + + +- Thread + +A somewhat more powerful and low-level construct than the Task. +Threads carry a "ThreadLocal" data object with them - at present, this +is a single Semaphore used for signaling the thread when it wants to +sleep until some graphics have been rendered. Threads can be created +with arbitrary data passed as an argument (in the form of the void *), +and can request their own ThreadLocal object. Threads can also be put +to sleep for various amounts of time. Waiting on a thread permits one +to block a thread until another completes. + +API: +Thread CreateThread (ThreadFunction func, void *data, + SDWORD stackSize, const char *name); +void SleepThread (TimePeriod timePeriod); +void SleepThreadUntil (TimeCount wakeTime); +void TaskSwitch (void); +void WaitThread (Thread thread, int *status); + + +- Mutex + +The simplest form of lock. If a thread tries to lock a mutex, it will +sleep if the mutex is already locked, and awaken once the mutex +becomes available. A Mutex must be unlocked by the same thread that +locked it, and a thread must never lock a mutex it has already locked +(without unlocking it first). + +API: +Mutex CreateMutex (const char *name, DWORD syncClass); +void DestroyMutex (Mutex sem); +void LockMutex (Mutex sem); +void UnlockMutex (Mutex sem); + +- RecursiveMutex + +A somewhat more powerful version of the Mutex; this mutex may be +locked multiple times by the same thread, but then to truly release it +it must unlock it an equal number of times. The Draw Command Queue +(DCQ) is protected by a recursive mutex. (This construct is +occasionally called a "reentrant mutex.") + +API: +RecursiveMutex CreateRecursiveMutex (const char *name, + DWORD syncClass); +void DestroyRecursiveMutex (RecursiveMutex m); +void LockRecursiveMutex (RecursiveMutex m); +void UnlockRecursiveMutex (RecursiveMutex m); +int GetRecursiveMutexDepth (RecursiveMutex m); + +- Semaphore + +Semaphores superficially resemble Mutexes; they are "set" and +"cleared". An integer is associated with each semaphore. Clearing +the semaphore raises the value by one; setting it decreases it by one. +Attempting to set a semaphore that is at value 0 will sleep the thread +until the semaphore is cleared. + +Semaphores are used in the code to sleep until another thread is +finished doing something. They are used heavily by the FlushGraphics +code and the thread handling routines. A Task in the game is +dedicated to advancing the calendar when necessary; this task is put +to sleep by the clock semaphore when the game is paused, the player +goes into orbit or to the menu, or any of several other events that +act to suspend the game clock. + +API: +Semaphore CreateSemaphore (DWORD initial, const char *name, + DWORD syncClass); +void DestroySemaphore (Semaphore sem); +void SetSemaphore (Semaphore sem); +void ClearSemaphore (Semaphore sem); + +- CondVar + +If a thread waits on a condition variable, it will go to sleep until +some other thread tells that condition variable to signal a thread (or +broadcast to all threads) that are waiting upon that variable. Our +condition variables are weaker than the "standard" variables. +Condition variables are generally used in conjunction with mutexes, +but ours do not permit this synchronization and are only suitable for +use if the condition variable will broadcast periodically. UQM has a +condition variable associated with the DCQ that broadcasts whenever +the queue is empty. Threads that attempt to write to the DCQ when the +DCQ is full wait on this condition variable. + +API: +CondVar CreateCondVar (const char *name, DWORD syncClass); +void DestroyCondVar (CondVar); +void WaitCondVar (CondVar); +void SignalCondVar (CondVar); +void BroadcastCondVar (CondVar); diff --git a/doc/devel/timing b/doc/devel/timing new file mode 100644 index 0000000..99aa62e --- /dev/null +++ b/doc/devel/timing @@ -0,0 +1,66 @@ +1. Timing and Changes +--------------------- +The current UQM timer runs on a 120 ticks/second clock, defined by the +constant ONE_SECOND (in timelib.h). Theoretically, all code has been +updated to use this constant where needed, so the timer precision can +be increased to 1000, for example, to match the native SDL timer +resolution. + +The following functions and all variables and constants used with them +have been examined and patched where necessary. + +Functions that have something to do with time: + XFormColorMap + XFormPLUT + CycleColorMap + FadeMusic + SeedRandomNumbers + WaitForNoInput + GetTimeCounter + SleepThread + SleepThreadUntil + +Global vars: + GameClock + +Constants changed: + BATTLE_FRAME_RATE (element.h) + NUM_DELAYS (clock.c) + ACCELERATION_INCREMENT (gameinp.c) + IP_FRAME_RATE (solarsys.c) + +Constants added: + CLOCK_BASE_FRAMERATE (clock.c) + STEP_ACCEL_DELAY (pstarmap.c) + PLANET_SIDE_RATE (lander.c) + +All alien comm animation definitions (frame rates) were patched to take +ONE_SECOND into account. So if some animations start to bug all of a +sudden, you know where to look ;). + +The game-clock function SetGameClockRate() changed to use the rate +defined by CLOCK_BASE_FRAMERATE and does not use ONE_SECOND now (and is +not supposed to). + + +2. Possible Rate Changes +------------------------ +The PLANET_SIDE_RATE and IP_FRAME_RATE can be safely adjusted at this +time. The BATTLE_FRAME_RATE needs more work. + + +3. Battle rate +-------------- +The BATTLE_FRAME_RATE constant (currently 24 fps) can be adjusted only +after converting the rate counters for all ships used in melee. They +are expressed in frames and *must* take BATTLE_FRAME_RATE into account. + +They are: + ENERGY_WAIT + TURN_WAIT + THRUST_WAIT + WEAPON_WAIT + SPECIAL_WAIT + +There is probably more that needs to be done to make it work properly +with an altered BATTLE_FRAME_RATE. Expect more info to appear. diff --git a/doc/devel/versions b/doc/devel/versions new file mode 100644 index 0000000..4b3d36a --- /dev/null +++ b/doc/devel/versions @@ -0,0 +1,42 @@ +This file lists the Subversion repository numbers that coincide with +each release. You should be able to revert to any individual release +by doing a checkout of that version. It is also possible to check out +a tagged version of each major release, but this is deprecated. + +Major releases for versions 0.6.0 and before are identified by their +tags in the CVS tree and correspond to source-release packages; all +microversions are identified by the point at which uqmversion.h +changed. + +Version 0.1: Revision 240 +Version 0.2: Revision 847 +Version 0.21: Revision 816 +Version 0.22: Revision 913 +Version 0.23: Revision 994 +Version 0.24: Revision 1036 +Version 0.3: Revision 1208 +Version 0.31: Revision 1220 +Version 0.32: Revision 1330 +Version 0.33: Revision 1440 +Version 0.34: Revision 1619 +Version 0.4.0: Revision 1814 +Version 0.4.1: Revision 1931 +Version 0.4.2: Revision 2049 +Version 0.4.3: Revision 2160 +Version 0.4.4: Revision 2196 +Version 0.5.0: Revision 2250 +Version 0.5.1: Revision 2309 +Version 0.5.2: Revision 2392 +Version 0.5.3: Revision 2436 +Version 0.5.4: Revision 2463 +Version 0.6.0: Revision 2627 +Version 0.6.1: Revision 2652 +Version 0.6.2: Revision 2669 +Version 0.6.3: Revision 2828 +Version 0.6.4: Revision 2869 +Version 0.6.5: Revision 3110 +Version 0.6.6: Revision 3143 +Version 0.6.7: Revision 3276 +Version 0.6.8: Revision 3334 +Version 0.6.9: Revision 3537 +Version 0.7.0: Revision 3631 diff --git a/doc/devel/voiceeffects b/doc/devel/voiceeffects new file mode 100644 index 0000000..1d53e90 --- /dev/null +++ b/doc/devel/voiceeffects @@ -0,0 +1,20 @@ +Slylandro Probe
+---------------------------------------------------------------------------
+The voice of the Slylandro probe is "Bruce" from MacInTalk Pro. MacInTalk
+Pro requires a 68040 Mac, a Quadra or Performa, and System 7.3 minimum.
+Basilisk II emulator can do Quadra 900 well enough.
+
+The probe speech added to UQM was processed as follows:
+1) generated on Basilisk II v0.8.0.142 running System 7.5.3 Rev 2 on
+ Quadra 900. Words like "hundred" and "point" were mid-sentence to get
+ better intonation. Names of tens -- 20, 30, etc. -- were cut from number
+ phrases "twenty-five", "thirty-five", etc.
+2) captured at 44100 Hz
+3) post-processed with Audacity 1.3 beta; filters:
+ a) GVerb: room 40m, reverb time 0.1s, damping 0.85, input bandwidth 0.75,
+ dry signal +0dB, early reflection -22dB, trail level -30dB
+ b) Amplify: +2.5dB (depends on your capture level)
+ c) Bass boost: centered at 300 Hz, +4dB
+4) chopped up and exported at 11025 Hz
+
+
|